Merge from ray, minor conflicts
This commit is contained in:
		
						commit
						79ca83c95a
					
				|  | @ -86,14 +86,34 @@ class Site: | ||||||
|         self.aux_window   = node.getAttribute("aux_window") |         self.aux_window   = node.getAttribute("aux_window") | ||||||
|         self.font         = node.getAttribute("font") |         self.font         = node.getAttribute("font") | ||||||
|         self.font_size    = node.getAttribute("font_size") |         self.font_size    = node.getAttribute("font_size") | ||||||
|         self.use_frames    = node.getAttribute("use_frames") |         self.use_frames   = node.getAttribute("use_frames") | ||||||
|         self.enabled      = fix_tf(node.getAttribute("enabled"), default = True) |         self.enabled      = fix_tf(node.getAttribute("enabled"), default = True) | ||||||
|  |         self.xpad         = node.getAttribute("xpad") | ||||||
|  |         self.ypad         = node.getAttribute("ypad") | ||||||
|         self.layout       = {} |         self.layout       = {} | ||||||
| 
 | 
 | ||||||
|         for layout_node in node.getElementsByTagName('layout'): |         for layout_node in node.getElementsByTagName('layout'): | ||||||
|             lo = Layout(layout_node) |             lo = Layout(layout_node) | ||||||
|             self.layout[lo.max] = lo |             self.layout[lo.max] = lo | ||||||
| 
 | 
 | ||||||
|  | #   Site defaults | ||||||
|  |         if self.xpad       == "": self.xpad = 1 | ||||||
|  |         else: self.xpad = int(self.xpad) | ||||||
|  | 
 | ||||||
|  |         if self.ypad       == "": self.ypad = 0 | ||||||
|  |         else: self.ypad = int(self.ypad) | ||||||
|  | 
 | ||||||
|  |         if self.font_size  == "": self.font_size = 7 | ||||||
|  |         else: self.font_size = int(self.font_size) | ||||||
|  | 
 | ||||||
|  |         if self.hudopacity == "": self.hudopacity = 1.0 | ||||||
|  |         else: self.hudopacity = float(self.hudopacity) | ||||||
|  | 
 | ||||||
|  |         if self.use_frames == "": self.use_frames = False | ||||||
|  |         if self.font       == "": self.font = "Sans"  | ||||||
|  |         if self.hudbgcolor == "": self.hudbgcolor = "000000" | ||||||
|  |         if self.hudfgcolor == "": self.hudfgcolor = "FFFFFF" | ||||||
|  | 
 | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|         temp = "Site = " + self.site_name + "\n" |         temp = "Site = " + self.site_name + "\n" | ||||||
|         for key in dir(self): |         for key in dir(self): | ||||||
|  | @ -119,9 +139,16 @@ class Stat: | ||||||
| class Game: | class Game: | ||||||
|     def __init__(self, node): |     def __init__(self, node): | ||||||
|         self.game_name = node.getAttribute("game_name") |         self.game_name = node.getAttribute("game_name") | ||||||
|         self.db        = node.getAttribute("db") |  | ||||||
|         self.rows      = int( node.getAttribute("rows") ) |         self.rows      = int( node.getAttribute("rows") ) | ||||||
|         self.cols      = int( node.getAttribute("cols") ) |         self.cols      = int( node.getAttribute("cols") ) | ||||||
|  |         self.xpad      = node.getAttribute("xpad") | ||||||
|  |         self.ypad      = node.getAttribute("ypad") | ||||||
|  | 
 | ||||||
|  | #    Defaults | ||||||
|  |         if self.xpad == "": self.xpad = 1 | ||||||
|  |         else: self.xpad = int(self.xpad) | ||||||
|  |         if self.ypad == "": self.ypad = 0 | ||||||
|  |         else: self.ypad = int(self.ypad) | ||||||
| 
 | 
 | ||||||
|         aux_text = node.getAttribute("aux") |         aux_text = node.getAttribute("aux") | ||||||
|         aux_list = aux_text.split(',') |         aux_list = aux_text.split(',') | ||||||
|  | @ -146,9 +173,10 @@ class Game: | ||||||
|              |              | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|         temp = "Game = " + self.game_name + "\n" |         temp = "Game = " + self.game_name + "\n" | ||||||
|         temp = temp + "    db = %s\n" % self.db |  | ||||||
|         temp = temp + "    rows = %d\n" % self.rows |         temp = temp + "    rows = %d\n" % self.rows | ||||||
|         temp = temp + "    cols = %d\n" % self.cols |         temp = temp + "    cols = %d\n" % self.cols | ||||||
|  |         temp = temp + "    xpad = %d\n" % self.xpad | ||||||
|  |         temp = temp + "    ypad = %d\n" % self.ypad | ||||||
|         temp = temp + "    aux = %s\n" % self.aux |         temp = temp + "    aux = %s\n" % self.aux | ||||||
|          |          | ||||||
|         for stat in self.stats.keys(): |         for stat in self.stats.keys(): | ||||||
|  | @ -633,6 +661,8 @@ class Config: | ||||||
|         parms["font"]         = self.supported_sites[site].font |         parms["font"]         = self.supported_sites[site].font | ||||||
|         parms["font_size"]    = self.supported_sites[site].font_size |         parms["font_size"]    = self.supported_sites[site].font_size | ||||||
|         parms["enabled"]      = self.supported_sites[site].enabled |         parms["enabled"]      = self.supported_sites[site].enabled | ||||||
|  |         parms["xpad"]         = self.supported_sites[site].xpad | ||||||
|  |         parms["ypad"]         = self.supported_sites[site].ypad | ||||||
|         return parms |         return parms | ||||||
| 
 | 
 | ||||||
|     def set_site_parameters(self, site_name, converter = None, decoder = None, |     def set_site_parameters(self, site_name, converter = None, decoder = None, | ||||||
|  | @ -683,9 +713,10 @@ class Config: | ||||||
|         param = {} |         param = {} | ||||||
|         if self.supported_games.has_key(name): |         if self.supported_games.has_key(name): | ||||||
|             param['game_name'] = self.supported_games[name].game_name |             param['game_name'] = self.supported_games[name].game_name | ||||||
|             param['db']        = self.supported_games[name].db |  | ||||||
|             param['rows']      = self.supported_games[name].rows |             param['rows']      = self.supported_games[name].rows | ||||||
|             param['cols']      = self.supported_games[name].cols |             param['cols']      = self.supported_games[name].cols | ||||||
|  |             param['xpad']      = self.supported_games[name].xpad | ||||||
|  |             param['ypad']      = self.supported_games[name].ypad | ||||||
|             param['aux']       = self.supported_games[name].aux |             param['aux']       = self.supported_games[name].aux | ||||||
|         return param |         return param | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -39,7 +39,8 @@ import SQL | ||||||
| import Card | import Card | ||||||
| 
 | 
 | ||||||
| class Database: | class Database: | ||||||
|     def __init__(self, c, db_name, game): |     def __init__(self, c, db_name = None, game = None, sql = None): # db_name and game not used any more | ||||||
|  |         print "\ncreating Database instance, sql =", sql | ||||||
|         self.fdb = fpdb_db.fpdb_db()   # sets self.fdb.db self.fdb.cursor and self.fdb.sql |         self.fdb = fpdb_db.fpdb_db()   # sets self.fdb.db self.fdb.cursor and self.fdb.sql | ||||||
|         self.fdb.do_connect(c) |         self.fdb.do_connect(c) | ||||||
|         self.connection = self.fdb.db |         self.connection = self.fdb.db | ||||||
|  | @ -48,7 +49,12 @@ class Database: | ||||||
|         self.import_options = c.get_import_parameters() |         self.import_options = c.get_import_parameters() | ||||||
|         self.type = db_params['db-type'] |         self.type = db_params['db-type'] | ||||||
|         self.backend = db_params['db-backend'] |         self.backend = db_params['db-backend'] | ||||||
|         self.sql = SQL.Sql(game = game, type = self.type, db_server = db_params['db-server']) |         self.db_server = db_params['db-server'] | ||||||
|  |         # where possible avoid creating new SQL instance by using the global one passed in | ||||||
|  |         if sql == None: | ||||||
|  |             self.sql = SQL.Sql(type = self.type, db_server = db_params['db-server']) | ||||||
|  |         else: | ||||||
|  |             self.sql = sql | ||||||
|         self.connection.rollback() |         self.connection.rollback() | ||||||
|          |          | ||||||
|                                    # To add to config: |                                    # To add to config: | ||||||
|  | @ -81,6 +87,8 @@ class Database: | ||||||
|         #row = cur.fetchone() |         #row = cur.fetchone() | ||||||
|         self.saveActions = False if self.import_options['saveActions'] == False else True |         self.saveActions = False if self.import_options['saveActions'] == False else True | ||||||
| 
 | 
 | ||||||
|  |     def do_connect(self, c): | ||||||
|  |         self.fdb.do_connect(c) | ||||||
| 
 | 
 | ||||||
|     def commit(self): |     def commit(self): | ||||||
|         self.fdb.db.commit() |         self.fdb.db.commit() | ||||||
|  | @ -88,6 +96,19 @@ class Database: | ||||||
|     def close_connection(self): |     def close_connection(self): | ||||||
|         self.connection.close() |         self.connection.close() | ||||||
| 
 | 
 | ||||||
|  |     def disconnect(self, due_to_error=False): | ||||||
|  |         """Disconnects the DB (rolls back if param is true, otherwise commits""" | ||||||
|  |         self.fdb.disconnect(due_to_error) | ||||||
|  |      | ||||||
|  |     def reconnect(self, due_to_error=False): | ||||||
|  |         """Reconnects the DB""" | ||||||
|  |         self.fdb.reconnect(due_to_error=False) | ||||||
|  |      | ||||||
|  |     def get_backend_name(self): | ||||||
|  |         """Reconnects the DB""" | ||||||
|  |         return self.fdb.get_backend_name() | ||||||
|  |          | ||||||
|  | 
 | ||||||
|     def get_table_name(self, hand_id): |     def get_table_name(self, hand_id): | ||||||
|         c = self.connection.cursor() |         c = self.connection.cursor() | ||||||
|         c.execute(self.sql.query['get_table_name'], (hand_id, )) |         c.execute(self.sql.query['get_table_name'], (hand_id, )) | ||||||
|  | @ -138,12 +159,8 @@ class Database: | ||||||
|         cards = {} |         cards = {} | ||||||
|         c = self.connection.cursor() |         c = self.connection.cursor() | ||||||
|         c.execute(self.sql.query['get_common_cards'], [hand]) |         c.execute(self.sql.query['get_common_cards'], [hand]) | ||||||
|         colnames = [desc[0] for desc in c.description] | #        row = c.fetchone() | ||||||
|         for row in c.fetchall(): |         cards['common'] = c.fetchone() | ||||||
|             s_dict = {} |  | ||||||
|             for name, val in zip(colnames, row): |  | ||||||
|                 s_dict[name] = val |  | ||||||
|             cards['common'] = (self.convert_cards(s_dict)) |  | ||||||
|         return cards |         return cards | ||||||
| 
 | 
 | ||||||
|     def convert_cards(self, d): |     def convert_cards(self, d): | ||||||
|  | @ -285,7 +302,8 @@ class Database: | ||||||
|         fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) |         fpdb_simple.fillCardArrays(len(names), base, category, card_values, card_suits) | ||||||
| 
 | 
 | ||||||
|         hands_id = fpdb_simple.storeHands(self.backend, db, cursor, site_hand_no, gametype_id |         hands_id = fpdb_simple.storeHands(self.backend, db, cursor, site_hand_no, gametype_id | ||||||
|                                        ,hand_start_time, names, tableName, maxSeats, hudImportData) |                                        ,hand_start_time, names, tableName, maxSeats, hudImportData | ||||||
|  |                                        ,(None, None, None, None, None), (None, None, None, None, None)) | ||||||
| 
 | 
 | ||||||
|         #print "before calling store_hands_players_stud, antes:", antes |         #print "before calling store_hands_players_stud, antes:", antes | ||||||
|         hands_players_ids = fpdb_simple.store_hands_players_stud(self.backend, db, cursor, hands_id, player_ids |         hands_players_ids = fpdb_simple.store_hands_players_stud(self.backend, db, cursor, hands_id, player_ids | ||||||
|  | @ -326,7 +344,6 @@ class Database: | ||||||
|         if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': |         if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': | ||||||
|             fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) |             fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) | ||||||
|         t5 = time() |         t5 = time() | ||||||
|         fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) |  | ||||||
|         t6 = time() |         t6 = time() | ||||||
|         if self.saveActions: |         if self.saveActions: | ||||||
|             fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) |             fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) | ||||||
|  | @ -361,8 +378,6 @@ class Database: | ||||||
|         if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': |         if 'updateHudCache' not in settings or settings['updateHudCache'] != 'drop': | ||||||
|             fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) |             fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) | ||||||
| 
 | 
 | ||||||
|         fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) |  | ||||||
| 
 |  | ||||||
|         if self.saveActions: |         if self.saveActions: | ||||||
|             fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) |             fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) | ||||||
|         return hands_id |         return hands_id | ||||||
|  |  | ||||||
|  | @ -30,12 +30,11 @@ import fpdb_db | ||||||
| import FpdbSQLQueries | import FpdbSQLQueries | ||||||
| 
 | 
 | ||||||
| class Filters(threading.Thread): | class Filters(threading.Thread): | ||||||
|     def __init__(self, db, settings, config, qdict, display = {},debug=True): |     def __init__(self, db, config, qdict, display = {}, debug=True): | ||||||
|         self.debug=debug |         self.debug=debug | ||||||
|         #print "start of GraphViewer constructor" |         #print "start of GraphViewer constructor" | ||||||
|         self.db=db |         self.db=db | ||||||
|         self.cursor=db.cursor |         self.cursor=db.cursor | ||||||
|         self.settings=settings |  | ||||||
|         self.sql=qdict |         self.sql=qdict | ||||||
|         self.conf = config |         self.conf = config | ||||||
|         self.display = display |         self.display = display | ||||||
|  | @ -235,7 +234,7 @@ class Filters(threading.Thread): | ||||||
| 
 | 
 | ||||||
|     def __set_hero_name(self, w, site): |     def __set_hero_name(self, w, site): | ||||||
|         self.heroes[site] = w.get_text() |         self.heroes[site] = w.get_text() | ||||||
| #        print "DEBUG: settings heroes[%s]: %s"%(site, self.heroes[site]) | #        print "DEBUG: setting heroes[%s]: %s"%(site, self.heroes[site]) | ||||||
| 
 | 
 | ||||||
|     def createSiteLine(self, hbox, site): |     def createSiteLine(self, hbox, site): | ||||||
|         cb = gtk.CheckButton(site) |         cb = gtk.CheckButton(site) | ||||||
|  | @ -556,23 +555,12 @@ def main(argv=None): | ||||||
|     config = Configuration.Config() |     config = Configuration.Config() | ||||||
|     db = None |     db = None | ||||||
|      |      | ||||||
|     settings = {} |  | ||||||
| 
 |  | ||||||
|     settings.update(config.get_db_parameters()) |  | ||||||
|     settings.update(config.get_tv_parameters()) |  | ||||||
|     settings.update(config.get_import_parameters()) |  | ||||||
|     settings.update(config.get_default_paths()) |  | ||||||
| 
 |  | ||||||
|     db = fpdb_db.fpdb_db() |     db = fpdb_db.fpdb_db() | ||||||
|     db.connect(settings['db-backend'], |     db.do_connect(config) | ||||||
|                settings['db-host'], |  | ||||||
|                settings['db-databaseName'], |  | ||||||
|                settings['db-user'], |  | ||||||
|                settings['db-password']) |  | ||||||
| 
 | 
 | ||||||
|     qdict = FpdbSQLQueries.FpdbSQLQueries(db.get_backend_name()) |     qdict = FpdbSQLQueries.FpdbSQLQueries(db.get_backend_name()) | ||||||
| 
 | 
 | ||||||
|     i = Filters(db, settings, config, qdict) |     i = Filters(db, config, qdict) | ||||||
|     main_window = gtk.Window() |     main_window = gtk.Window() | ||||||
|     main_window.connect('destroy', destroy) |     main_window.connect('destroy', destroy) | ||||||
|     main_window.add(i.get_vbox()) |     main_window.add(i.get_vbox()) | ||||||
|  |  | ||||||
|  | @ -282,43 +282,6 @@ class FpdbSQLQueries: | ||||||
|                             FOREIGN KEY(gametypeId) REFERENCES Gametypes(id) ON DELETE CASCADE)""" |                             FOREIGN KEY(gametypeId) REFERENCES Gametypes(id) ON DELETE CASCADE)""" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         ################################ |  | ||||||
|         # Create BoardCards |  | ||||||
|         ################################ |  | ||||||
| 
 |  | ||||||
|         if(self.dbname == 'MySQL InnoDB'): |  | ||||||
|             self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( |  | ||||||
|                             id BIGINT UNSIGNED AUTO_INCREMENT NOT NULL, PRIMARY KEY (id), |  | ||||||
|                             handId BIGINT UNSIGNED NOT NULL, FOREIGN KEY (handId) REFERENCES Hands(id), |  | ||||||
|                             card1Value smallint NOT NULL, |  | ||||||
|                             card1Suit char(1) NOT NULL, |  | ||||||
|                             card2Value smallint NOT NULL, |  | ||||||
|                             card2Suit char(1) NOT NULL, |  | ||||||
|                             card3Value smallint NOT NULL, |  | ||||||
|                             card3Suit char(1) NOT NULL, |  | ||||||
|                             card4Value smallint NOT NULL, |  | ||||||
|                             card4Suit char(1) NOT NULL, |  | ||||||
|                             card5Value smallint NOT NULL, |  | ||||||
|                             card5Suit char(1) NOT NULL) |  | ||||||
|                         ENGINE=INNODB"""  |  | ||||||
|         elif(self.dbname == 'PostgreSQL'): |  | ||||||
|             self.query['createBoardCardsTable'] = """CREATE TABLE BoardCards ( |  | ||||||
|                         id BIGSERIAL, PRIMARY KEY (id), |  | ||||||
|                         handId BIGINT, FOREIGN KEY (handId) REFERENCES Hands(id), |  | ||||||
|                         card1Value smallint, |  | ||||||
|                         card1Suit char(1), |  | ||||||
|                         card2Value smallint, |  | ||||||
|                         card2Suit char(1), |  | ||||||
|                         card3Value smallint, |  | ||||||
|                         card3Suit char(1), |  | ||||||
|                         card4Value smallint, |  | ||||||
|                         card4Suit char(1), |  | ||||||
|                         card5Value smallint, |  | ||||||
|                         card5Suit char(1))""" |  | ||||||
|         elif(self.dbname == 'SQLite'): |  | ||||||
|             self.query['createBoardCardsTable'] = """ """ |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         ################################ |         ################################ | ||||||
|         # Create TourneyTypes |         # Create TourneyTypes | ||||||
|         ################################ |         ################################ | ||||||
|  | @ -1598,136 +1561,6 @@ class FpdbSQLQueries: | ||||||
|         elif(self.dbname == 'SQLite'): |         elif(self.dbname == 'SQLite'): | ||||||
|             self.query['playerStatsByPosition'] = """ """ |             self.query['playerStatsByPosition'] = """ """ | ||||||
| 
 | 
 | ||||||
|         if(self.dbname == 'MySQL InnoDB'): |  | ||||||
|             self.query['playerStatsByPositionAndHoleCards'] = """ |  | ||||||
|                 SELECT  |  | ||||||
|                       concat(upper(stats.limitType), ' ' |  | ||||||
|                             ,concat(upper(substring(stats.category,1,1)),substring(stats.category,2) ), ' ' |  | ||||||
|                             ,stats.name, ' $' |  | ||||||
|                             ,cast(trim(leading ' ' from |  | ||||||
|                                   case when stats.bigBlind < 100 then format(stats.bigBlind/100.0,2) |  | ||||||
|                                       else format(stats.bigBlind/100.0,0) |  | ||||||
|                                   end ) as char) |  | ||||||
|                             )                                                      AS Game |  | ||||||
|                      ,case when stats.PlPosition = -2 then 'BB' |  | ||||||
|                            when stats.PlPosition = -1 then 'SB' |  | ||||||
|                            when stats.PlPosition =  0 then 'Btn' |  | ||||||
|                            when stats.PlPosition =  1 then 'CO' |  | ||||||
|                            when stats.PlPosition =  2 then 'MP' |  | ||||||
|                            when stats.PlPosition =  5 then 'EP' |  | ||||||
|                            else '??' |  | ||||||
|                       end                                                          AS PlPosition |  | ||||||
|                      /*,stats.n*/,hprof2.n |  | ||||||
|                      /*,stats.vpip*/,0 |  | ||||||
|                      /*,stats.pfr*/,0 |  | ||||||
|                      /*,stats.saw_f*/,0 |  | ||||||
|                      /*,stats.sawsd*/,0 |  | ||||||
|                      /*,stats.wtsdwsf*/,0 |  | ||||||
|                      /*,stats.wmsd*/,0 |  | ||||||
|                      /*,stats.FlAFq*/,0 |  | ||||||
|                      /*,stats.TuAFq*/,0 |  | ||||||
|                      /*,stats.RvAFq*/,0 |  | ||||||
|                      /*,stats.PoFAFq*/,0 |  | ||||||
|                      /* if you have handsactions data the next 3 fields should give same answer as |  | ||||||
|                         following 3 commented out fields */ |  | ||||||
|                      /*,stats.Net |  | ||||||
|                      ,stats.BBper100 |  | ||||||
|                      ,stats.Profitperhand*/ |  | ||||||
|                      ,format(hprof2.sum_profit/100.0,2)                          AS Net |  | ||||||
|                        /*,format((hprof2.sum_profit/(stats.bigBlind+0.0)) / (stats.n/100.0),2)*/,0 |  | ||||||
|                                                                                    AS BBlPer100 |  | ||||||
|                        ,hprof2.profitperhand                                       AS Profitperhand |  | ||||||
|                      ,format(hprof2.variance,2)                                    AS Variance |  | ||||||
|                 FROM |  | ||||||
|                     (select /* stats from hudcache */ |  | ||||||
|                             gt.base |  | ||||||
|                            ,gt.category |  | ||||||
|                            ,upper(gt.limitType) as limitType |  | ||||||
|                            ,s.name |  | ||||||
|                            ,gt.bigBlind |  | ||||||
|                            ,hc.gametypeId |  | ||||||
|                            ,case when hc.position = 'B' then -2 |  | ||||||
|                                  when hc.position = 'S' then -1 |  | ||||||
|                                  when hc.position = 'D' then  0 |  | ||||||
|                                  when hc.position = 'C' then  1 |  | ||||||
|                                  when hc.position = 'M' then  2 |  | ||||||
|                                  when hc.position = 'E' then  5 |  | ||||||
|                                  else 9 |  | ||||||
|                             end                                                             as PlPosition |  | ||||||
|                            ,sum(HDs)                                                        AS n |  | ||||||
|                            ,format(100.0*sum(street0VPI)/sum(HDs),1)                 AS vpip |  | ||||||
|                            ,format(100.0*sum(street0Aggr)/sum(HDs),1)                AS pfr |  | ||||||
|                            ,format(100.0*sum(street1Seen)/sum(HDs),1)                AS saw_f |  | ||||||
|                            ,format(100.0*sum(sawShowdown)/sum(HDs),1)                AS sawsd |  | ||||||
|                            ,case when sum(street1Seen) = 0 then '-' |  | ||||||
|                                 else format(100.0*sum(sawShowdown)/sum(street1Seen),1) |  | ||||||
|                             end                                                             AS wtsdwsf |  | ||||||
|                            ,case when sum(sawShowdown) = 0 then '-' |  | ||||||
|                            end                                                             AS wtsdwsf |  | ||||||
|                            ,case when sum(sawShowdown) = 0 then '-' |  | ||||||
|                                  else format(100.0*sum(wonAtSD)/sum(sawShowdown),1) |  | ||||||
|                             end                                                             AS wmsd |  | ||||||
|                            ,case when sum(street1Seen) = 0 then '-' |  | ||||||
|                                  else format(100.0*sum(street1Aggr)/sum(street1Seen),1) |  | ||||||
|                             end                                                             AS FlAFq |  | ||||||
|                            ,case when sum(street2Seen) = 0 then '-' |  | ||||||
|                                  else format(100.0*sum(street2Aggr)/sum(street2Seen),1) |  | ||||||
|                             end                                                             AS TuAFq |  | ||||||
|                            ,case when sum(street3Seen) = 0 then '-' |  | ||||||
|                                 else format(100.0*sum(street3Aggr)/sum(street3Seen),1) |  | ||||||
|                             end                                                             AS RvAFq |  | ||||||
|                            ,case when sum(street1Seen)+sum(street2Seen)+sum(street3Seen) = 0 then '-' |  | ||||||
|                                 else format(100.0*(sum(street1Aggr)+sum(street2Aggr)+sum(street3Aggr)) |  | ||||||
|                                          /(sum(street1Seen)+sum(street2Seen)+sum(street3Seen)),1) |  | ||||||
|                             end                                                             AS PoFAFq |  | ||||||
|                            ,format(sum(totalProfit)/100.0,2)                                AS Net |  | ||||||
|                            ,format((sum(totalProfit)/(gt.bigBlind+0.0)) / (sum(HDs)/100.0),2) |  | ||||||
|                                                                                             AS BBper100 |  | ||||||
|                            ,format( (sum(totalProfit)/100.0) / sum(HDs), 4)                 AS Profitperhand |  | ||||||
|                      from Gametypes gt |  | ||||||
|                           inner join Sites s on s.Id = gt.siteId |  | ||||||
|                           inner join HudCache hc on hc.gameTypeId = gt.Id |  | ||||||
|                      where hc.playerId in <player_test> |  | ||||||
|                                                 # use <gametype_test> here ? |  | ||||||
|                      group by gt.base |  | ||||||
|                           ,gt.category |  | ||||||
|                           ,upper(gt.limitType) |  | ||||||
|                           ,s.name |  | ||||||
|                           ,gt.bigBlind |  | ||||||
|                           ,hc.gametypeId |  | ||||||
|                           ,PlPosition |  | ||||||
|                     ) stats |  | ||||||
|                 inner join |  | ||||||
|                     ( select # profit from handsplayers/handsactions |  | ||||||
|                              hprof.gameTypeId,  |  | ||||||
|                              case when hprof.position = 'B' then -2 |  | ||||||
|                                   when hprof.position = 'S' then -1 |  | ||||||
|                                   when hprof.position in ('3','4') then 2 |  | ||||||
|                                   when hprof.position in ('6','7') then 5 |  | ||||||
|                                   else hprof.position |  | ||||||
|                              end                                      as PlPosition, |  | ||||||
|                              sum(hprof.profit) as sum_profit, |  | ||||||
|                              avg(hprof.profit/100.0) as profitperhand, |  | ||||||
|                              variance(hprof.profit/100.0) as variance, |  | ||||||
|                              count(*) as n |  | ||||||
|                       from |  | ||||||
|                           (select hp.handId, h.gameTypeId, hp.position, hp.winnings, SUM(ha.amount) as costs |  | ||||||
|                                 , hp.winnings - SUM(ha.amount) as profit |  | ||||||
|                           from HandsPlayers hp |  | ||||||
|                           inner join Hands h        ON h.id             = hp.handId |  | ||||||
|                           left join HandsActions ha ON ha.handsPlayerId = hp.id |  | ||||||
|                           where hp.playerId in <player_test> |  | ||||||
|                                                      # use <gametype_test> here ? |  | ||||||
|                           and   hp.tourneysPlayersId IS NULL |  | ||||||
|                           and ((hp.card1Value = <first_card> and hp.card2Value = <second_card>) or (hp.card1Value = <second_card> and hp.card2Value = <first_card>)) |  | ||||||
|                           group by hp.handId, h.gameTypeId, hp.position, hp.winnings |  | ||||||
|                          ) hprof |  | ||||||
|                       group by hprof.gameTypeId, PlPosition |  | ||||||
|                      ) hprof2 |  | ||||||
|                     on (    hprof2.gameTypeId = stats.gameTypeId |  | ||||||
|                         and hprof2.PlPosition = stats.PlPosition) |  | ||||||
|                 order by stats.category, stats.limittype, stats.bigBlind, cast(stats.PlPosition as signed) |  | ||||||
|                 """ |  | ||||||
|         if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL')  or (self.dbname == 'SQLite'): |         if(self.dbname == 'MySQL InnoDB') or (self.dbname == 'PostgreSQL')  or (self.dbname == 'SQLite'): | ||||||
|             self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" |             self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" | ||||||
|          |          | ||||||
|  |  | ||||||
|  | @ -43,14 +43,14 @@ import Filters | ||||||
| 
 | 
 | ||||||
| class GuiGraphViewer (threading.Thread): | class GuiGraphViewer (threading.Thread): | ||||||
| 
 | 
 | ||||||
|     def __init__(self, db, settings, querylist, config, debug=True): |     def __init__(self, querylist, config, debug=True): | ||||||
|         """Constructor for GraphViewer""" |         """Constructor for GraphViewer""" | ||||||
|         self.debug=debug |         self.debug=debug | ||||||
|         #print "start of GraphViewer constructor" |         #print "start of GraphViewer constructor" | ||||||
|         self.db=db |         self.db = fpdb_db.fpdb_db()   # sets self.fdb.db self.fdb.cursor and self.fdb.sql | ||||||
|         self.cursor=db.cursor |         self.db.do_connect(config) | ||||||
|         self.settings=settings | 
 | ||||||
|         self.sql=querylist |         self.sql = querylist | ||||||
|         self.conf = config |         self.conf = config | ||||||
| 
 | 
 | ||||||
|         filters_display = { "Heroes"  :  True, |         filters_display = { "Heroes"  :  True, | ||||||
|  | @ -63,7 +63,7 @@ class GuiGraphViewer (threading.Thread): | ||||||
|                             "Button2" :  True |                             "Button2" :  True | ||||||
|                           } |                           } | ||||||
| 
 | 
 | ||||||
|         self.filters = Filters.Filters(db, settings, config, querylist, display = filters_display) |         self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) | ||||||
|         self.filters.registerButton1Name("Refresh Graph") |         self.filters.registerButton1Name("Refresh Graph") | ||||||
|         self.filters.registerButton1Callback(self.generateGraph) |         self.filters.registerButton1Callback(self.generateGraph) | ||||||
|         self.filters.registerButton2Name("Export to File") |         self.filters.registerButton2Name("Export to File") | ||||||
|  | @ -146,7 +146,7 @@ class GuiGraphViewer (threading.Thread): | ||||||
|         for site in sites: |         for site in sites: | ||||||
|             if sites[site] == True: |             if sites[site] == True: | ||||||
|                 sitenos.append(siteids[site]) |                 sitenos.append(siteids[site]) | ||||||
|                 self.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) |                 self.db.cursor.execute(self.sql.query['getPlayerId'], (heroes[site],)) | ||||||
|                 result = self.db.cursor.fetchall() |                 result = self.db.cursor.fetchall() | ||||||
|                 if len(result) == 1: |                 if len(result) == 1: | ||||||
|                     playerids.append(result[0][0]) |                     playerids.append(result[0][0]) | ||||||
|  | @ -226,7 +226,7 @@ class GuiGraphViewer (threading.Thread): | ||||||
| 
 | 
 | ||||||
|         #print "DEBUG: sql query:" |         #print "DEBUG: sql query:" | ||||||
|         #print tmp |         #print tmp | ||||||
|         self.cursor.execute(tmp) |         self.db.cursor.execute(tmp) | ||||||
|         #returns (HandId,Winnings,Costs,Profit) |         #returns (HandId,Winnings,Costs,Profit) | ||||||
|         winnings = self.db.cursor.fetchall() |         winnings = self.db.cursor.fetchall() | ||||||
|         self.db.db.rollback() |         self.db.db.rollback() | ||||||
|  |  | ||||||
|  | @ -66,7 +66,7 @@ class GuiPlayerStats (threading.Thread): | ||||||
|                             "Button2"  :  True |                             "Button2"  :  True | ||||||
|                           } |                           } | ||||||
| 
 | 
 | ||||||
|         self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) |         self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) | ||||||
|         self.filters.registerButton1Name("_Filters") |         self.filters.registerButton1Name("_Filters") | ||||||
|         self.filters.registerButton1Callback(self.showDetailFilter) |         self.filters.registerButton1Callback(self.showDetailFilter) | ||||||
|         self.filters.registerButton2Name("_Refresh") |         self.filters.registerButton2Name("_Refresh") | ||||||
|  | @ -227,11 +227,6 @@ class GuiPlayerStats (threading.Thread): | ||||||
|         if not flags:  holecards = False |         if not flags:  holecards = False | ||||||
|         else:          holecards = flags[0] |         else:          holecards = flags[0] | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|         self.stats_table = gtk.Table(1, 1, False) |  | ||||||
|         self.stats_table.set_col_spacings(4) |  | ||||||
|         self.stats_table.show() |  | ||||||
|          |  | ||||||
|         tmp = self.sql.query[query] |         tmp = self.sql.query[query] | ||||||
|         tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, seats, groups, dates) |         tmp = self.refineQuery(tmp, flags, playerids, sitenos, limits, seats, groups, dates) | ||||||
|         self.cursor.execute(tmp) |         self.cursor.execute(tmp) | ||||||
|  | @ -279,10 +274,6 @@ class GuiPlayerStats (threading.Thread): | ||||||
| 
 | 
 | ||||||
|         while sqlrow < rows: |         while sqlrow < rows: | ||||||
|             treerow = [] |             treerow = [] | ||||||
|             if(row%2 == 0): |  | ||||||
|                 bgcolor = "white" |  | ||||||
|             else: |  | ||||||
|                 bgcolor = "lightgrey" |  | ||||||
|             for col,column in enumerate(cols_to_show): |             for col,column in enumerate(cols_to_show): | ||||||
|                 if column[colalias] in colnames: |                 if column[colalias] in colnames: | ||||||
|                     value = result[sqlrow][colnames.index(column[colalias])] |                     value = result[sqlrow][colnames.index(column[colalias])] | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ import pygtk | ||||||
| pygtk.require('2.0') | pygtk.require('2.0') | ||||||
| import gtk | import gtk | ||||||
| import os | import os | ||||||
|  | from time import time, strftime | ||||||
|      |      | ||||||
| import fpdb_import | import fpdb_import | ||||||
| import fpdb_db | import fpdb_db | ||||||
|  | @ -58,21 +59,50 @@ class GuiPositionalStats (threading.Thread): | ||||||
|                             "Button2"  :  False |                             "Button2"  :  False | ||||||
|                           } |                           } | ||||||
| 
 | 
 | ||||||
|         self.filters = Filters.Filters(self.db, settings, config, querylist, display = filters_display) |         self.filters = Filters.Filters(self.db, config, querylist, display = filters_display) | ||||||
|         self.filters.registerButton1Name("Refresh") |         self.filters.registerButton1Name("Refresh") | ||||||
|         self.filters.registerButton1Callback(self.refreshStats) |         self.filters.registerButton1Callback(self.refreshStats) | ||||||
| 
 | 
 | ||||||
|  |         # ToDo: store in config | ||||||
|  |         # ToDo: create popup to adjust column config | ||||||
|  |         # columns to display, keys match column name returned by sql, values in tuple are: | ||||||
|  |         #     is column displayed, column heading, xalignment, formatting | ||||||
|  |         self.columns = [ ["game",       True,  "Game",     0.0, "%s"] | ||||||
|  |                        , ["hand",       False, "Hand",     0.0, "%s"]   # true not allowed for this line | ||||||
|  |                        , ["plposition", False, "Posn",     1.0, "%s"]   # true not allowed for this line (set in code) | ||||||
|  |                        , ["n",          True,  "Hds",      1.0, "%d"] | ||||||
|  |                        , ["avgseats",   True,  "Seats",    1.0, "%3.1f"] | ||||||
|  |                        , ["vpip",       True,  "VPIP",     1.0, "%3.1f"] | ||||||
|  |                        , ["pfr",        True,  "PFR",      1.0, "%3.1f"] | ||||||
|  |                        , ["pf3",        True,  "PF3",      1.0, "%3.1f"] | ||||||
|  |                        , ["steals",     True,  "Steals",   1.0, "%3.1f"] | ||||||
|  |                        , ["saw_f",      True,  "Saw_F",    1.0, "%3.1f"] | ||||||
|  |                        , ["sawsd",      True,  "SawSD",    1.0, "%3.1f"] | ||||||
|  |                        , ["wtsdwsf",    True,  "WtSDwsF",  1.0, "%3.1f"] | ||||||
|  |                        , ["wmsd",       True,  "W$SD",     1.0, "%3.1f"] | ||||||
|  |                        , ["flafq",      True,  "FlAFq",    1.0, "%3.1f"] | ||||||
|  |                        , ["tuafq",      True,  "TuAFq",    1.0, "%3.1f"] | ||||||
|  |                        , ["rvafq",      True,  "RvAFq",    1.0, "%3.1f"] | ||||||
|  |                        , ["pofafq",     False, "PoFAFq",   1.0, "%3.1f"] | ||||||
|  |                        , ["net",        True,  "Net($)",   1.0, "%6.2f"] | ||||||
|  |                        , ["bbper100",   True,  "bb/100",   1.0, "%4.2f"] | ||||||
|  |                        , ["rake",       True,  "Rake($)",  1.0, "%6.2f"] | ||||||
|  |                        , ["bb100xr",    True,  "bbxr/100", 1.0, "%4.2f"] | ||||||
|  |                        , ["variance",   True,  "Variance", 1.0, "%5.2f"] | ||||||
|  |                        ] | ||||||
|  | 
 | ||||||
|         self.stat_table = None |         self.stat_table = None | ||||||
|         self.stats_frame = None |         self.stats_frame = None | ||||||
|  |         self.stats_vbox = None | ||||||
|          |          | ||||||
|         self.main_hbox = gtk.HBox(False, 0) |         self.main_hbox = gtk.HBox(False, 0) | ||||||
|         self.main_hbox.show() |         self.main_hbox.show() | ||||||
| 
 | 
 | ||||||
|         statsFrame = gtk.Frame("Stats:") |         self.stats_frame = gtk.Frame() | ||||||
|         statsFrame.set_label_align(0.0, 0.0) |         self.stats_frame.set_label_align(0.0, 0.0) | ||||||
|         statsFrame.show() |  | ||||||
|         self.stats_frame = gtk.VBox(False, 0) |  | ||||||
|         self.stats_frame.show() |         self.stats_frame.show() | ||||||
|  |         self.stats_vbox = gtk.VBox(False, 0) | ||||||
|  |         self.stats_vbox.show() | ||||||
| 
 | 
 | ||||||
|         # This could be stored in config eventually, or maybe configured in this window somehow. |         # This could be stored in config eventually, or maybe configured in this window somehow. | ||||||
|         # Each posncols element is the name of a column returned by the sql  |         # Each posncols element is the name of a column returned by the sql  | ||||||
|  | @ -90,11 +120,11 @@ class GuiPositionalStats (threading.Thread): | ||||||
|                          , "PoFAFq", "Net($)", "bb/100", "$/hand", "Variance", "Hds" |                          , "PoFAFq", "Net($)", "bb/100", "$/hand", "Variance", "Hds" | ||||||
|                          ) |                          ) | ||||||
| 
 | 
 | ||||||
|         self.fillStatsFrame(self.stats_frame) |         self.fillStatsFrame(self.stats_vbox) | ||||||
|         statsFrame.add(self.stats_frame) |         self.stats_frame.add(self.stats_vbox) | ||||||
| 
 | 
 | ||||||
|         self.main_hbox.pack_start(self.filters.get_vbox()) |         self.main_hbox.pack_start(self.filters.get_vbox()) | ||||||
|         self.main_hbox.pack_start(statsFrame) |         self.main_hbox.pack_start(self.stats_frame) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def get_vbox(self): |     def get_vbox(self): | ||||||
|  | @ -107,9 +137,12 @@ class GuiPositionalStats (threading.Thread): | ||||||
|         print "DEBUG: activesite set to %s" %(self.activesite) |         print "DEBUG: activesite set to %s" %(self.activesite) | ||||||
| 
 | 
 | ||||||
|     def refreshStats(self, widget, data): |     def refreshStats(self, widget, data): | ||||||
|         try: self.stats_table.destroy() |         try: self.stats_vbox.destroy() | ||||||
|         except AttributeError: pass |         except AttributeError: pass | ||||||
|         self.fillStatsFrame(self.stats_frame) |         self.stats_vbox = gtk.VBox(False, 0) | ||||||
|  |         self.stats_vbox.show() | ||||||
|  |         self.stats_frame.add(self.stats_vbox) | ||||||
|  |         self.fillStatsFrame(self.stats_vbox) | ||||||
| 
 | 
 | ||||||
|     def fillStatsFrame(self, vbox): |     def fillStatsFrame(self, vbox): | ||||||
|         sites = self.filters.getSites() |         sites = self.filters.getSites() | ||||||
|  | @ -144,66 +177,104 @@ class GuiPositionalStats (threading.Thread): | ||||||
|         self.createStatsTable(vbox, playerids, sitenos, limits, seats, dates) |         self.createStatsTable(vbox, playerids, sitenos, limits, seats, dates) | ||||||
| 
 | 
 | ||||||
|     def createStatsTable(self, vbox, playerids, sitenos, limits, seats, dates): |     def createStatsTable(self, vbox, playerids, sitenos, limits, seats, dates): | ||||||
|         self.stats_table = gtk.Table(1, 1, False) # gtk table expands as required |  | ||||||
|         self.stats_table.set_col_spacings(4) |  | ||||||
|         self.stats_table.show() |  | ||||||
|         vbox.add(self.stats_table) |  | ||||||
| 
 | 
 | ||||||
|  |         starttime = time() | ||||||
|  |         colalias,colshow,colheading,colxalign,colformat = 0,1,2,3,4 | ||||||
|         row = 0 |         row = 0 | ||||||
|         col = 0 |         col = 0 | ||||||
|         for t in self.posnheads: |  | ||||||
|             l = gtk.Label(self.posnheads[col]) |  | ||||||
|             l.show() |  | ||||||
|             self.stats_table.attach(l, col, col+1, row, row+1, yoptions=gtk.SHRINK) |  | ||||||
|             col +=1  |  | ||||||
| 
 | 
 | ||||||
|         tmp = self.sql.query['playerStatsByPosition'] |         tmp = self.sql.query['playerStatsByPosition'] | ||||||
|         tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats, dates) |         tmp = self.refineQuery(tmp, playerids, sitenos, limits, seats, dates) | ||||||
|         self.cursor.execute(tmp) |         self.cursor.execute(tmp) | ||||||
|         result = self.cursor.fetchall() |         result = self.cursor.fetchall() | ||||||
|  |         colnames = [desc[0].lower() for desc in self.cursor.description] | ||||||
|  | 
 | ||||||
|  |         liststore = gtk.ListStore(*([str] * len(colnames))) | ||||||
|  |         view = gtk.TreeView(model=liststore) | ||||||
|  |         view.set_grid_lines(gtk.TREE_VIEW_GRID_LINES_BOTH) | ||||||
|  |         vbox.pack_start(view, expand=False, padding=3) | ||||||
|  |         # left-aligned cells: | ||||||
|  |         textcell = gtk.CellRendererText() | ||||||
|  |         # centred cells: | ||||||
|  |         textcell50 = gtk.CellRendererText() | ||||||
|  |         textcell50.set_property('xalign', 0.5) | ||||||
|  |         # right-aligned cells: | ||||||
|  |         numcell = gtk.CellRendererText() | ||||||
|  |         numcell.set_property('xalign', 1.0) | ||||||
|  |         listcols = [] | ||||||
|  | 
 | ||||||
|  |         for t in self.posnheads: | ||||||
|  |             listcols.append(gtk.TreeViewColumn(self.posnheads[col])) | ||||||
|  |             view.append_column(listcols[col]) | ||||||
|  |             if col == 0: | ||||||
|  |                 listcols[col].pack_start(textcell, expand=True) | ||||||
|  |                 listcols[col].add_attribute(textcell, 'text', col) | ||||||
|  |                 listcols[col].set_expand(True) | ||||||
|  |             elif col in (1, 2): | ||||||
|  |                 listcols[col].pack_start(textcell50, expand=True) | ||||||
|  |                 listcols[col].add_attribute(textcell50, 'text', col) | ||||||
|  |                 listcols[col].set_expand(True) | ||||||
|  |             else: | ||||||
|  |                 listcols[col].pack_start(numcell, expand=True) | ||||||
|  |                 listcols[col].add_attribute(numcell, 'text', col) | ||||||
|  |                 listcols[col].set_expand(True) | ||||||
|  |             col +=1  | ||||||
|  | 
 | ||||||
|  |         # Code below to be used when full column data structures implemented like in player stats: | ||||||
|  |          | ||||||
|  |         # Create header row   eg column: ("game",     True, "Game",     0.0, "%s") | ||||||
|  |         #for col, column in enumerate(cols_to_show): | ||||||
|  |         #    if column[colalias] == 'game' and holecards: | ||||||
|  |         #        s = [x for x in self.columns if x[colalias] == 'hand'][0][colheading] | ||||||
|  |         #    else: | ||||||
|  |         #        s = column[colheading] | ||||||
|  |         #    listcols.append(gtk.TreeViewColumn(s)) | ||||||
|  |         #    view.append_column(listcols[col]) | ||||||
|  |         #    if column[colformat] == '%s': | ||||||
|  |         #        if column[colxalign] == 0.0: | ||||||
|  |         #            listcols[col].pack_start(textcell, expand=True) | ||||||
|  |         #            listcols[col].add_attribute(textcell, 'text', col) | ||||||
|  |         #        else: | ||||||
|  |         #            listcols[col].pack_start(textcell50, expand=True) | ||||||
|  |         #            listcols[col].add_attribute(textcell50, 'text', col) | ||||||
|  |         #        listcols[col].set_expand(True) | ||||||
|  |         #    else: | ||||||
|  |         #        listcols[col].pack_start(numcell, expand=True) | ||||||
|  |         #        listcols[col].add_attribute(numcell, 'text', col) | ||||||
|  |         #        listcols[col].set_expand(True) | ||||||
|  |         #        #listcols[col].set_alignment(column[colxalign]) # no effect? | ||||||
| 
 | 
 | ||||||
|         rows = len(result) |         rows = len(result) | ||||||
|         colnames = [desc[0].lower() for desc in self.cursor.description] |  | ||||||
| 
 | 
 | ||||||
|         last_game,last_seats,sqlrow = "","",0 |         last_game,last_seats,sqlrow = "","",0 | ||||||
|         while sqlrow < rows: |         while sqlrow < rows: | ||||||
|             if(row%2 == 0): |  | ||||||
|                 bgcolor = "white" |  | ||||||
|             else: |  | ||||||
|                 bgcolor = "lightgrey" |  | ||||||
|             rowprinted=0 |             rowprinted=0 | ||||||
|  |             treerow = [] | ||||||
|             avgcol = colnames.index('avgseats') |             avgcol = colnames.index('avgseats') | ||||||
|             for col,colname in enumerate(self.posncols): |             for col,colname in enumerate(self.posncols): | ||||||
|                 if colname in colnames: |                 if colname in colnames: | ||||||
|                     sqlcol = colnames.index(colname) |                     sqlcol = colnames.index(colname) | ||||||
|                 else: |                 else: | ||||||
|                     continue |                     continue | ||||||
|                 eb = gtk.EventBox() |  | ||||||
|                 eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) |  | ||||||
|                 # print blank row between levels: |  | ||||||
|                 if result[sqlrow][sqlcol]: |                 if result[sqlrow][sqlcol]: | ||||||
|                     if sqlrow == 0: |                     if sqlrow == 0: | ||||||
|                         l = gtk.Label(result[sqlrow][sqlcol]) |                         value = result[sqlrow][sqlcol] | ||||||
|                         rowprinted=1 |                         rowprinted=1 | ||||||
|                     elif result[sqlrow][0] != last_game: |                     elif result[sqlrow][0] != last_game: | ||||||
|                         l = gtk.Label(' ') |                         value = ' ' | ||||||
|                     elif 'show' in seats and seats['show'] and result[sqlrow][avgcol] != last_seats: |                     elif 'show' in seats and seats['show'] and result[sqlrow][avgcol] != last_seats: | ||||||
|                         l = gtk.Label(' ') |                         value = ' ' | ||||||
|                     else: |                     else: | ||||||
|                         l = gtk.Label(result[sqlrow][sqlcol]) |                         value = result[sqlrow][sqlcol] | ||||||
|                         rowprinted=1 |                         rowprinted=1 | ||||||
|                 else: |                 else: | ||||||
|                     l = gtk.Label(' ') |                     l = gtk.Label(' ') | ||||||
|                 if col == 0: |                     value = ' ' | ||||||
|                     l.set_alignment(xalign=0.0, yalign=0.5) |                 if value and value != -999: | ||||||
|                 elif col == 1: |                     treerow.append(value) | ||||||
|                     l.set_alignment(xalign=0.5, yalign=0.5) |  | ||||||
|                 else: |                 else: | ||||||
|                     l.set_alignment(xalign=1.0, yalign=0.5) |                     treerow.append(' ') | ||||||
|                 eb.add(l) |             iter = liststore.append(treerow) | ||||||
|                 self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) |  | ||||||
|                 l.show() |  | ||||||
|                 eb.show() |  | ||||||
|             last_game = result[sqlrow][0] |             last_game = result[sqlrow][0] | ||||||
|             last_seats = result[sqlrow][avgcol] |             last_seats = result[sqlrow][avgcol] | ||||||
|             if rowprinted: |             if rowprinted: | ||||||
|  | @ -220,50 +291,36 @@ class GuiPositionalStats (threading.Thread): | ||||||
| 
 | 
 | ||||||
|         # blank row between main stats and totals: |         # blank row between main stats and totals: | ||||||
|         col = 0 |         col = 0 | ||||||
|         if(row%2 == 0): |         treerow = [' ' for x in self.posncols] | ||||||
|             bgcolor = "white" |         iter = liststore.append(treerow) | ||||||
|         else: |  | ||||||
|             bgcolor = "lightgrey" |  | ||||||
|         eb = gtk.EventBox() |  | ||||||
|         eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) |  | ||||||
|         l = gtk.Label(' ') |  | ||||||
|         eb.add(l) |  | ||||||
|         self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) |  | ||||||
|         l.show() |  | ||||||
|         eb.show() |  | ||||||
|         row = row + 1 |         row = row + 1 | ||||||
| 
 | 
 | ||||||
|         for sqlrow in range(rows): |         for sqlrow in range(rows): | ||||||
|             if(row%2 == 0): |             treerow = [] | ||||||
|                 bgcolor = "white" |  | ||||||
|             else: |  | ||||||
|                 bgcolor = "lightgrey" |  | ||||||
|             for col,colname in enumerate(self.posncols): |             for col,colname in enumerate(self.posncols): | ||||||
|                 if colname in colnames: |                 if colname in colnames: | ||||||
|                     sqlcol = colnames.index(colname) |                     sqlcol = colnames.index(colname) | ||||||
|                 elif colname != "plposition": |                 elif colname != "plposition": | ||||||
|                     continue |                     continue | ||||||
|                 eb = gtk.EventBox() |  | ||||||
|                 eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) |  | ||||||
|                 if colname == 'plposition': |                 if colname == 'plposition': | ||||||
|                     l = gtk.Label('Totals') |                     l = gtk.Label('Totals') | ||||||
|  |                     value = 'Totals' | ||||||
|                 elif result[sqlrow][sqlcol]: |                 elif result[sqlrow][sqlcol]: | ||||||
|                     l = gtk.Label(result[sqlrow][sqlcol]) |                     l = gtk.Label(result[sqlrow][sqlcol]) | ||||||
|  |                     value = result[sqlrow][sqlcol] | ||||||
|                 else: |                 else: | ||||||
|                     l = gtk.Label(' ') |                     l = gtk.Label(' ') | ||||||
|                 if col == 0: |                     value = ' ' | ||||||
|                     l.set_alignment(xalign=0.0, yalign=0.5) |                 if value and value != -999: | ||||||
|                 elif col == 1: |                     treerow.append(value) | ||||||
|                     l.set_alignment(xalign=0.5, yalign=0.5) |  | ||||||
|                 else: |                 else: | ||||||
|                     l.set_alignment(xalign=1.0, yalign=0.5) |                     treerow.append(' ') | ||||||
|                 eb.add(l) |             iter = liststore.append(treerow) | ||||||
|                 self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) |  | ||||||
|                 l.show() |  | ||||||
|                 eb.show() |  | ||||||
|             row = row + 1 |             row = row + 1 | ||||||
|  |         vbox.show_all() | ||||||
| 
 | 
 | ||||||
|         self.db.db.rollback() |         self.db.db.rollback() | ||||||
|  |         print "Positional Stats page displayed in %4.2f seconds" % (time() - starttime) | ||||||
|     #end def fillStatsFrame(self, vbox): |     #end def fillStatsFrame(self, vbox): | ||||||
| 
 | 
 | ||||||
|     def refineQuery(self, query, playerids, sitenos, limits, seats, dates): |     def refineQuery(self, query, playerids, sitenos, limits, seats, dates): | ||||||
|  |  | ||||||
							
								
								
									
										414
									
								
								pyfpdb/Hand.py
									
									
									
									
									
								
							
							
						
						
									
										414
									
								
								pyfpdb/Hand.py
									
									
									
									
									
								
							|  | @ -15,6 +15,8 @@ | ||||||
| #In the "official" distribution you can find the license in | #In the "official" distribution you can find the license in | ||||||
| #agpl-3.0.txt in the docs folder of the package. | #agpl-3.0.txt in the docs folder of the package. | ||||||
| 
 | 
 | ||||||
|  | # TODO: get writehand() encoding correct | ||||||
|  | 
 | ||||||
| import re | import re | ||||||
| import sys | import sys | ||||||
| import traceback | import traceback | ||||||
|  | @ -26,12 +28,20 @@ import operator | ||||||
| import time,datetime | import time,datetime | ||||||
| from copy import deepcopy | from copy import deepcopy | ||||||
| from Exceptions import * | from Exceptions import * | ||||||
|  | import pprint | ||||||
| import DerivedStats | import DerivedStats | ||||||
| import Card | import Card | ||||||
| 
 | 
 | ||||||
| class Hand: | class Hand: | ||||||
|  | 
 | ||||||
|  | ###############################################################3 | ||||||
|  | #    Class Variables | ||||||
|     UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} |     UPS = {'a':'A', 't':'T', 'j':'J', 'q':'Q', 'k':'K', 'S':'s', 'C':'c', 'H':'h', 'D':'d'} | ||||||
|     LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} |     LCS = {'H':'h', 'D':'d', 'C':'c', 'S':'s'} | ||||||
|  |     SYMBOL = {'USD': '$', 'EUR': u'E', 'T$': '', 'play': ''} | ||||||
|  |     MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose'  : 'HOSE'} | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     def __init__(self, sitename, gametype, handText, builtFrom = "HHC"): |     def __init__(self, sitename, gametype, handText, builtFrom = "HHC"): | ||||||
|         self.sitename = sitename |         self.sitename = sitename | ||||||
|         self.stats = DerivedStats.DerivedStats(self) |         self.stats = DerivedStats.DerivedStats(self) | ||||||
|  | @ -44,6 +54,10 @@ class Hand: | ||||||
|         self.maxseats = 10 |         self.maxseats = 10 | ||||||
|         self.counted_seats = 0 |         self.counted_seats = 0 | ||||||
|         self.buttonpos = 0 |         self.buttonpos = 0 | ||||||
|  |         self.tourNo = None | ||||||
|  |         self.buyin = None | ||||||
|  |         self.level = None | ||||||
|  |         self.mixed = None | ||||||
|         self.seating = [] |         self.seating = [] | ||||||
|         self.players = [] |         self.players = [] | ||||||
|         self.posted = [] |         self.posted = [] | ||||||
|  | @ -55,17 +69,19 @@ class Hand: | ||||||
|         self.actions = {} # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']] |         self.actions = {} # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']] | ||||||
|         self.board = {} # dict from street names to community cards |         self.board = {} # dict from street names to community cards | ||||||
|         self.holecards = {} |         self.holecards = {} | ||||||
|  |         self.discards = {} | ||||||
|         for street in self.allStreets: |         for street in self.allStreets: | ||||||
|             self.streets[street] = "" # portions of the handText, filled by markStreets() |             self.streets[street] = "" # portions of the handText, filled by markStreets() | ||||||
|  |             self.actions[street] = [] | ||||||
|  |         for street in self.actionStreets: | ||||||
|             self.bets[street] = {} |             self.bets[street] = {} | ||||||
|             self.lastBet[street] = 0 |             self.lastBet[street] = 0 | ||||||
|             self.actions[street] = [] |  | ||||||
|             self.board[street] = [] |             self.board[street] = [] | ||||||
|  |         for street in self.holeStreets: | ||||||
|             self.holecards[street] = {} # dict from player names to holecards |             self.holecards[street] = {} # dict from player names to holecards | ||||||
|          |             self.discards[street] = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards | ||||||
|         # Collections indexed by player names |         # Collections indexed by player names | ||||||
| #        self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards | #        self.holecards = {} # dict from player names to dicts by street ... of tuples ... of holecards | ||||||
|         self.discards = {} # dict from player names to dicts by street ... of tuples ... of discarded holecards |  | ||||||
|         self.stacks = {} |         self.stacks = {} | ||||||
|         self.collected = [] #list of ? |         self.collected = [] #list of ? | ||||||
|         self.collectees = {} # dict from player names to amounts collected (?) |         self.collectees = {} # dict from player names to amounts collected (?) | ||||||
|  | @ -74,6 +90,7 @@ class Hand: | ||||||
|         self.folded = set() |         self.folded = set() | ||||||
|         self.dealt = set()  # 'dealt to' line to be printed |         self.dealt = set()  # 'dealt to' line to be printed | ||||||
|         self.shown = set()  # cards were shown |         self.shown = set()  # cards were shown | ||||||
|  |         self.mucked = set() # cards were mucked at showdown | ||||||
| 
 | 
 | ||||||
| #        self.action = [] | #        self.action = [] | ||||||
|         # Things to do with money |         # Things to do with money | ||||||
|  | @ -83,10 +100,77 @@ class Hand: | ||||||
|         self.rake = None |         self.rake = None | ||||||
| 
 | 
 | ||||||
|     def __str__(self): |     def __str__(self): | ||||||
|  |         vars = ( ("BB", self.bb), | ||||||
|  |                  ("SB", self.sb), | ||||||
|  |                  ("BUTTONPOS", self.buttonpos), | ||||||
|  |                  ("HAND NO.", self.handid), | ||||||
|  |                  ("SITE", self.sitename), | ||||||
|  |                  ("TABLE NAME", self.tablename), | ||||||
|  |                  ("HERO", self.hero), | ||||||
|  |                  ("MAXSEATS", self.maxseats), | ||||||
|  |                  ("TOURNAMENT NO", self.tourNo), | ||||||
|  |                  ("BUYIN", self.buyin), | ||||||
|  |                  ("LEVEL", self.level), | ||||||
|  |                  ("MIXED", self.mixed), | ||||||
|  |                  ("LASTBET", self.lastBet), | ||||||
|  |                  ("ACTION STREETS", self.actionStreets), | ||||||
|  |                  ("STREETS", self.streets),    | ||||||
|  |                  ("ALL STREETS", self.allStreets), | ||||||
|  |                  ("COMMUNITY STREETS", self.communityStreets), | ||||||
|  |                  ("HOLE STREETS", self.holeStreets), | ||||||
|  |                  ("COUNTED SEATS", self.counted_seats), | ||||||
|  |                  ("DEALT", self.dealt), | ||||||
|  |                  ("SHOWN", self.shown), | ||||||
|  |                  ("MUCKED", self.mucked), | ||||||
|  |                  ("TOTAL POT", self.totalpot), | ||||||
|  |                  ("TOTAL COLLECTED", self.totalcollected), | ||||||
|  |                  ("RAKE", self.rake), | ||||||
|  |                  ("START TIME", self.starttime), | ||||||
|  |         ) | ||||||
|  |   | ||||||
|  |         structs = ( ("PLAYERS", self.players), | ||||||
|  |                     ("STACKS", self.stacks), | ||||||
|  |                     ("POSTED", self.posted), | ||||||
|  |                     ("POT", self.pot), | ||||||
|  |                     ("SEATING", self.seating), | ||||||
|  |                     ("GAMETYPE", self.gametype), | ||||||
|  |                     ("ACTION", self.actions), | ||||||
|  |                     ("COLLECTEES", self.collectees), | ||||||
|  |                     ("BETS", self.bets), | ||||||
|  |                     ("BOARD", self.board), | ||||||
|  |                     ("DISCARDS", self.discards), | ||||||
|  |                     ("HOLECARDS", self.holecards), | ||||||
|  |         ) | ||||||
|         str = '' |         str = '' | ||||||
|         str = str + "Hand Object for %s at %s" % (self.handid, self.sitename)  |         for (name, var) in vars: | ||||||
|  |             str = str + "\n%s = " % name + pprint.pformat(var) | ||||||
|  | 
 | ||||||
|  |         for (name, struct) in structs: | ||||||
|  |             str = str + "\n%s =\n" % name + pprint.pformat(struct, 4) | ||||||
|         return str |         return str | ||||||
| 
 | 
 | ||||||
|  |     def addHoleCards(self, street, player, open=[], closed=[], shown=False, mucked=False, dealt=False): | ||||||
|  |         """\ | ||||||
|  | Assigns observed holecards to a player. | ||||||
|  | cards   list of card bigrams e.g. ['2h','Jc'] | ||||||
|  | player  (string) name of player | ||||||
|  | shown   whether they were revealed at showdown | ||||||
|  | mucked  whether they were mucked at showdown | ||||||
|  | dealt   whether they were seen in a 'dealt to' line | ||||||
|  | """ | ||||||
|  | #        logging.debug("addHoleCards %s %s" % (open + closed, player)) | ||||||
|  |         try: | ||||||
|  |             self.checkPlayerExists(player) | ||||||
|  |         except FpdbParseError, e: | ||||||
|  |             print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) | ||||||
|  |             return | ||||||
|  | 
 | ||||||
|  |         if dealt:  self.dealt.add(player) | ||||||
|  |         if shown:  self.shown.add(player) | ||||||
|  |         if mucked: self.mucked.add(player) | ||||||
|  | 
 | ||||||
|  |         self.holecards[street][player] = [open, closed] | ||||||
|  | 
 | ||||||
|     def insert(self, db): |     def insert(self, db): | ||||||
|         """ Function to insert Hand into database |         """ Function to insert Hand into database | ||||||
| Should not commit, and do minimal selects. Callers may want to cache commits | Should not commit, and do minimal selects. Callers may want to cache commits | ||||||
|  | @ -178,10 +262,10 @@ If a player has None chips he won't be added.""" | ||||||
|             self.players.append([seat, name, chips]) |             self.players.append([seat, name, chips]) | ||||||
|             self.stacks[name] = Decimal(chips) |             self.stacks[name] = Decimal(chips) | ||||||
|             self.pot.addPlayer(name) |             self.pot.addPlayer(name) | ||||||
|             for street in self.allStreets: |             for street in self.actionStreets: | ||||||
|                 self.bets[street][name] = [] |                 self.bets[street][name] = [] | ||||||
|                 #self.holecards[name] = {} # dict from street names. |                 #self.holecards[name] = {} # dict from street names. | ||||||
|                 self.discards[name] = {} # dict from street names. |                 #self.discards[name] = {} # dict from street names. | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def addStreets(self, match): |     def addStreets(self, match): | ||||||
|  | @ -202,7 +286,7 @@ If a player has None chips he won't be added.""" | ||||||
|     def setCommunityCards(self, street, cards): |     def setCommunityCards(self, street, cards): | ||||||
|         logging.debug("setCommunityCards %s %s" %(street,  cards)) |         logging.debug("setCommunityCards %s %s" %(street,  cards)) | ||||||
|         self.board[street] = [self.card(c) for c in cards] |         self.board[street] = [self.card(c) for c in cards] | ||||||
|         print "DEBUG: self.board: %s" % self.board | #        print "DEBUG: self.board: %s" % self.board | ||||||
| 
 | 
 | ||||||
|     def card(self,c): |     def card(self,c): | ||||||
|         """upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" |         """upper case the ranks but not suits, 'atjqk' => 'ATJQK'""" | ||||||
|  | @ -367,6 +451,20 @@ Add a raise on [street] by [player] to [amountTo] | ||||||
|             self.collectees[player] += Decimal(pot) |             self.collectees[player] += Decimal(pot) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |     def addShownCards(self, cards, player, holeandboard=None, shown=True, mucked=False): | ||||||
|  |         """\ | ||||||
|  | For when a player shows cards for any reason (for showdown or out of choice). | ||||||
|  | Card ranks will be uppercased | ||||||
|  | """ | ||||||
|  |         logging.debug("addShownCards %s hole=%s all=%s" % (player, cards,  holeandboard)) | ||||||
|  |         if cards is not None: | ||||||
|  |             self.addHoleCards(cards,player,shown, mucked) | ||||||
|  |         elif holeandboard is not None: | ||||||
|  |             holeandboard = set([self.card(c) for c in holeandboard]) | ||||||
|  |             board = set([c for s in self.board.values() for c in s]) | ||||||
|  |             self.addHoleCards(holeandboard.difference(board),player,shown, mucked) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     def totalPot(self): |     def totalPot(self): | ||||||
|         """If all bets and blinds have been added, totals up the total pot size""" |         """If all bets and blinds have been added, totals up the total pot size""" | ||||||
|          |          | ||||||
|  | @ -390,7 +488,7 @@ Add a raise on [street] by [player] to [amountTo] | ||||||
| Map the tuple self.gametype onto the pokerstars string describing it | Map the tuple self.gametype onto the pokerstars string describing it | ||||||
| """ | """ | ||||||
|         # currently it appears to be something like ["ring", "hold", "nl", sb, bb]: |         # currently it appears to be something like ["ring", "hold", "nl", sb, bb]: | ||||||
|         gs = {"holdem"       : "Hold'em", |         gs = {"holdem"     : "Hold'em", | ||||||
|               "omahahi"    : "Omaha", |               "omahahi"    : "Omaha", | ||||||
|               "omahahilo"  : "Omaha Hi/Lo", |               "omahahilo"  : "Omaha Hi/Lo", | ||||||
|               "razz"       : "Razz", |               "razz"       : "Razz", | ||||||
|  | @ -410,7 +508,6 @@ Map the tuple self.gametype onto the pokerstars string describing it | ||||||
| 
 | 
 | ||||||
|         logging.debug("gametype: %s" %(self.gametype)) |         logging.debug("gametype: %s" %(self.gametype)) | ||||||
|         retstring = "%s %s" %(gs[self.gametype['category']], ls[self.gametype['limitType']]) |         retstring = "%s %s" %(gs[self.gametype['category']], ls[self.gametype['limitType']]) | ||||||
|              |  | ||||||
|         return retstring |         return retstring | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -447,6 +544,33 @@ Map the tuple self.gametype onto the pokerstars string describing it | ||||||
|         elif act[1] == 'stands pat': |         elif act[1] == 'stands pat': | ||||||
|             return ("%s: stands pat" %(act[0])) |             return ("%s: stands pat" %(act[0])) | ||||||
| 
 | 
 | ||||||
|  |     def getStakesAsString(self): | ||||||
|  |         retstring = "%s%s/%s%s" % (self.SYMBOL[self.gametype['currency']], self.sb, self.SYMBOL[self.gametype['currency']], self.bb) | ||||||
|  |         return retstring | ||||||
|  | 
 | ||||||
|  |     def writeGameLine(self): | ||||||
|  | #        print >>fh, ("%s Game #%s:  %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) | ||||||
|  |         game_string = "PokerStars Game #%s: " % self.handid | ||||||
|  |         if self.tourNo != None: | ||||||
|  |             game_string = game_string + "Tournament #%s, %s %s - Level %s (%s) - " % (self.tourNo,  | ||||||
|  |                             self.buyin, self.getGameTypeAsString(), self.level, self.getStakesAsString()) | ||||||
|  |         elif self.mixed != None: | ||||||
|  |             game_string = game_string + " %s (%s, %s) - " % (self.MS[self.mixed],  | ||||||
|  |                             self.getGameTypeAsString(), self.getStakesAsString()) | ||||||
|  |         else: | ||||||
|  |             game_string = game_string + " %s (%s) - " % (self.getGameTypeAsString(), self.getStakesAsString()) | ||||||
|  |         game_string = game_string + datetime.datetime.strftime(self.starttime,'%Y/%m/%d %H:%M:%S ET') | ||||||
|  |         return game_string | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |     def writeTableLine(self): | ||||||
|  |         table_string = "Table \'%s\' %s-max" % (self.tablename, self.maxseats) | ||||||
|  |         if self.gametype['currency'] == 'play': | ||||||
|  |             table_string = table_string + " (Play Money)" | ||||||
|  |         if self.buttonpos != None: | ||||||
|  |             table_string = table_string + " Seat #%s is the button" % self.buttonpos | ||||||
|  |         return table_string | ||||||
|  | 
 | ||||||
| 
 | 
 | ||||||
| class HoldemOmahaHand(Hand): | class HoldemOmahaHand(Hand): | ||||||
|     def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None): |     def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None): | ||||||
|  | @ -494,45 +618,12 @@ class HoldemOmahaHand(Hand): | ||||||
|             pass |             pass | ||||||
|                  |                  | ||||||
| 
 | 
 | ||||||
|     def addHoleCards(self, cards, player, shown=False, dealt=False): |     def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False): | ||||||
|         """\ |         if player == self.hero: # we have hero's cards just update shown/mucked | ||||||
| Assigns observed holecards to a player. |             if shown:  self.shown.add(player) | ||||||
| cards   list of card bigrams e.g. ['2h','Jc'] |             if mucked: self.mucked.add(player) | ||||||
| player  (string) name of player |  | ||||||
| shown   whether they were revealed at showdown |  | ||||||
| dealt   whether they were seen in a 'dealt to' line |  | ||||||
| """ |  | ||||||
|         logging.debug("addHoleCards %s %s" % (cards, player)) |  | ||||||
|         try: |  | ||||||
|             self.checkPlayerExists(player) |  | ||||||
|         except FpdbParseError, e: |  | ||||||
|             print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) |  | ||||||
|             return |  | ||||||
| 
 |  | ||||||
|         cardset = set((self.card(c) for c in cards)) |  | ||||||
|         if len(cardset) == 0: |  | ||||||
|             return |  | ||||||
|         if dealt: |  | ||||||
|             self.dealt.add(player) |  | ||||||
|         if shown: |  | ||||||
|             self.shown.add(player) |  | ||||||
|         if player in self.holecards['PREFLOP']: |  | ||||||
|             self.holecards['PREFLOP'][player].update(cardset) |  | ||||||
|         else: |         else: | ||||||
|             self.holecards['PREFLOP'][player] = cardset |             self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt) | ||||||
| 
 |  | ||||||
|     def addShownCards(self, cards, player, holeandboard=None): |  | ||||||
|         """\ |  | ||||||
| For when a player shows cards for any reason (for showdown or out of choice). |  | ||||||
| Card ranks will be uppercased |  | ||||||
| """ |  | ||||||
|         logging.debug("addShownCards %s hole=%s all=%s" % (player, cards,  holeandboard)) |  | ||||||
|         if cards is not None: |  | ||||||
|             self.addHoleCards(cards,player,shown=True) |  | ||||||
|         elif holeandboard is not None: |  | ||||||
|             holeandboard = set([self.card(c) for c in holeandboard]) |  | ||||||
|             board = set([c for s in self.board.values() for c in s]) |  | ||||||
|             self.addHoleCards(holeandboard.difference(board),player,shown=True) |  | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def writeHTMLHand(self, fh=sys.__stdout__): |     def writeHTMLHand(self, fh=sys.__stdout__): | ||||||
|  | @ -632,8 +723,11 @@ Card ranks will be uppercased | ||||||
|          |          | ||||||
|     def writeHand(self, fh=sys.__stdout__): |     def writeHand(self, fh=sys.__stdout__): | ||||||
|         # PokerStars format. |         # PokerStars format. | ||||||
|         print >>fh, ("%s Game #%s:  %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) | #        print >>fh, ("%s Game #%s:  %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) | ||||||
|         print >>fh, ("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) |         print >>fh, self.writeGameLine()  | ||||||
|  |         print >>fh, self.writeTableLine()  | ||||||
|  | 
 | ||||||
|  | #        print >>fh, ("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) | ||||||
|          |          | ||||||
|         players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) |         players_who_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) | ||||||
|         logging.debug(self.actions['PREFLOP']) |         logging.debug(self.actions['PREFLOP']) | ||||||
|  | @ -647,10 +741,10 @@ Card ranks will be uppercased | ||||||
|          |          | ||||||
|         print >>fh, ("*** HOLE CARDS ***") |         print >>fh, ("*** HOLE CARDS ***") | ||||||
|         for player in self.dealt: |         for player in self.dealt: | ||||||
|             print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player]))) |             print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player][1]))) | ||||||
|         if self.hero == "": |         if self.hero == "": | ||||||
|             for player in self.shown.difference(self.dealt): |             for player in self.shown.difference(self.dealt): | ||||||
|                 print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player]))) |                 print >>fh, ("Dealt to %s [%s]" %(player, " ".join(self.holecards['PREFLOP'][player][1]))) | ||||||
| 
 | 
 | ||||||
|         if self.actions['PREFLOP']: |         if self.actions['PREFLOP']: | ||||||
|             for act in self.actions['PREFLOP']: |             for act in self.actions['PREFLOP']: | ||||||
|  | @ -689,7 +783,7 @@ Card ranks will be uppercased | ||||||
|                 elif self.gametype['category'] in ('holdem'): |                 elif self.gametype['category'] in ('holdem'): | ||||||
|                     numOfHoleCardsNeeded = 2 |                     numOfHoleCardsNeeded = 2 | ||||||
|                 if len(self.holecards['PREFLOP'][name]) == numOfHoleCardsNeeded: |                 if len(self.holecards['PREFLOP'][name]) == numOfHoleCardsNeeded: | ||||||
|                     print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards['PREFLOP'][name]))) |                     print >>fh, ("%s shows [%s] (a hand...)" % (name, " ".join(self.holecards['PREFLOP'][name][1]))) | ||||||
|                  |                  | ||||||
|         # Current PS format has the lines: |         # Current PS format has the lines: | ||||||
|         # Uncalled bet ($111.25) returned to s0rrow |         # Uncalled bet ($111.25) returned to s0rrow | ||||||
|  | @ -716,7 +810,7 @@ Card ranks will be uppercased | ||||||
|             seatnum = player[0] |             seatnum = player[0] | ||||||
|             name = player[1] |             name = player[1] | ||||||
|             if name in self.collectees and name in self.shown: |             if name in self.collectees and name in self.shown: | ||||||
|                 print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]), self.collectees[name])) |                 print >>fh, ("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]), self.collectees[name])) | ||||||
|             elif name in self.collectees: |             elif name in self.collectees: | ||||||
|                 print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) |                 print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) | ||||||
|             #~ elif name in self.shown: |             #~ elif name in self.shown: | ||||||
|  | @ -725,7 +819,9 @@ Card ranks will be uppercased | ||||||
|                 print >>fh, ("Seat %d: %s folded" % (seatnum, name)) |                 print >>fh, ("Seat %d: %s folded" % (seatnum, name)) | ||||||
|             else: |             else: | ||||||
|                 if name in self.shown: |                 if name in self.shown: | ||||||
|                     print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards['PREFLOP'][name]))) |                     print >>fh, ("Seat %d: %s showed [%s] and lost with..." % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]))) | ||||||
|  |                 elif name in self.mucked: | ||||||
|  |                     print >>fh, ("Seat %d: %s mucked [%s] " % (seatnum, name, " ".join(self.holecards['PREFLOP'][name][1]))) | ||||||
|                 else: |                 else: | ||||||
|                     print >>fh, ("Seat %d: %s mucked" % (seatnum, name)) |                     print >>fh, ("Seat %d: %s mucked" % (seatnum, name)) | ||||||
| 
 | 
 | ||||||
|  | @ -736,8 +832,10 @@ class DrawHand(Hand): | ||||||
|         if gametype['base'] != 'draw': |         if gametype['base'] != 'draw': | ||||||
|             pass # or indeed don't pass and complain instead |             pass # or indeed don't pass and complain instead | ||||||
|         self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] |         self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||||
|  |         self.allStreets = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||||
|         self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] |         self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||||
|         self.actionStreets =  ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] |         self.actionStreets =  ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||||
|  |         self.communityStreets = [] | ||||||
|         Hand.__init__(self, sitename, gametype, handText) |         Hand.__init__(self, sitename, gametype, handText) | ||||||
|         self.sb = gametype['sb'] |         self.sb = gametype['sb'] | ||||||
|         self.bb = gametype['bb'] |         self.bb = gametype['bb'] | ||||||
|  | @ -749,12 +847,13 @@ class DrawHand(Hand): | ||||||
|             hhc.markStreets(self) |             hhc.markStreets(self) | ||||||
|             hhc.readBlinds(self) |             hhc.readBlinds(self) | ||||||
|             hhc.readButton(self) |             hhc.readButton(self) | ||||||
|  |             hhc.readHeroCards(self) | ||||||
|             hhc.readShowdownActions(self) |             hhc.readShowdownActions(self) | ||||||
|             # Read actions in street order |             # Read actions in street order | ||||||
|             for street in self.streetList: |             for street in self.streetList: | ||||||
|                 if self.streets[street]: |                 if self.streets[street]: | ||||||
|                     # hhc.readCommunityCards(self, street) |                     # hhc.readCommunityCards(self, street) | ||||||
|                     hhc.readDrawCards(self, street) | #                    hhc.readDrawCards(self, street) | ||||||
|                     hhc.readAction(self, street) |                     hhc.readAction(self, street) | ||||||
|             hhc.readCollectPot(self) |             hhc.readCollectPot(self) | ||||||
|             hhc.readShownCards(self) |             hhc.readShownCards(self) | ||||||
|  | @ -790,25 +889,33 @@ class DrawHand(Hand): | ||||||
|         #print "DEBUG: self.posted: %s" %(self.posted) |         #print "DEBUG: self.posted: %s" %(self.posted) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |     def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False): | ||||||
|  |         if player == self.hero: # we have hero's cards just update shown/mucked | ||||||
|  |             if shown:  self.shown.add(player) | ||||||
|  |             if mucked: self.mucked.add(player) | ||||||
|  |         else: | ||||||
|  | # TODO: Probably better to find the last street with action and add the hole cards to that street | ||||||
|  |             self.addHoleCards('DRAWTHREE', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt) | ||||||
| 
 | 
 | ||||||
|     def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False): | 
 | ||||||
|         """\ | #    def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False): | ||||||
| Assigns observed holecards to a player. | #        """\ | ||||||
| cards   list of card bigrams e.g. ['2h','Jc'] | #Assigns observed holecards to a player. | ||||||
| player  (string) name of player | #cards   list of card bigrams e.g. ['2h','Jc'] | ||||||
| """ | #player  (string) name of player | ||||||
|         try: | #""" | ||||||
|             self.checkPlayerExists(player) | #        try: | ||||||
| #            if shown and len(cardset) > 0: | #            self.checkPlayerExists(player) | ||||||
| #                self.shown.add(player) | ##            if shown and len(cardset) > 0: | ||||||
|             self.holecards[player][street] = (newcards,oldcards) | ##                self.shown.add(player) | ||||||
|         except FpdbParseError, e: | #            self.holecards[street][player] = (newcards,oldcards) | ||||||
|             print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) | #        except FpdbParseError, e: | ||||||
|  | #            print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def discardDrawHoleCards(self, cards, player, street): |     def discardDrawHoleCards(self, cards, player, street): | ||||||
|         logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street)) |         logging.debug("discardDrawHoleCards '%s' '%s' '%s'" % (cards, player, street)) | ||||||
|         self.discards[player][street] = set([cards]) |         self.discards[street][player] = set([cards]) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def addDiscard(self, street, player, num, cards): |     def addDiscard(self, street, player, num, cards): | ||||||
|  | @ -821,12 +928,12 @@ player  (string) name of player | ||||||
|         self.actions[street].append(act) |         self.actions[street].append(act) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def addShownCards(self, cards, player, holeandboard=None): | #    def addShownCards(self, cards, player, holeandboard=None, shown=False, mucked=False): | ||||||
|         """\ | #        """\ | ||||||
| For when a player shows cards for any reason (for showdown or out of choice). | #For when a player shows cards for any reason (for showdown or out of choice). | ||||||
| Card ranks will be uppercased | #Card ranks will be uppercased | ||||||
| """ | #""" | ||||||
|         logging.debug("addShownCards %s hole=%s all=%s" % (player, cards,  holeandboard)) | #        logging.debug("addShownCards %s hole=%s all=%s" % (player, cards,  holeandboard)) | ||||||
| #        if cards is not None: | #        if cards is not None: | ||||||
| #            self.shown.add(player) | #            self.shown.add(player) | ||||||
| #            self.addHoleCards(cards,player) | #            self.addHoleCards(cards,player) | ||||||
|  | @ -836,10 +943,39 @@ Card ranks will be uppercased | ||||||
| #            self.addHoleCards(holeandboard.difference(board),player,shown=True) | #            self.addHoleCards(holeandboard.difference(board),player,shown=True) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | #    def addHoleCards(self, cards, player, shown, mucked, dealt=False): | ||||||
|  | #        """\ | ||||||
|  | #Assigns observed holecards to a player. | ||||||
|  | #cards   list of card bigrams e.g. ['2h','Jc'] | ||||||
|  | #player  (string) name of player | ||||||
|  | #shown   whether they were revealed at showdown | ||||||
|  | #mucked  whether they were mucked at showdown | ||||||
|  | #dealt   whether they were seen in a 'dealt to' line | ||||||
|  | #""" | ||||||
|  | ##    I think this only gets called for shown cards. | ||||||
|  | #        logging.debug("addHoleCards %s %s" % (cards, player)) | ||||||
|  | #        try: | ||||||
|  | #            self.checkPlayerExists(player) | ||||||
|  | #        except FpdbParseError, e: | ||||||
|  | #            print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) | ||||||
|  | #            return | ||||||
|  | # | ||||||
|  | #        if dealt: | ||||||
|  | #            self.dealt.add(player) | ||||||
|  | #        if shown: | ||||||
|  | #            self.shown.add(player) | ||||||
|  | #        if mucked: | ||||||
|  | #            self.mucked.add(player) | ||||||
|  | #        if player != self.hero: #skip hero, we know his cards | ||||||
|  | #            print "player, cards =", player, cards | ||||||
|  | #            self.holecards[self.holeStreets[-1]][player] = (cards, set([])) | ||||||
|  | 
 | ||||||
|     def writeHand(self, fh=sys.__stdout__): |     def writeHand(self, fh=sys.__stdout__): | ||||||
|         # PokerStars format. |         # PokerStars format. | ||||||
|         print >>fh, _("%s Game #%s:  %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d %H:%M:%S ET', self.starttime))) | #        print >>fh, _("%s Game #%s:  %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d %H:%M:%S ET', self.starttime))) | ||||||
|         print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) |         print >>fh, self.writeGameLine()  | ||||||
|  | #        print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) | ||||||
|  |         print >>fh, self.writeTableLine() | ||||||
| 
 | 
 | ||||||
|         players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']])) |         players_who_act_ondeal = set(([x[0] for x in self.actions['DEAL']]+[x[0] for x in self.actions['BLINDSANTES']])) | ||||||
| 
 | 
 | ||||||
|  | @ -865,8 +1001,8 @@ Card ranks will be uppercased | ||||||
|             for act in self.actions['DRAWONE']: |             for act in self.actions['DRAWONE']: | ||||||
|                 print >>fh, self.actionString(act) |                 print >>fh, self.actionString(act) | ||||||
|                 if act[0] == self.hero and act[1] == 'discards': |                 if act[0] == self.hero and act[1] == 'discards': | ||||||
|                     (nc,oc) = self.holecards[act[0]]['DRAWONE'] |                     (nc,oc) = self.holecards['DRAWONE'][act[0]] | ||||||
|                     dc = self.discards[act[0]]['DRAWONE'] |                     dc = self.discards['DRAWONE'][act[0]] | ||||||
|                     kc = oc - dc |                     kc = oc - dc | ||||||
|                     print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) |                     print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) | ||||||
| 
 | 
 | ||||||
|  | @ -875,8 +1011,8 @@ Card ranks will be uppercased | ||||||
|             for act in self.actions['DRAWTWO']: |             for act in self.actions['DRAWTWO']: | ||||||
|                 print >>fh, self.actionString(act) |                 print >>fh, self.actionString(act) | ||||||
|                 if act[0] == self.hero and act[1] == 'discards': |                 if act[0] == self.hero and act[1] == 'discards': | ||||||
|                     (nc,oc) = self.holecards[act[0]]['DRAWTWO'] |                     (nc,oc) = self.holecards['DRAWTWO'][act[0]] | ||||||
|                     dc = self.discards[act[0]]['DRAWTWO'] |                     dc = self.discards['DRAWTWO'][act[0]] | ||||||
|                     kc = oc - dc |                     kc = oc - dc | ||||||
|                     print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) |                     print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) | ||||||
| 
 | 
 | ||||||
|  | @ -885,8 +1021,8 @@ Card ranks will be uppercased | ||||||
|             for act in self.actions['DRAWTHREE']: |             for act in self.actions['DRAWTHREE']: | ||||||
|                 print >>fh, self.actionString(act) |                 print >>fh, self.actionString(act) | ||||||
|                 if act[0] == self.hero and act[1] == 'discards': |                 if act[0] == self.hero and act[1] == 'discards': | ||||||
|                     (nc,oc) = self.holecards[act[0]]['DRAWTHREE'] |                     (nc,oc) = self.holecards['DRAWTHREE'][act[0]] | ||||||
|                     dc = self.discards[act[0]]['DRAWTHREE'] |                     dc = self.discards['DRAWTHREE'][act[0]] | ||||||
|                     kc = oc - dc |                     kc = oc - dc | ||||||
|                     print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) |                     print >>fh, _("Dealt to %s [%s] [%s]" % (act[0], " ".join(kc), " ".join(nc))) | ||||||
| 
 | 
 | ||||||
|  | @ -916,6 +1052,11 @@ class StudHand(Hand): | ||||||
|     def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): |     def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC"): | ||||||
|         if gametype['base'] != 'stud': |         if gametype['base'] != 'stud': | ||||||
|             pass # or indeed don't pass and complain instead |             pass # or indeed don't pass and complain instead | ||||||
|  | 
 | ||||||
|  |         self.allStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] | ||||||
|  |         self.communityStreets = [] | ||||||
|  |         self.actionStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] | ||||||
|  | 
 | ||||||
|         self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order |         self.streetList = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] # a list of the observed street names in order | ||||||
|         self.holeStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] |         self.holeStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] | ||||||
|         Hand.__init__(self, sitename, gametype, handText) |         Hand.__init__(self, sitename, gametype, handText) | ||||||
|  | @ -931,21 +1072,35 @@ class StudHand(Hand): | ||||||
|             hhc.markStreets(self) |             hhc.markStreets(self) | ||||||
|             hhc.readAntes(self) |             hhc.readAntes(self) | ||||||
|             hhc.readBringIn(self) |             hhc.readBringIn(self) | ||||||
|  |             hhc.readHeroCards(self) | ||||||
|             #hhc.readShowdownActions(self) # not done yet |             #hhc.readShowdownActions(self) # not done yet | ||||||
|             # Read actions in street order |             # Read actions in street order | ||||||
|             for street in self.streetList: |             for street in self.streetList: | ||||||
|                 if self.streets[street]: |                 if self.streets[street]: | ||||||
|                     logging.debug(street) |                     logging.debug(street) | ||||||
|                     logging.debug(self.streets[street]) |                     logging.debug(self.streets[street]) | ||||||
|                     hhc.readStudPlayerCards(self, street) | #                    hhc.readStudPlayerCards(self, street) | ||||||
|                     hhc.readAction(self, street) |                     hhc.readAction(self, street) | ||||||
|             hhc.readCollectPot(self) |             hhc.readCollectPot(self) | ||||||
|             #hhc.readShownCards(self) # not done yet |             hhc.readShownCards(self) # not done yet | ||||||
|             self.totalPot() # finalise it (total the pot) |             self.totalPot() # finalise it (total the pot) | ||||||
|             hhc.getRake(self) |             hhc.getRake(self) | ||||||
|         elif builtFrom == "DB": |         elif builtFrom == "DB": | ||||||
|             self.select("dummy") # Will need a handId |             self.select("dummy") # Will need a handId | ||||||
| 
 | 
 | ||||||
|  |     def addShownCards(self, cards, player, shown=True, mucked=False, dealt=False): | ||||||
|  |         if player == self.hero: # we have hero's cards just update shown/mucked | ||||||
|  |             if shown:  self.shown.add(player) | ||||||
|  |             if mucked: self.mucked.add(player) | ||||||
|  |         else: | ||||||
|  | #            self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt) | ||||||
|  |             self.addHoleCards('THIRD',   player, open=[cards[2]], closed=cards[0:2], shown=shown, mucked=mucked) | ||||||
|  |             self.addHoleCards('FOURTH',  player, open=[cards[3]], closed=[],         shown=shown, mucked=mucked) | ||||||
|  |             self.addHoleCards('FIFTH',   player, open=[cards[4]], closed=[],         shown=shown, mucked=mucked) | ||||||
|  |             self.addHoleCards('SIXTH',   player, open=[cards[5]], closed=[],         shown=shown, mucked=mucked) | ||||||
|  |             self.addHoleCards('SEVENTH', player, open=[],         closed=[cards[6]], shown=shown, mucked=mucked) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|     def addPlayerCards(self, player,  street,  open=[],  closed=[]): |     def addPlayerCards(self, player,  street,  open=[],  closed=[]): | ||||||
|         """\ |         """\ | ||||||
| Assigns observed cards to a player. | Assigns observed cards to a player. | ||||||
|  | @ -957,12 +1112,47 @@ closed    likewise, but known only to player | ||||||
|         logging.debug("addPlayerCards %s, o%s x%s" % (player,  open, closed)) |         logging.debug("addPlayerCards %s, o%s x%s" % (player,  open, closed)) | ||||||
|         try: |         try: | ||||||
|             self.checkPlayerExists(player) |             self.checkPlayerExists(player) | ||||||
|             self.holecards[player][street] = (open, closed) |             self.holecards[street][player] = (open, closed) | ||||||
| #            cards = set([self.card(c) for c in cards]) | #            cards = set([self.card(c) for c in cards]) | ||||||
| #            self.holecards[player].update(cards) | #            self.holecards[player].update(cards) | ||||||
|         except FpdbParseError, e: |         except FpdbParseError, e: | ||||||
|             print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) |             print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) | ||||||
| 
 | 
 | ||||||
|  | #    def addHoleCards(self, cards, player, shown, mucked, dealt=False): | ||||||
|  | #        """\ | ||||||
|  | #Assigns observed holecards to a player. | ||||||
|  | #cards   list of card bigrams e.g. ['2h','Jc'] | ||||||
|  | #player  (string) name of player | ||||||
|  | #shown   whether they were revealed at showdown | ||||||
|  | #mucked  whether they were mucked at showdown | ||||||
|  | #dealt   whether they were seen in a 'dealt to' line | ||||||
|  | #""" | ||||||
|  | ## | ||||||
|  | ##    For stud games we just need to do the routine setting of shown/mucked/etc | ||||||
|  | ##    and then update the cards 'THIRD' and 'SEVENTH' | ||||||
|  | #        logging.debug("addHoleCards %s %s" % (cards, player)) | ||||||
|  | #        try: | ||||||
|  | #            self.checkPlayerExists(player) | ||||||
|  | #        except FpdbParseError, e: | ||||||
|  | #            print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) | ||||||
|  | #            return | ||||||
|  | # | ||||||
|  | #        if dealt: | ||||||
|  | #            self.dealt.add(player) | ||||||
|  | #        if shown: | ||||||
|  | #            self.shown.add(player) | ||||||
|  | #        if mucked: | ||||||
|  | #            self.mucked.add(player) | ||||||
|  | #        if player == self.hero: | ||||||
|  | #            if len(cards) > 2: | ||||||
|  | #                self.holecards['THIRD'][player] = ([cards[0:3]], []) | ||||||
|  | #            if len(cards) > 6: | ||||||
|  | #                self.holecards['SEVENTH'][player] = ([cards[6]], []) | ||||||
|  | #        else: | ||||||
|  | #            if len(cards) > 2: | ||||||
|  | #                self.holecards['THIRD'][player] = ([cards[0]], cards[1:3]) | ||||||
|  | #            if len(cards) > 6: | ||||||
|  | #                self.holecards['SEVENTH'][player] = ([], [cards[6]]) | ||||||
|     # TODO: def addComplete(self, player, amount): |     # TODO: def addComplete(self, player, amount): | ||||||
|     def addComplete(self, street, player, amountTo): |     def addComplete(self, street, player, amountTo): | ||||||
|         # assert street=='THIRD' |         # assert street=='THIRD' | ||||||
|  | @ -995,11 +1185,19 @@ Add a complete on [street] by [player] to [amountTo] | ||||||
|             self.lastBet['THIRD'] = Decimal(bringin) |             self.lastBet['THIRD'] = Decimal(bringin) | ||||||
|             self.pot.addMoney(player, Decimal(bringin)) |             self.pot.addMoney(player, Decimal(bringin)) | ||||||
| 
 | 
 | ||||||
|  |      | ||||||
|     def writeHand(self, fh=sys.__stdout__): |     def writeHand(self, fh=sys.__stdout__): | ||||||
|         # PokerStars format. |         # PokerStars format. | ||||||
| #        print >>fh, _("%s Game #%s:  %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime))) | #        print >>fh, _("%s Game #%s:  %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, time.strftime('%Y/%m/%d - %H:%M:%S (ET)', self.starttime))) | ||||||
|         print >>fh, _("%s Game #%s:  %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) | 
 | ||||||
|         print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) | # TODO: | ||||||
|  | #    Hole cards are not currently correctly written. Currently the down cards for non-heros | ||||||
|  | #    are shown in the "dealt to" lines. They should be hidden in those lines. I tried to fix | ||||||
|  | #    but mind got boggled, will try again. | ||||||
|  | #        print >>fh, _("%s Game #%s:  %s ($%s/$%s) - %s" %("PokerStars", self.handid, self.getGameTypeAsString(), self.sb, self.bb, datetime.datetime.strftime(self.starttime,'%Y/%m/%d - %H:%M:%S ET'))) | ||||||
|  |         print >>fh, self.writeGameLine()  | ||||||
|  |         print >>fh, self.writeTableLine()  | ||||||
|  | #        print >>fh, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) | ||||||
|          |          | ||||||
|         players_who_post_antes = set([x[0] for x in self.actions['ANTES']]) |         players_who_post_antes = set([x[0] for x in self.actions['ANTES']]) | ||||||
| 
 | 
 | ||||||
|  | @ -1015,8 +1213,8 @@ Add a complete on [street] by [player] to [amountTo] | ||||||
|             dealt = 0 |             dealt = 0 | ||||||
|             #~ print >>fh, _("*** 3RD STREET ***") |             #~ print >>fh, _("*** 3RD STREET ***") | ||||||
|             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: |             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: | ||||||
|                 if 'THIRD' in self.holecards[player]: |                 if self.holecards['THIRD'].has_key(player): | ||||||
|                     (open,  closed) = self.holecards[player]['THIRD'] |                     (open,  closed) = self.holecards['THIRD'][player] | ||||||
|                     dealt+=1 |                     dealt+=1 | ||||||
|                     if dealt==1: |                     if dealt==1: | ||||||
|                         print >>fh, _("*** 3RD STREET ***") |                         print >>fh, _("*** 3RD STREET ***") | ||||||
|  | @ -1029,12 +1227,12 @@ Add a complete on [street] by [player] to [amountTo] | ||||||
|             dealt = 0 |             dealt = 0 | ||||||
|             #~ print >>fh, _("*** 4TH STREET ***") |             #~ print >>fh, _("*** 4TH STREET ***") | ||||||
|             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: |             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: | ||||||
|                 if 'FOURTH' in self.holecards[player]: |                 if player in self.holecards['FOURTH']: | ||||||
|                     old = [] |                     old = [] | ||||||
|                     (o,c) = self.holecards[player]['THIRD'] |                     (o,c) = self.holecards['THIRD'][player] | ||||||
|                     if o:old.extend(o) |                     if o:old.extend(o) | ||||||
|                     if c:old.extend(c) |                     if c:old.extend(c) | ||||||
|                     new = self.holecards[player]['FOURTH'][0] |                     new = self.holecards['FOURTH'][player][0] | ||||||
|                     dealt+=1 |                     dealt+=1 | ||||||
|                     if dealt==1: |                     if dealt==1: | ||||||
|                         print >>fh, _("*** 4TH STREET ***") |                         print >>fh, _("*** 4TH STREET ***") | ||||||
|  | @ -1046,13 +1244,13 @@ Add a complete on [street] by [player] to [amountTo] | ||||||
|             dealt = 0 |             dealt = 0 | ||||||
|             #~ print >>fh, _("*** 5TH STREET ***") |             #~ print >>fh, _("*** 5TH STREET ***") | ||||||
|             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: |             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: | ||||||
|                 if 'FIFTH' in self.holecards[player]: |                 if self.holecards['FIFTH'].has_key(player): | ||||||
|                     old = [] |                     old = [] | ||||||
|                     for street in ('THIRD','FOURTH'): |                     for street in ('THIRD','FOURTH'): | ||||||
|                         (o,c) = self.holecards[player][street] |                         (o,c) = self.holecards[street][player] | ||||||
|                         if o:old.extend(o) |                         if o:old.extend(o) | ||||||
|                         if c:old.extend(c) |                         if c:old.extend(c) | ||||||
|                     new = self.holecards[player]['FIFTH'][0] |                     new = self.holecards['FIFTH'][player][0] | ||||||
|                     dealt+=1 |                     dealt+=1 | ||||||
|                     if dealt==1: |                     if dealt==1: | ||||||
|                         print >>fh, _("*** 5TH STREET ***") |                         print >>fh, _("*** 5TH STREET ***") | ||||||
|  | @ -1064,13 +1262,13 @@ Add a complete on [street] by [player] to [amountTo] | ||||||
|             dealt = 0 |             dealt = 0 | ||||||
|             #~ print >>fh, _("*** 6TH STREET ***") |             #~ print >>fh, _("*** 6TH STREET ***") | ||||||
|             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: |             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: | ||||||
|                 if 'SIXTH' in self.holecards[player]: |                 if self.holecards['SIXTH'].has_key(player): | ||||||
|                     old = [] |                     old = [] | ||||||
|                     for street in ('THIRD','FOURTH','FIFTH'): |                     for street in ('THIRD','FOURTH','FIFTH'): | ||||||
|                         (o,c) = self.holecards[player][street] |                         (o,c) = self.holecards[street][player] | ||||||
|                         if o:old.extend(o) |                         if o:old.extend(o) | ||||||
|                         if c:old.extend(c) |                         if c:old.extend(c) | ||||||
|                     new = self.holecards[player]['SIXTH'][0] |                     new = self.holecards['SIXTH'][player][0] | ||||||
|                     dealt += 1 |                     dealt += 1 | ||||||
|                     if dealt == 1: |                     if dealt == 1: | ||||||
|                         print >>fh, _("*** 6TH STREET ***") |                         print >>fh, _("*** 6TH STREET ***") | ||||||
|  | @ -1085,13 +1283,13 @@ Add a complete on [street] by [player] to [amountTo] | ||||||
|             # i.e. are all but one players folded; is there an allin showdown; and all that. |             # i.e. are all but one players folded; is there an allin showdown; and all that. | ||||||
|             print >>fh, _("*** 7TH STREET ***") |             print >>fh, _("*** 7TH STREET ***") | ||||||
|             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: |             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: | ||||||
|                 if 'SEVENTH' in self.holecards[player]: |                 if self.holecards['SEVENTH'].has_key(player): | ||||||
|                     old = [] |                     old = [] | ||||||
|                     for street in ('THIRD','FOURTH','FIFTH','SIXTH'): |                     for street in ('THIRD','FOURTH','FIFTH','SIXTH'): | ||||||
|                         (o,c) = self.holecards[player][street] |                         (o,c) = self.holecards[street][player] | ||||||
|                         if o:old.extend(o) |                         if o:old.extend(o) | ||||||
|                         if c:old.extend(c) |                         if c:old.extend(c) | ||||||
|                     new = self.holecards[player]['SEVENTH'][0] |                     new = self.holecards['SEVENTH'][player][0] | ||||||
|                     if new: |                     if new: | ||||||
|                         print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") |                         print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") | ||||||
|             for act in self.actions['SEVENTH']: |             for act in self.actions['SEVENTH']: | ||||||
|  | @ -1130,11 +1328,13 @@ Add a complete on [street] by [player] to [amountTo] | ||||||
|             seatnum = player[0] |             seatnum = player[0] | ||||||
|             name = player[1] |             name = player[1] | ||||||
|             if name in self.collectees and name in self.shown: |             if name in self.collectees and name in self.shown: | ||||||
|                 print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, " ".join(self.holecards[name]), self.collectees[name])) |                 print >>fh, _("Seat %d: %s showed [%s] and won ($%s)" % (seatnum, name, self.join_holecards(name), self.collectees[name])) | ||||||
|             elif name in self.collectees: |             elif name in self.collectees: | ||||||
|                 print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) |                 print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) | ||||||
|             elif name in self.shown: |             elif name in self.shown: | ||||||
|                 print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, " ".join(self.holecards[name]))) |                 print >>fh, _("Seat %d: %s showed [%s]" % (seatnum, name, self.join_holecards(name))) | ||||||
|  |             elif name in self.mucked: | ||||||
|  |                 print >>fh, _("Seat %d: %s mucked [%s]" % (seatnum, name, self.join_holecards(name))) | ||||||
|             elif name in self.folded: |             elif name in self.folded: | ||||||
|                 print >>fh, _("Seat %d: %s folded" % (seatnum, name)) |                 print >>fh, _("Seat %d: %s folded" % (seatnum, name)) | ||||||
|             else: |             else: | ||||||
|  | @ -1143,6 +1343,12 @@ Add a complete on [street] by [player] to [amountTo] | ||||||
|         print >>fh, "\n\n" |         print >>fh, "\n\n" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |     def join_holecards(self, player): | ||||||
|  |         holecards = [] | ||||||
|  |         for street in self.holeStreets: | ||||||
|  |             if self.holecards[street].has_key(player): | ||||||
|  |                 holecards = holecards + self.holecards[street][player][0] | ||||||
|  |         return " ".join(holecards) | ||||||
| 
 | 
 | ||||||
| class Pot(object): | class Pot(object): | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -197,6 +197,7 @@ which it expects to find at self.re_TailSplitHands -- see for e.g. Everleaf.py. | ||||||
|             logging.info("Unsupported game type: %s" % gametype) |             logging.info("Unsupported game type: %s" % gametype) | ||||||
| 
 | 
 | ||||||
|         if hand: |         if hand: | ||||||
|  | #            print hand | ||||||
|             hand.writeHand(self.out_fh) |             hand.writeHand(self.out_fh) | ||||||
|         else: |         else: | ||||||
|             logging.info("Unsupported game type: %s" % gametype) |             logging.info("Unsupported game type: %s" % gametype) | ||||||
|  |  | ||||||
|  | @ -34,10 +34,13 @@ import gobject | ||||||
| 
 | 
 | ||||||
| #    FreePokerTools modules | #    FreePokerTools modules | ||||||
| from Mucked import Aux_Window | from Mucked import Aux_Window | ||||||
|  | from Mucked import Seat_Window | ||||||
|  | from Mucked import Aux_Seats | ||||||
| 
 | 
 | ||||||
| class Hello(Aux_Window): | class Hello(Aux_Window): | ||||||
|     """A 'Hello World' Aux_Window demo.""" |     """A 'Hello World' Aux_Window demo.""" | ||||||
|     def create(self): |     def create(self): | ||||||
|  |         print "creating Hello" | ||||||
| #    This demo simply creates a label in a window. | #    This demo simply creates a label in a window. | ||||||
|         self.container = gtk.Window() |         self.container = gtk.Window() | ||||||
|         self.container.add(gtk.Label("Hello World")) |         self.container.add(gtk.Label("Hello World")) | ||||||
|  | @ -99,15 +102,18 @@ class Hello_plus(Aux_Window): | ||||||
| #    hands played that was updated in the "update_data()" function. | #    hands played that was updated in the "update_data()" function. | ||||||
|         self.label.set_text("Hello %s\nYou have played %d hands\n on %s." % (self.hero, self.hands_played, self.site)) |         self.label.set_text("Hello %s\nYou have played %d hands\n on %s." % (self.hero, self.hands_played, self.site)) | ||||||
| 
 | 
 | ||||||
| class Hello_Menu(Aux_Window): | class Hello_Seats(Aux_Seats): | ||||||
|     """A 'Hello World' Aux_Window demo.""" |     """A 'Hello World' Seat_Window demo.""" | ||||||
|     def create(self): |  | ||||||
| #    This demo puts a menu item on the HUD mainwindow. |  | ||||||
|         self.item = gtk.MenuItem('Print cards') |  | ||||||
|         self.hud.menu.append(self.item) |  | ||||||
|         self.item.connect("activate", self.print_cards) |  | ||||||
|         self.item.show() |  | ||||||
| 
 | 
 | ||||||
|     def print_cards(self, *args): |     def create_contents(self, container, i): | ||||||
| #    callback for the menu item |         container.label = gtk.Label("empty") | ||||||
|         print "cards =", self.hud.cards |         container.add(container.label) | ||||||
|  |         container.show_all() | ||||||
|  | 
 | ||||||
|  |     def update_contents(self, container, i): | ||||||
|  |         if i == "common": return | ||||||
|  |         id = self.get_id_from_seat(i) | ||||||
|  |         if id == None: | ||||||
|  |             container.label.set_text("empty") | ||||||
|  |         else: | ||||||
|  |             container.label.set_text("player = %s" % self.hud.stat_dict[id]['screen_name']) | ||||||
|  |  | ||||||
|  | @ -339,30 +339,30 @@ class Hud: | ||||||
|                     Stats.do_tip(window.e_box[r][c], tip) |                     Stats.do_tip(window.e_box[r][c], tip) | ||||||
| 
 | 
 | ||||||
|     def topify_window(self, window): |     def topify_window(self, window): | ||||||
|         """Set the specified gtk window to stayontop in MS Windows.""" | #        """Set the specified gtk window to stayontop in MS Windows.""" | ||||||
| 
 | # | ||||||
|         def windowEnumerationHandler(hwnd, resultList): | #        def windowEnumerationHandler(hwnd, resultList): | ||||||
|             '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | #            '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | ||||||
|             resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | #            resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | ||||||
| 
 | #        unique_name = 'unique name for finding this window' | ||||||
|         unique_name = 'unique name for finding this window' | #        real_name = window.get_title() | ||||||
|         real_name = window.get_title() | #        window.set_title(unique_name) | ||||||
|         window.set_title(unique_name) | #        tl_windows = [] | ||||||
|         tl_windows = [] | #        win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | ||||||
|         win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | #         | ||||||
|          | #        for w in tl_windows: | ||||||
|         for w in tl_windows: | #            if w[1] == unique_name: | ||||||
|             if w[1] == unique_name: |  | ||||||
|                 self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(long(self.table.number)) |                 self.main_window.parentgdkhandle = gtk.gdk.window_foreign_new(long(self.table.number)) | ||||||
|                 self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) | #                self.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) | ||||||
|  |                 self.main_window.gdkhandle = self.main_window.window | ||||||
|                 self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) |                 self.main_window.gdkhandle.set_transient_for(self.main_window.parentgdkhandle) | ||||||
|                  |                  | ||||||
|                 style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) |                 style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) | ||||||
|                 style |= win32con.WS_CLIPCHILDREN |                 style |= win32con.WS_CLIPCHILDREN | ||||||
|                 win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) |                 win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) | ||||||
|                 break | #                break | ||||||
|              |              | ||||||
|         window.set_title(real_name) | #        window.set_title(real_name) | ||||||
| 
 | 
 | ||||||
| class Stat_Window: | class Stat_Window: | ||||||
| 
 | 
 | ||||||
|  | @ -445,10 +445,10 @@ class Stat_Window: | ||||||
|                  |                  | ||||||
|                 Stats.do_tip(e_box[r][c], 'stuff') |                 Stats.do_tip(e_box[r][c], 'stuff') | ||||||
|                 if usegtkframes: |                 if usegtkframes: | ||||||
|                     grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) |                     grid.attach(self.frame[r][c], c, c+1, r, r+1, xpadding = game.xpad, ypadding = game.ypad) | ||||||
|                     self.frame[r][c].add(e_box[r][c]) |                     self.frame[r][c].add(e_box[r][c]) | ||||||
|                 else: |                 else: | ||||||
|                     grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = 0, ypadding = 0) |                     grid.attach(e_box[r][c], c, c+1, r, r+1, xpadding = game.xpad, ypadding = game.ypad) | ||||||
|                 label[r].append( gtk.Label('xxx') ) |                 label[r].append( gtk.Label('xxx') ) | ||||||
|                  |                  | ||||||
|                 if usegtkframes: |                 if usegtkframes: | ||||||
|  | @ -473,6 +473,7 @@ class Popup_window: | ||||||
|     def __init__(self, parent, stat_window): |     def __init__(self, parent, stat_window): | ||||||
|         self.sb_click = 0 |         self.sb_click = 0 | ||||||
|         self.stat_window = stat_window |         self.stat_window = stat_window | ||||||
|  |         self.parent = parent | ||||||
| 
 | 
 | ||||||
| #    create the popup window | #    create the popup window | ||||||
|         self.window = gtk.Window() |         self.window = gtk.Window() | ||||||
|  | @ -532,11 +533,15 @@ class Popup_window: | ||||||
| #        db_connection.close_connection() | #        db_connection.close_connection() | ||||||
|         stat_dict = stat_window.parent.stat_dict |         stat_dict = stat_window.parent.stat_dict | ||||||
|         pu_text = "" |         pu_text = "" | ||||||
|  |         mo_text = "" | ||||||
|         for s in stat_list: |         for s in stat_list: | ||||||
|             number = Stats.do_stat(stat_dict, player = int(stat_window.player_id), stat = s) |             number = Stats.do_stat(stat_dict, player = int(stat_window.player_id), stat = s) | ||||||
|  |             mo_text += number[5] + " " + number[4] + "\n" | ||||||
|             pu_text += number[3] + "\n" |             pu_text += number[3] + "\n" | ||||||
|              |              | ||||||
|  | 
 | ||||||
|         self.lab.set_text(pu_text) |         self.lab.set_text(pu_text) | ||||||
|  |         Stats.do_tip(self.lab, mo_text) | ||||||
|         self.window.show_all() |         self.window.show_all() | ||||||
|          |          | ||||||
|         self.window.set_transient_for(stat_window.window) |         self.window.set_transient_for(stat_window.window) | ||||||
|  | @ -572,25 +577,25 @@ class Popup_window: | ||||||
|     def topify_window(self, window): |     def topify_window(self, window): | ||||||
|         """Set the specified gtk window to stayontop in MS Windows.""" |         """Set the specified gtk window to stayontop in MS Windows.""" | ||||||
| 
 | 
 | ||||||
|         def windowEnumerationHandler(hwnd, resultList): | #        def windowEnumerationHandler(hwnd, resultList): | ||||||
|             '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | #            '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | ||||||
|             resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | #            resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | ||||||
| 
 | 
 | ||||||
|         unique_name = 'unique name for finding this window' | #        unique_name = 'unique name for finding this window' | ||||||
|         real_name = window.get_title() | #        real_name = window.get_title() | ||||||
|         window.set_title(unique_name) | #        window.set_title(unique_name) | ||||||
|         tl_windows = [] | #        tl_windows = [] | ||||||
|         win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | #        win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | ||||||
|          |          | ||||||
|         for w in tl_windows: | #        for w in tl_windows: | ||||||
|             if w[1] == unique_name: | #            if w[1] == unique_name: | ||||||
|                 window.set_transient_for(self.parent.main_window)                |         window.set_transient_for(self.parent.main_window)                | ||||||
|                 style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) |         style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) | ||||||
|                 style |= win32con.WS_CLIPCHILDREN |         style |= win32con.WS_CLIPCHILDREN | ||||||
|                 win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) |         win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) | ||||||
|                 break | #                break | ||||||
|                  |                  | ||||||
|         window.set_title(real_name) | #        window.set_title(real_name) | ||||||
| 
 | 
 | ||||||
| if __name__== "__main__": | if __name__== "__main__": | ||||||
|     main_window = gtk.Window() |     main_window = gtk.Window() | ||||||
|  |  | ||||||
							
								
								
									
										253
									
								
								pyfpdb/Mucked.py
									
									
									
									
									
								
							
							
						
						
									
										253
									
								
								pyfpdb/Mucked.py
									
									
									
									
									
								
							|  | @ -37,27 +37,18 @@ import Configuration | ||||||
| import Database | import Database | ||||||
| import Card | import Card | ||||||
| 
 | 
 | ||||||
| class Aux_Window: | class Aux_Window(object): | ||||||
|     def __init__(self, hud, params, config): |     def __init__(self, hud, params, config): | ||||||
|         self.hud     = hud |         self.hud     = hud | ||||||
|         self.params  = params |         self.params  = params | ||||||
|         self.config  = config |         self.config  = config | ||||||
| 
 | 
 | ||||||
|     def update_data(self, *args): | #   Override these methods as needed | ||||||
|         pass |     def update_data(self, *args): pass | ||||||
| 
 |     def update_gui(self, *args):  pass | ||||||
|     def update_gui(self, *args): |     def create(self, *args):      pass | ||||||
|         pass |     def relocate(self, *args):    pass | ||||||
| 
 |     def save_layout(self, *args): pass | ||||||
|     def create(self, *args): |  | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
|     def relocate(self, *args): |  | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
|     def save_layout(self, *args): |  | ||||||
|         pass |  | ||||||
| 
 |  | ||||||
|     def destroy(self): |     def destroy(self): | ||||||
|         try: |         try: | ||||||
|             self.container.destroy() |             self.container.destroy() | ||||||
|  | @ -89,14 +80,19 @@ class Aux_Window: | ||||||
|         pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) |         pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) | ||||||
|         return temp_pb |         return temp_pb | ||||||
| 
 | 
 | ||||||
|     def split_cards(self, card): |  | ||||||
|         if card == 'xx': return ('B', 'S') |  | ||||||
|         return (card[0], card[1].upper()) |  | ||||||
| 
 |  | ||||||
|     def has_cards(self, cards): |     def has_cards(self, cards): | ||||||
|  |         """Returns the number of cards in the list.""" | ||||||
|  |         n = 0 | ||||||
|         for c in cards: |         for c in cards: | ||||||
|             if c in set('shdc'): return True |             if c != None and c > 0: n = n + 1 | ||||||
|         return False |         return n | ||||||
|  | 
 | ||||||
|  |     def get_id_from_seat(self, seat): | ||||||
|  |         """Determine player id from seat number, given stat_dict.""" | ||||||
|  |         for id, dict in self.hud.stat_dict.iteritems(): | ||||||
|  |             if seat == dict['seat']: | ||||||
|  |                 return id | ||||||
|  |         return None | ||||||
|          |          | ||||||
| class Stud_mucked(Aux_Window): | class Stud_mucked(Aux_Window): | ||||||
|     def __init__(self, hud, config, params): |     def __init__(self, hud, config, params): | ||||||
|  | @ -329,87 +325,152 @@ class Stud_cards: | ||||||
|                 self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[0]) |                 self.seen_cards[(c, r)].set_from_pixbuf(self.card_images[0]) | ||||||
|                 self.eb[(c, r)].set_tooltip_text('') |                 self.eb[(c, r)].set_tooltip_text('') | ||||||
| 
 | 
 | ||||||
| class Flop_Mucked(Aux_Window): | class Seat_Window(gtk.Window): | ||||||
|     """Aux_Window class for displaying mucked cards for flop games.""" |     """Subclass gtk.Window for the seat windows.""" | ||||||
|  | 
 | ||||||
|  | class Aux_Seats(Aux_Window): | ||||||
|  |     """A super class to display an aux_window at each seat.""" | ||||||
| 
 | 
 | ||||||
|     def __init__(self, hud, config, params): |     def __init__(self, hud, config, params): | ||||||
|         self.hud     = hud       # hud object that this aux window supports |         self.hud     = hud       # hud object that this aux window supports | ||||||
|         self.config  = config    # configuration object for this aux window to use |         self.config  = config    # configuration object for this aux window to use | ||||||
|         self.params  = params    # dict aux params from config |         self.params  = params    # dict aux params from config | ||||||
|         self.positions = {}      # dict of window positions |         self.positions = {}      # dict of window positions | ||||||
| #        self.rel_positions = {}  # dict of window positions, relative to the table origin |         self.displayed = False   # the seat windows are displayed | ||||||
|         self.displayed_cards = False |         self.uses_timer = False  # the Aux_seats object uses a timer to control hiding | ||||||
|         self.timer_on = False    # bool = Ture if the timeout for removing the cards is on |         self.timer_on = False    # bool = Ture if the timeout for removing the cards is on | ||||||
|         self.card_images = self.get_card_images() | 
 | ||||||
|  | #    placeholders that should be overridden--so we don't throw errors | ||||||
|  |     def create_contents(self): pass | ||||||
|  |     def update_contents(self): pass | ||||||
| 
 | 
 | ||||||
|     def create(self): |     def create(self): | ||||||
|         self.adj = self.hud.adj_seats(0, self.config) |         self.adj = self.hud.adj_seats(0, self.config)  # move adj_seats to aux and get rid of it in Hud.py | ||||||
|         loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max)) |         loc = self.config.get_aux_locations(self.params['name'], int(self.hud.max)) | ||||||
|          |          | ||||||
|         self.m_windows = {}      # windows to put the card images in |         self.m_windows = {}      # windows to put the card images in | ||||||
|         self.eb = {}             # event boxes so we can interact with the mucked cards |  | ||||||
|         self.seen_cards = {}     # image objects to stash the cards in |  | ||||||
| 
 | 
 | ||||||
|         for i in (range(1, self.hud.max + 1) + ['common']):            |         for i in (range(1, self.hud.max + 1) + ['common']):            | ||||||
|             if i == 'common': |             if i == 'common': | ||||||
|                 (x, y) = self.params['layout'][self.hud.max].common |                 (x, y) = self.params['layout'][self.hud.max].common | ||||||
|             else: |             else: | ||||||
|                 (x, y) = loc[self.adj[i]] |                 (x, y) = loc[self.adj[i]] | ||||||
|             self.m_windows[i] = gtk.Window() |             self.m_windows[i] = Seat_Window() | ||||||
|             self.m_windows[i].set_decorated(False) |             self.m_windows[i].set_decorated(False) | ||||||
|             self.m_windows[i].set_property("skip-taskbar-hint", True) |             self.m_windows[i].set_property("skip-taskbar-hint", True) | ||||||
|             self.m_windows[i].set_transient_for(self.hud.main_window) |             self.m_windows[i].set_transient_for(self.hud.main_window) | ||||||
|             self.m_windows[i].set_focus_on_map(False) |             self.m_windows[i].set_focus_on_map(False) | ||||||
|             self.eb[i] = gtk.EventBox() |  | ||||||
|             self.eb[i].connect("button_press_event", self.button_press_cb) |  | ||||||
|             self.m_windows[i].connect("configure_event", self.configure_event_cb, i) |             self.m_windows[i].connect("configure_event", self.configure_event_cb, i) | ||||||
|             self.m_windows[i].add(self.eb[i]) |  | ||||||
|             self.seen_cards[i] = gtk.image_new_from_pixbuf(self.card_images[('B', 'H')]) |  | ||||||
|             self.eb[i].add(self.seen_cards[i]) |  | ||||||
|             self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y) |             self.positions[i] = (int(x) + self.hud.table.x, int(y) + self.hud.table.y) | ||||||
| #            self.rel_positions[i] = (int(x), int(y)) |  | ||||||
|             self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) |             self.m_windows[i].move(self.positions[i][0], self.positions[i][1]) | ||||||
|             self.m_windows[i].set_opacity(float(self.params['opacity'])) |             if self.params.has_key('opacity'): | ||||||
|  |                 self.m_windows[i].set_opacity(float(self.params['opacity'])) | ||||||
|  | 
 | ||||||
|  | #    the create_contents method is supplied by the subclass | ||||||
|  |             self.create_contents(self.m_windows[i], i) | ||||||
|  | 
 | ||||||
|             self.m_windows[i].show_all() |             self.m_windows[i].show_all() | ||||||
|             self.m_windows[i].hide() |             if self.uses_timer: | ||||||
|  |                 self.m_windows[i].hide() | ||||||
|  | 
 | ||||||
|  |     def update_gui(self, new_hand_id): | ||||||
|  |         """Update the gui, LDO.""" | ||||||
|  |         for i in self.m_windows.keys(): | ||||||
|  |             self.update_contents(self.m_windows[i], i)            | ||||||
|  | 
 | ||||||
|  | #   Methods likely to be of use for any Seat_Window implementation | ||||||
|  |     def destroy(self): | ||||||
|  |         """Destroy all of the seat windows.""" | ||||||
|  |         for i in self.m_windows.keys(): | ||||||
|  |             self.m_windows[i].destroy() | ||||||
|  |             del(self.m_windows[i]) | ||||||
|  | 
 | ||||||
|  | #   Methods likely to be useful for mucked card windows (or similar) only | ||||||
|  |     def hide(self): | ||||||
|  |         """Hide the seat windows.""" | ||||||
|  |         for (i, w) in self.m_windows.iteritems(): | ||||||
|  |             w.hide() | ||||||
|  |         self.displayed = False | ||||||
|  | 
 | ||||||
|  |     def save_layout(self, *args): | ||||||
|  |         """Save new layout back to the aux element in the config file.""" | ||||||
|  |         new_locs = {} | ||||||
|  | #        print "adj =", self.adj | ||||||
|  |         for (i, pos) in self.positions.iteritems(): | ||||||
|  |             if i != 'common': | ||||||
|  |                 new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) | ||||||
|  |             else: | ||||||
|  |                 new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) | ||||||
|  |         self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) | ||||||
|  | 
 | ||||||
|  |     def configure_event_cb(self, widget, event, i, *args): | ||||||
|  |         self.positions[i] = widget.get_position() | ||||||
|  | #        self.rel_positions[i] = (self.positions[i][0] - self.hud.table.x, self.positions[i][1] - self.hud.table.y) | ||||||
|  | 
 | ||||||
|  | class Flop_Mucked(Aux_Seats): | ||||||
|  |     """Aux_Window class for displaying mucked cards for flop games.""" | ||||||
|  | 
 | ||||||
|  |     def __init__(self, hud, config, params): | ||||||
|  |         super(Flop_Mucked, self).__init__(hud, config, params) | ||||||
|  |         self.card_images = self.get_card_images() | ||||||
|  |         self.uses_timer = True  # this Aux_seats object uses a timer to control hiding | ||||||
|  | 
 | ||||||
|  |     def create_contents(self, container, i): | ||||||
|  |         """Create the widgets for showing the contents of the Aux_seats window.""" | ||||||
|  |         container.eb = gtk.EventBox() | ||||||
|  |         container.eb.connect("button_press_event", self.button_press_cb) | ||||||
|  |         container.add(container.eb) | ||||||
|  |         container.seen_cards = gtk.image_new_from_pixbuf(self.card_images[0]) | ||||||
|  |         container.eb.add(container.seen_cards) | ||||||
|  | 
 | ||||||
|  |     def update_contents(self, container, i): | ||||||
|  |         if not self.hud.cards.has_key(i): return | ||||||
|  |         cards = self.hud.cards[i] | ||||||
|  |         n_cards = self.has_cards(cards) | ||||||
|  |         if n_cards > 1: | ||||||
|  | 
 | ||||||
|  | #    scratch is a working pixbuf, used to assemble the image | ||||||
|  |             scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, | ||||||
|  |                                      int(self.params['card_wd'])*n_cards, | ||||||
|  |                                      int(self.params['card_ht'])) | ||||||
|  |             x = 0 # x coord where the next card starts in scratch | ||||||
|  |             for card in cards: | ||||||
|  | #    concatenate each card image to scratch | ||||||
|  |                 if card == None or card ==0: | ||||||
|  |                     break | ||||||
|  |                 self.card_images[card].copy_area(0, 0,  | ||||||
|  |                                         int(self.params['card_wd']), int(self.params['card_ht']), | ||||||
|  |                                         scratch, x, 0) | ||||||
|  |                 x = x + int(self.params['card_wd']) | ||||||
|  |             container.seen_cards.set_from_pixbuf(scratch) | ||||||
|  |             container.resize(1,1) | ||||||
|  |             container.show() | ||||||
|  |             container.move(self.positions[i][0], self.positions[i][1])   # here is where I move back | ||||||
|  |             self.displayed = True | ||||||
|  |             if i != "common": | ||||||
|  |                 id = self.get_id_from_seat(i) | ||||||
|  |                 self.m_windows[i].eb.set_tooltip_text(self.hud.stat_dict[id]['screen_name']) | ||||||
| 
 | 
 | ||||||
|     def update_gui(self, new_hand_id): |     def update_gui(self, new_hand_id): | ||||||
|         """Prepare and show the mucked cards.""" |         """Prepare and show the mucked cards.""" | ||||||
|         if self.displayed_cards: |         if self.displayed: self.hide() | ||||||
|             self.hide_mucked_cards() | 
 | ||||||
|             self.displayed_cards = False | #   See how many players showed a hand. Skip if only 1 shows (= hero) | ||||||
|  |         n_sd = 0 | ||||||
|         for (i, cards) in self.hud.cards.iteritems(): |         for (i, cards) in self.hud.cards.iteritems(): | ||||||
|             if self.has_cards(cards): |             n_cards = self.has_cards(cards) | ||||||
| #    scratch is a working pixbuf, used to assemble the image |             if n_cards > 0 and i != 'common': | ||||||
|                 scratch = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, |                 n_sd = n_sd + 1 | ||||||
|                                          int(self.params['card_wd'])*len(cards)/2, |         if n_sd < 2:  | ||||||
|                                          int(self.params['card_ht'])) |             print "skipping, n_sd =", n_sd | ||||||
|                 x = 0 # x coord where the next card starts in scratch |             return | ||||||
|                 for card in [cards[k:k+2] for k in xrange(0, len(cards), 2)]: |  | ||||||
| #    concatenate each card image to scratch |  | ||||||
|                     self.card_images[self.split_cards(card)].copy_area(0, 0,  |  | ||||||
|                                             int(self.params['card_wd']), int(self.params['card_ht']), |  | ||||||
|                                             scratch, x, 0) |  | ||||||
|                     x = x + int(self.params['card_wd']) |  | ||||||
|                 self.seen_cards[i].set_from_pixbuf(scratch) |  | ||||||
| #                self.m_windows[i].show_all() |  | ||||||
|                 self.m_windows[i].resize(1,1) |  | ||||||
|                 self.m_windows[i].show() |  | ||||||
|                 self.m_windows[i].move(self.positions[i][0], self.positions[i][1])   # here is where I move back |  | ||||||
|                 self.displayed_cards = True |  | ||||||
| 
 | 
 | ||||||
|         for stats in self.hud.stat_dict.itervalues(): |         super(Flop_Mucked, self).update_gui(new_hand_id) | ||||||
|             self.eb[stats['seat']].set_tooltip_text(stats['screen_name']) |  | ||||||
| 
 | 
 | ||||||
|         if self.displayed_cards and float(self.params['timeout']) > 0: |         if self.displayed and float(self.params['timeout']) > 0: | ||||||
|             self.timer_on = True |             self.timer_on = True | ||||||
|             gobject.timeout_add(int(1000*float(self.params['timeout'])), self.timed_out) |             gobject.timeout_add(int(1000*float(self.params['timeout'])), self.timed_out) | ||||||
| 
 | 
 | ||||||
|     def destroy(self): |  | ||||||
|         """Destroy all of the mucked windows.""" |  | ||||||
|         for w in self.m_windows.values(): |  | ||||||
|             w.destroy() |  | ||||||
| 
 |  | ||||||
|     def timed_out(self): |     def timed_out(self): | ||||||
| #    this is the callback from the timeout | #    this is the callback from the timeout | ||||||
| 
 | 
 | ||||||
|  | @ -418,15 +479,9 @@ class Flop_Mucked(Aux_Window): | ||||||
|         if not self.timer_on: |         if not self.timer_on: | ||||||
|             return False |             return False | ||||||
|         else: |         else: | ||||||
|             self.hide_mucked_cards() |             self.hide() | ||||||
|             return False |             return False | ||||||
| 
 | 
 | ||||||
|     def hide_mucked_cards(self): |  | ||||||
|         """Hide the mucked card windows.""" |  | ||||||
|         for (i, w) in self.m_windows.iteritems(): |  | ||||||
|             w.hide() |  | ||||||
|         self.displayed_cards = False |  | ||||||
| 
 |  | ||||||
|     def button_press_cb(self, widget, event, *args): |     def button_press_cb(self, widget, event, *args): | ||||||
|         """Handle button clicks in the event boxes.""" |         """Handle button clicks in the event boxes.""" | ||||||
| 
 | 
 | ||||||
|  | @ -444,58 +499,14 @@ class Flop_Mucked(Aux_Window): | ||||||
|                 self.timer_on = False |                 self.timer_on = False | ||||||
|             else: |             else: | ||||||
|                 self.timer_on = False |                 self.timer_on = False | ||||||
|                 self.hide_mucked_cards() |                 self.hide() | ||||||
| 
 | 
 | ||||||
|         elif event.button == 1:   # left button event |         elif event.button == 1:   # left button event | ||||||
|             window = widget.get_parent() |             window = widget.get_parent() | ||||||
|             window.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time) |             window.begin_move_drag(event.button, int(event.x_root), int(event.y_root), event.time) | ||||||
| 
 | 
 | ||||||
|     def configure_event_cb(self, widget, event, i, *args): |  | ||||||
|         self.positions[i] = widget.get_position() |  | ||||||
| #        self.rel_positions[i] = (self.positions[i][0] - self.hud.table.x, self.positions[i][1] - self.hud.table.y) |  | ||||||
| 
 |  | ||||||
|     def expose_all(self): |     def expose_all(self): | ||||||
|         for (i, cards) in self.hud.cards.iteritems(): |         for (i, cards) in self.hud.cards.iteritems(): | ||||||
|             self.m_windows[i].show() |             self.m_windows[i].show() | ||||||
|             self.m_windows[i].move(self.positions[i][0], self.positions[i][1])   # here is where I move back |             self.m_windows[i].move(self.positions[i][0], self.positions[i][1])   # here is where I move back | ||||||
|             self.displayed_cards = True |             self.displayed = True | ||||||
| 
 |  | ||||||
|     def save_layout(self, *args): |  | ||||||
|         """Save new layout back to the aux element in the config file.""" |  | ||||||
|         new_locs = {} |  | ||||||
| #        print "adj =", self.adj |  | ||||||
|         for (i, pos) in self.positions.iteritems(): |  | ||||||
|             if i != 'common': |  | ||||||
|                 new_locs[self.adj[int(i)]] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) |  | ||||||
|             else: |  | ||||||
|                 new_locs[i] = (pos[0] - self.hud.table.x, pos[1] - self.hud.table.y) |  | ||||||
|         self.config.edit_aux_layout(self.params['name'], self.hud.max, locations = new_locs) |  | ||||||
| 
 |  | ||||||
| #    This test program doesn't work |  | ||||||
| 
 |  | ||||||
| #if __name__== "__main__": |  | ||||||
| #     |  | ||||||
| #    def destroy(*args):             # call back for terminating the main eventloop |  | ||||||
| #        gtk.main_quit()             # used only for testing |  | ||||||
| # |  | ||||||
| #    def process_new_hand(source, condition, db_connection):  #callback from stdin watch -- testing only |  | ||||||
| ##    there is a new hand_id to be processed |  | ||||||
| ##    just read it and pass it to update |  | ||||||
| #        new_hand_id = sys.stdin.readline() |  | ||||||
| #        new_hand_id = new_hand_id.rstrip()  # remove trailing whitespace |  | ||||||
| #        m.update_data(new_hand_id, db_connection) |  | ||||||
| #        m.update_gui(new_hand_id) |  | ||||||
| #        return(True) |  | ||||||
| # |  | ||||||
| #    config = Configuration.Config() |  | ||||||
| #    db_connection = Database.Database(config, 'fpdbTEST', '') |  | ||||||
| #    main_window = gtk.Window() |  | ||||||
| #    main_window.set_keep_above(True) |  | ||||||
| #    main_window.connect("destroy", destroy) |  | ||||||
| # |  | ||||||
| #    aux_to_call = "stud_mucked" |  | ||||||
| #    aux_params = config.get_aux_parameters(aux_to_call) |  | ||||||
| #    m = eval("%s(None, config, aux_params)" % aux_params['class']) |  | ||||||
| #     |  | ||||||
| #    s_id = gobject.io_add_watch(sys.stdin, gobject.IO_IN, process_new_hand, db_connection) |  | ||||||
| #    gtk.main() |  | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ | ||||||
| #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||||
| ######################################################################## | ######################################################################## | ||||||
| 
 | 
 | ||||||
|  | # TODO: straighten out discards for draw games | ||||||
| import sys | import sys | ||||||
| from HandHistoryConverter import * | from HandHistoryConverter import * | ||||||
| 
 | 
 | ||||||
|  | @ -25,16 +26,35 @@ from HandHistoryConverter import * | ||||||
| 
 | 
 | ||||||
| class PokerStars(HandHistoryConverter): | class PokerStars(HandHistoryConverter): | ||||||
| 
 | 
 | ||||||
|  | ############################################################ | ||||||
|  | #    Class Variables | ||||||
|  | 
 | ||||||
|     # Static regexes |     # Static regexes | ||||||
|     re_GameInfo     = re.compile("PokerStars Game #(?P<HID>[0-9]+):\s+(HORSE)? \(?(?P<GAME>Hold\'em|Razz|7 Card Stud|7 Card Stud Hi/Lo|Omaha|Omaha Hi/Lo|Badugi) (?P<LIMIT>No Limit|Limit|Pot Limit),? \(?(?P<CURRENCY>\$|)?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+)\) - (?P<DATETIME>.*$)", re.MULTILINE) |     re_GameInfo     = re.compile("""PokerStars\sGame\s\#(?P<HID>[0-9]+):\s+ | ||||||
|  |                                   (Tournament\s\#(?P<TOURNO>\d+),\s(?P<BUYIN>[\$\+\d\.]+)\s)? | ||||||
|  |                                   (?P<MIXED>HORSE|8\-Game|HOSE)?\s?\(? | ||||||
|  |                                   (?P<GAME>Hold\'em|Razz|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball)\s | ||||||
|  |                                   (?P<LIMIT>No\sLimit|Limit|Pot\sLimit)\)?,?\s | ||||||
|  |                                   (-\sLevel\s(?P<LEVEL>[IVXLC]+)\s)?\(? | ||||||
|  |                                   (?P<CURRENCY>\$|)? | ||||||
|  |                                   (?P<SB>[.0-9]+)/\$? | ||||||
|  |                                   (?P<BB>[.0-9]+)\)\s-\s | ||||||
|  |                                   (?P<DATETIME>.*$)""", | ||||||
|  |                                   re.MULTILINE|re.VERBOSE) | ||||||
|     re_SplitHands   = re.compile('\n\n+') |     re_SplitHands   = re.compile('\n\n+') | ||||||
|     re_TailSplitHands   = re.compile('(\n\n\n+)') |     re_TailSplitHands   = re.compile('(\n\n\n+)') | ||||||
|     re_HandInfo     = re.compile("^Table \'(?P<TABLE>[- a-zA-Z]+)\'(?P<TABLEATTRIBUTES>.+?$)?", re.MULTILINE) |     re_HandInfo     = re.compile("""^Table\s\'(?P<TABLE>[-\ a-zA-Z\d]+)\'\s | ||||||
|  |                                     ((?P<MAX>\d+)-max\s)? | ||||||
|  |                                     (?P<PLAY>\(Play\sMoney\)\s)? | ||||||
|  |                                     (Seat\s\#(?P<BUTTON>\d+)\sis\sthe\sbutton)?""",  | ||||||
|  |                                     re.MULTILINE|re.VERBOSE) | ||||||
|     re_Button       = re.compile('Seat #(?P<BUTTON>\d+) is the button', re.MULTILINE) |     re_Button       = re.compile('Seat #(?P<BUTTON>\d+) is the button', re.MULTILINE) | ||||||
|     re_PlayerInfo   = re.compile('^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[.0-9]+) in chips\)', re.MULTILINE) |     re_PlayerInfo   = re.compile('^Seat (?P<SEAT>[0-9]+): (?P<PNAME>.*) \(\$?(?P<CASH>[.0-9]+) in chips\)', re.MULTILINE) | ||||||
|     re_Board        = re.compile(r"\[(?P<CARDS>.+)\]") |     re_Board        = re.compile(r"\[(?P<CARDS>.+)\]") | ||||||
| #        self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')     | #        self.re_setHandInfoRegex('.*#(?P<HID>[0-9]+): Table (?P<TABLE>[ a-zA-Z]+) - \$?(?P<SB>[.0-9]+)/\$?(?P<BB>[.0-9]+) - (?P<GAMETYPE>.*) - (?P<HR>[0-9]+):(?P<MIN>[0-9]+) ET - (?P<YEAR>[0-9]+)/(?P<MON>[0-9]+)/(?P<DAY>[0-9]+)Table (?P<TABLE>[ a-zA-Z]+)\nSeat (?P<BUTTON>[0-9]+)')     | ||||||
| 
 | 
 | ||||||
|  |     mixes = { 'HORSE': 'horse', '8-Game': '8game', 'HOSE': 'hose'} | ||||||
|  | 
 | ||||||
|     def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): |     def __init__(self, in_path = '-', out_path = '-', follow = False, autostart=True): | ||||||
|         """\ |         """\ | ||||||
| in_path   (default '-' = sys.stdin) | in_path   (default '-' = sys.stdin) | ||||||
|  | @ -53,6 +73,9 @@ follow :  whether to tail -f the input""" | ||||||
|         players = set([player[1] for player in hand.players]) |         players = set([player[1] for player in hand.players]) | ||||||
|         if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' |         if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' | ||||||
|             # we need to recompile the player regexs. |             # we need to recompile the player regexs. | ||||||
|  | # TODO: should probably rename re_HeroCards and corresponding method, | ||||||
|  | #    since they are used to find all cards on lines starting with "Dealt to:" | ||||||
|  | #    They still identify the hero. | ||||||
|             self.compiledPlayers = players |             self.compiledPlayers = players | ||||||
|             player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")" |             player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")" | ||||||
|             logging.debug("player_re: " + player_re) |             logging.debug("player_re: " + player_re) | ||||||
|  | @ -62,43 +85,59 @@ follow :  whether to tail -f the input""" | ||||||
|             self.re_BringIn          = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE) |             self.re_BringIn          = re.compile(r"^%s: brings[- ]in( low|) for \$?(?P<BRINGIN>[.0-9]+)" % player_re, re.MULTILINE) | ||||||
|             self.re_PostBoth         = re.compile(r"^%s: posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" %  player_re, re.MULTILINE) |             self.re_PostBoth         = re.compile(r"^%s: posts small \& big blinds \[\$? (?P<SBBB>[.0-9]+)" %  player_re, re.MULTILINE) | ||||||
|             self.re_HeroCards        = re.compile(r"^Dealt to %s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE) |             self.re_HeroCards        = re.compile(r"^Dealt to %s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % player_re, re.MULTILINE) | ||||||
|             self.re_Action           = re.compile(r"^%s:(?P<ATYPE> bets| checks| raises| calls| folds| discards| stands pat)( \$(?P<BET>[.\d]+))?( to \$(?P<BETTO>[.\d]+))?( (?P<NODISCARDED>\d) cards?( \[(?P<DISCARDED>.+?)\])?)?" %  player_re, re.MULTILINE) |             self.re_Action           = re.compile(r"""^%s:(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\sdiscards|\sstands\spat) | ||||||
|  |                                                         (\s\$?(?P<BET>[.\d]+))?(\sto\s\$?(?P<BETTO>[.\d]+))?  # the number discarded goes in <BET> | ||||||
|  |                                                         (\scards?(\s\[(?P<DISCARDED>.+?)\])?)?""" | ||||||
|  |                                                          %  player_re, re.MULTILINE|re.VERBOSE) | ||||||
|             self.re_ShowdownAction   = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" %  player_re, re.MULTILINE) |             self.re_ShowdownAction   = re.compile(r"^%s: shows \[(?P<CARDS>.*)\]" %  player_re, re.MULTILINE) | ||||||
|             self.re_CollectPot       = re.compile(r"Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$(?P<POT>[.\d]+)\)(, mucked| with.*|)" %  player_re, re.MULTILINE) |             self.re_CollectPot       = re.compile(r"Seat (?P<SEAT>[0-9]+): %s (\(button\) |\(small blind\) |\(big blind\) )?(collected|showed \[.*\] and won) \(\$?(?P<POT>[.\d]+)\)(, mucked| with.*|)" %  player_re, re.MULTILINE) | ||||||
|             self.re_sitsOut          = re.compile("^%s sits out" %  player_re, re.MULTILINE) |             self.re_sitsOut          = re.compile("^%s sits out" %  player_re, re.MULTILINE) | ||||||
|             self.re_ShownCards       = re.compile("^Seat (?P<SEAT>[0-9]+): %s \(.*\) showed \[(?P<CARDS>.*)\].*" %  player_re, re.MULTILINE) |             self.re_ShownCards       = re.compile("^Seat (?P<SEAT>[0-9]+): %s (\(.*\) )?(?P<SHOWED>showed|mucked) \[(?P<CARDS>.*)\].*" %  player_re, re.MULTILINE) | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|     def readSupportedGames(self): |     def readSupportedGames(self): | ||||||
|         return [["ring", "hold", "nl"], |         return [["ring", "hold", "nl"], | ||||||
|                 ["ring", "hold", "pl"], |                 ["ring", "hold", "pl"], | ||||||
|                 ["ring", "hold", "fl"], |                 ["ring", "hold", "fl"], | ||||||
|  | 
 | ||||||
|                 ["ring", "stud", "fl"], |                 ["ring", "stud", "fl"], | ||||||
|                 #["ring", "draw", "fl"], | 
 | ||||||
|                 ["ring", "omaha", "pl"] |                 ["ring", "draw", "fl"], | ||||||
|  | 
 | ||||||
|  |                 ["tour", "hold", "nl"], | ||||||
|  |                 ["tour", "hold", "pl"], | ||||||
|  |                 ["tour", "hold", "fl"], | ||||||
|  | 
 | ||||||
|  |                 ["tour", "stud", "fl"], | ||||||
|                ] |                ] | ||||||
| 
 | 
 | ||||||
|     def determineGameType(self, handText): |     def determineGameType(self, handText): | ||||||
|         info = {'type':'ring'} | #    inspect the handText and return the gametype dict | ||||||
|  | #    gametype dict is: | ||||||
|  | #    {'limitType': xxx, 'base': xxx, 'category': xxx} | ||||||
|          |          | ||||||
|  |         info = {} | ||||||
|         m = self.re_GameInfo.search(handText) |         m = self.re_GameInfo.search(handText) | ||||||
|         if not m: |         if not m: | ||||||
|             return None |             return None | ||||||
| 
 | 
 | ||||||
|         mg = m.groupdict() |         mg = m.groupdict() | ||||||
|          |         # translations from captured groups to fpdb info strings | ||||||
|         # translations from captured groups to our info strings |  | ||||||
|         limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' } |         limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' } | ||||||
|         games = {              # base, category |         games = {                          # base, category | ||||||
|                   "Hold'em" : ('hold','holdem'),  |                               "Hold'em" : ('hold','holdem'),  | ||||||
|                     'Omaha' : ('hold','omahahi'), |                                 'Omaha' : ('hold','omahahi'), | ||||||
|               'Omaha Hi/Lo' : ('hold','omahahilo'), |                           'Omaha Hi/Lo' : ('hold','omahahilo'), | ||||||
|                      'Razz' : ('stud','razz'),  |                                  'Razz' : ('stud','razz'),  | ||||||
|               '7 Card Stud' : ('stud','studhi'), |                           '7 Card Stud' : ('stud','studhi'), | ||||||
|         '7 Card Stud Hi/Lo' : ('stud','studhilo'), |                     '7 Card Stud Hi/Lo' : ('stud','studhilo'), | ||||||
|                    'Badugi' : ('draw','badugi') |                                'Badugi' : ('draw','badugi'), | ||||||
|  |               'Triple Draw 2-7 Lowball' : ('draw','27_3draw'), | ||||||
|                } |                } | ||||||
|         currencies = { u'€':'EUR', '$':'USD', '':'T$' } |         currencies = { u'€':'EUR', '$':'USD', '':'T$' } | ||||||
|  | #    I don't think this is doing what we think. mg will always have all  | ||||||
|  | #    the expected keys, but the ones that didn't match in the regex will | ||||||
|  | #    have a value of None. It is OK if it throws an exception when it  | ||||||
|  | #    runs across an unknown game or limit or whatever. | ||||||
|         if 'LIMIT' in mg: |         if 'LIMIT' in mg: | ||||||
|             info['limitType'] = limits[mg['LIMIT']] |             info['limitType'] = limits[mg['LIMIT']] | ||||||
|         if 'GAME' in mg: |         if 'GAME' in mg: | ||||||
|  | @ -109,8 +148,13 @@ follow :  whether to tail -f the input""" | ||||||
|             info['bb'] = mg['BB'] |             info['bb'] = mg['BB'] | ||||||
|         if 'CURRENCY' in mg: |         if 'CURRENCY' in mg: | ||||||
|             info['currency'] = currencies[mg['CURRENCY']] |             info['currency'] = currencies[mg['CURRENCY']] | ||||||
|         # NB: SB, BB must be interpreted as blinds or bets depending on limit type. |  | ||||||
| 
 | 
 | ||||||
|  |         if 'TOURNO' in mg and mg['TOURNO'] == None: | ||||||
|  |             info['type'] = 'ring' | ||||||
|  |         else: | ||||||
|  |             info['type'] = 'tour' | ||||||
|  | 
 | ||||||
|  |         # NB: SB, BB must be interpreted as blinds or bets depending on limit type. | ||||||
|         return info |         return info | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -119,14 +163,13 @@ follow :  whether to tail -f the input""" | ||||||
|         m = self.re_HandInfo.search(hand.handText,re.DOTALL) |         m = self.re_HandInfo.search(hand.handText,re.DOTALL) | ||||||
|         if m: |         if m: | ||||||
|             info.update(m.groupdict()) |             info.update(m.groupdict()) | ||||||
|             # TODO: Be less lazy and parse maxseats from the HandInfo regex | #                hand.maxseats = int(m2.group(1)) | ||||||
|             if m.group('TABLEATTRIBUTES'): |         else: | ||||||
|                 m2 = re.search("\s*(\d+)-max", m.group('TABLEATTRIBUTES')) |             pass  # throw an exception here, eh? | ||||||
|                 hand.maxseats = int(m2.group(1)) |  | ||||||
|         m = self.re_GameInfo.search(hand.handText) |         m = self.re_GameInfo.search(hand.handText) | ||||||
|         if m: info.update(m.groupdict()) |         if m: info.update(m.groupdict()) | ||||||
|         m = self.re_Button.search(hand.handText) | #        m = self.re_Button.search(hand.handText) | ||||||
|         if m: info.update(m.groupdict())  | #        if m: info.update(m.groupdict())  | ||||||
|         # TODO : I rather like the idea of just having this dict as hand.info |         # TODO : I rather like the idea of just having this dict as hand.info | ||||||
|         logging.debug("readHandInfo: %s" % info) |         logging.debug("readHandInfo: %s" % info) | ||||||
|         for key in info: |         for key in info: | ||||||
|  | @ -143,6 +186,22 @@ follow :  whether to tail -f the input""" | ||||||
|                 hand.tablename = info[key] |                 hand.tablename = info[key] | ||||||
|             if key == 'BUTTON': |             if key == 'BUTTON': | ||||||
|                 hand.buttonpos = info[key] |                 hand.buttonpos = info[key] | ||||||
|  |             if key == 'MAX': | ||||||
|  |                 hand.maxseats = int(info[key]) | ||||||
|  | 
 | ||||||
|  |             if key == 'MIXED': | ||||||
|  |                 if info[key] == None: hand.mixed = None | ||||||
|  |                 else:   hand.mixed = self.mixes[info[key]] | ||||||
|  | 
 | ||||||
|  |             if key == 'TOURNO': | ||||||
|  |                 hand.tourNo = info[key] | ||||||
|  |             if key == 'BUYIN': | ||||||
|  |                 hand.buyin = info[key] | ||||||
|  |             if key == 'LEVEL': | ||||||
|  |                 hand.level = info[key] | ||||||
|  |             if key == 'PLAY' and info['PLAY'] != None: | ||||||
|  | #                hand.currency = 'play' # overrides previously set value | ||||||
|  |                 hand.gametype['currency'] = 'play' | ||||||
| 
 | 
 | ||||||
|     def readButton(self, hand): |     def readButton(self, hand): | ||||||
|         m = self.re_Button.search(hand.handText) |         m = self.re_Button.search(hand.handText) | ||||||
|  | @ -211,78 +270,115 @@ follow :  whether to tail -f the input""" | ||||||
|         for a in self.re_PostBoth.finditer(hand.handText): |         for a in self.re_PostBoth.finditer(hand.handText): | ||||||
|             hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB')) |             hand.addBlind(a.group('PNAME'), 'both', a.group('SBBB')) | ||||||
| 
 | 
 | ||||||
|  | #    def readHeroCards(self, hand): | ||||||
|  | #        m = self.re_HeroCards.search(hand.handText) | ||||||
|  | #        if(m == None): | ||||||
|  | #            #Not involved in hand | ||||||
|  | #            hand.involved = False | ||||||
|  | #        else: | ||||||
|  | #            hand.hero = m.group('PNAME') | ||||||
|  | #            # "2c, qh" -> set(["2c","qc"]) | ||||||
|  | #            # Also works with Omaha hands. | ||||||
|  | #            cards = m.group('NEWCARDS') | ||||||
|  | #            cards = set(cards.split(' ')) | ||||||
|  | #            hand.addHoleCards(cards, m.group('PNAME'), shown=False, mucked=False, dealt=True) | ||||||
|  | 
 | ||||||
|     def readHeroCards(self, hand): |     def readHeroCards(self, hand): | ||||||
|         m = self.re_HeroCards.search(hand.handText) | #    streets PREFLOP, PREDRAW, and THIRD are special cases beacause | ||||||
|         if(m == None): | #    we need to grab hero's cards | ||||||
|             #Not involved in hand |         for street in ('PREFLOP', 'DEAL'): | ||||||
|             hand.involved = False |             if street in hand.streets.keys(): | ||||||
|         else: |                 m = self.re_HeroCards.finditer(hand.streets[street]) | ||||||
|             hand.hero = m.group('PNAME') |                 for found in m: | ||||||
|             # "2c, qh" -> set(["2c","qc"]) | #                    if m == None: | ||||||
|             # Also works with Omaha hands. | #                        hand.involved = False | ||||||
|             cards = m.group('NEWCARDS') | #                    else: | ||||||
|             cards = set(cards.split(' ')) |                     hand.hero = found.group('PNAME') | ||||||
|             hand.addHoleCards(cards, m.group('PNAME')) |                     newcards = found.group('NEWCARDS').split(' ') | ||||||
|  |                     hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True) | ||||||
| 
 | 
 | ||||||
|     def readDrawCards(self, hand, street): |         for street, text in hand.streets.iteritems(): | ||||||
|         logging.debug("readDrawCards") |             if street in ('PREFLOP', 'DEAL'): continue  # already done these | ||||||
|         m = self.re_HeroCards.finditer(hand.streets[street]) |             m = self.re_HeroCards.finditer(hand.streets[street]) | ||||||
|         if m == None: |             for found in m: | ||||||
|             hand.involved = False |                 player = found.group('PNAME') | ||||||
|         else: |                 if found.group('NEWCARDS') == None: | ||||||
|             for player in m: |                     newcards = [] | ||||||
|                 hand.hero = player.group('PNAME') # Only really need to do this once |  | ||||||
|                 newcards = player.group('NEWCARDS') |  | ||||||
|                 oldcards = player.group('OLDCARDS') |  | ||||||
|                 if newcards == None: |  | ||||||
|                     newcards = set() |  | ||||||
|                 else: |                 else: | ||||||
|                     newcards = set(newcards.split(' ')) |                     newcards = found.group('NEWCARDS').split(' ') | ||||||
|                 if oldcards == None: |                 if found.group('OLDCARDS') == None: | ||||||
|                     oldcards = set() |                     oldcards = [] | ||||||
|                 else: |                 else: | ||||||
|                     oldcards = set(oldcards.split(' ')) |                     oldcards = found.group('OLDCARDS').split(' ') | ||||||
|                 hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street) | 
 | ||||||
|  |                 if street == 'THIRD' and len(newcards) == 3: # hero in stud game | ||||||
|  |                     hand.hero = player | ||||||
|  |                     hand.dealt.add(player) # need this for stud?? | ||||||
|  |                     hand.addHoleCards(street, player, closed=newcards[0:2], open=[newcards[2]], shown=False, mucked=False, dealt=False) | ||||||
|  |                 else: | ||||||
|  |                     hand.addHoleCards(street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False) | ||||||
| 
 | 
 | ||||||
|              |              | ||||||
|     def readStudPlayerCards(self, hand, street): | #    def readDrawCards(self, hand, street): | ||||||
|         # See comments of reference implementation in FullTiltToFpdb.py | #        logging.debug("readDrawCards") | ||||||
|         logging.debug("readStudPlayerCards") | #        m = self.re_HeroCards.finditer(hand.streets[street]) | ||||||
|         m = self.re_HeroCards.finditer(hand.streets[street]) | #        if m == None: | ||||||
|         for player in m: | #            hand.involved = False | ||||||
|             #~ logging.debug(player.groupdict()) | #        else: | ||||||
|             (pname,  oldcards,  newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS')) | #            for player in m: | ||||||
|             if oldcards: | #                hand.hero = player.group('PNAME') # Only really need to do this once | ||||||
|                 oldcards = [c.strip() for c in oldcards.split(' ')] | #                newcards = player.group('NEWCARDS') | ||||||
|             if newcards: | #                oldcards = player.group('OLDCARDS') | ||||||
|                 newcards = [c.strip() for c in newcards.split(' ')] | #                if newcards == None: | ||||||
|             if street=='ANTES': | #                    newcards = set() | ||||||
|                 return | #                else: | ||||||
|             elif street=='THIRD': | #                    newcards = set(newcards.split(' ')) | ||||||
|                 # we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS' | #                if oldcards == None: | ||||||
|                 # hero: [xx][o] | #                    oldcards = set() | ||||||
|                 # others: [o] | #                else: | ||||||
|                 hand.addPlayerCards(player = player.group('PNAME'), street = street,  closed = oldcards,  open = newcards) | #                    oldcards = set(oldcards.split(' ')) | ||||||
|             elif street in ('FOURTH',  'FIFTH',  'SIXTH'): | #                hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street) | ||||||
|                 # 4th: | 
 | ||||||
|                 # hero: [xxo] [o] | 
 | ||||||
|                 # others: [o] [o] | #    def readStudPlayerCards(self, hand, street): | ||||||
|                 # 5th: | #        # See comments of reference implementation in FullTiltToFpdb.py | ||||||
|                 # hero: [xxoo] [o] | #        logging.debug("readStudPlayerCards") | ||||||
|                 # others: [oo] [o] | #        m = self.re_HeroCards.finditer(hand.streets[street]) | ||||||
|                 # 6th: | #        for player in m: | ||||||
|                 # hero: [xxooo] [o] | #            #~ logging.debug(player.groupdict()) | ||||||
|                 # others:  [ooo] [o] | #            (pname,  oldcards,  newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS')) | ||||||
|                 hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards) | #            if oldcards: | ||||||
|                 # we may additionally want to check the earlier streets tally with what we have but lets trust it for now. | #                oldcards = [c.strip() for c in oldcards.split(' ')] | ||||||
|             elif street=='SEVENTH' and newcards: | #            if newcards: | ||||||
|                 # hero: [xxoooo] [x] | #                newcards = [c.strip() for c in newcards.split(' ')] | ||||||
|                 # others: not reported. | #            if street=='ANTES': | ||||||
|                 hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards) | #                return | ||||||
|  | #            elif street=='THIRD': | ||||||
|  | #                # we'll have observed hero holecards in CARDS and thirdstreet open cards in 'NEWCARDS' | ||||||
|  | #                # hero: [xx][o] | ||||||
|  | #                # others: [o] | ||||||
|  | #                hand.addPlayerCards(player = player.group('PNAME'), street = street,  closed = oldcards,  open = newcards) | ||||||
|  | #            elif street in ('FOURTH',  'FIFTH',  'SIXTH'): | ||||||
|  | #                # 4th: | ||||||
|  | #                # hero: [xxo] [o] | ||||||
|  | #                # others: [o] [o] | ||||||
|  | #                # 5th: | ||||||
|  | #                # hero: [xxoo] [o] | ||||||
|  | #                # others: [oo] [o] | ||||||
|  | #                # 6th: | ||||||
|  | #                # hero: [xxooo] [o] | ||||||
|  | #                # others:  [ooo] [o] | ||||||
|  | #                hand.addPlayerCards(player = player.group('PNAME'), street = street, open = newcards) | ||||||
|  | #                # we may additionally want to check the earlier streets tally with what we have but lets trust it for now. | ||||||
|  | #            elif street=='SEVENTH' and newcards: | ||||||
|  | #                # hero: [xxoooo] [x] | ||||||
|  | #                # others: not reported. | ||||||
|  | #                hand.addPlayerCards(player = player.group('PNAME'), street = street, closed = newcards) | ||||||
| 
 | 
 | ||||||
|     def readAction(self, hand, street): |     def readAction(self, hand, street): | ||||||
|         m = self.re_Action.finditer(hand.streets[street]) |         m = self.re_Action.finditer(hand.streets[street]) | ||||||
|         for action in m: |         for action in m: | ||||||
|  |             acts = action.groupdict() | ||||||
|             if action.group('ATYPE') == ' raises': |             if action.group('ATYPE') == ' raises': | ||||||
|                 hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') ) |                 hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') ) | ||||||
|             elif action.group('ATYPE') == ' calls': |             elif action.group('ATYPE') == ' calls': | ||||||
|  | @ -294,7 +390,7 @@ follow :  whether to tail -f the input""" | ||||||
|             elif action.group('ATYPE') == ' checks': |             elif action.group('ATYPE') == ' checks': | ||||||
|                 hand.addCheck( street, action.group('PNAME')) |                 hand.addCheck( street, action.group('PNAME')) | ||||||
|             elif action.group('ATYPE') == ' discards': |             elif action.group('ATYPE') == ' discards': | ||||||
|                 hand.addDiscard(street, action.group('PNAME'), action.group('NODISCARDED'), action.group('DISCARDED')) |                 hand.addDiscard(street, action.group('PNAME'), action.group('BET'), action.group('DISCARDED')) | ||||||
|             elif action.group('ATYPE') == ' stands pat': |             elif action.group('ATYPE') == ' stands pat': | ||||||
|                 hand.addStandsPat( street, action.group('PNAME')) |                 hand.addStandsPat( street, action.group('PNAME')) | ||||||
|             else: |             else: | ||||||
|  | @ -302,9 +398,9 @@ follow :  whether to tail -f the input""" | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|     def readShowdownActions(self, hand): |     def readShowdownActions(self, hand): | ||||||
|  | # TODO: pick up mucks also | ||||||
|         for shows in self.re_ShowdownAction.finditer(hand.handText):             |         for shows in self.re_ShowdownAction.finditer(hand.handText):             | ||||||
|             cards = shows.group('CARDS') |             cards = shows.group('CARDS').split(' ') | ||||||
|             cards = set(cards.split(' ')) |  | ||||||
|             hand.addShownCards(cards, shows.group('PNAME')) |             hand.addShownCards(cards, shows.group('PNAME')) | ||||||
| 
 | 
 | ||||||
|     def readCollectPot(self,hand): |     def readCollectPot(self,hand): | ||||||
|  | @ -315,8 +411,13 @@ follow :  whether to tail -f the input""" | ||||||
|         for m in self.re_ShownCards.finditer(hand.handText): |         for m in self.re_ShownCards.finditer(hand.handText): | ||||||
|             if m.group('CARDS') is not None: |             if m.group('CARDS') is not None: | ||||||
|                 cards = m.group('CARDS') |                 cards = m.group('CARDS') | ||||||
|                 cards = set(cards.split(' ')) |                 cards = cards.split(' ') # needs to be a list, not a set--stud needs the order | ||||||
|                 hand.addShownCards(cards=cards, player=m.group('PNAME')) | 
 | ||||||
|  |                 (shown, mucked) = (False, False) | ||||||
|  |                 if m.group('SHOWED') == "showed": shown = True | ||||||
|  |                 elif m.group('SHOWED') == "mucked": mucked = True | ||||||
|  | 
 | ||||||
|  |                 hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked) | ||||||
| 
 | 
 | ||||||
| if __name__ == "__main__": | if __name__ == "__main__": | ||||||
|     parser = OptionParser() |     parser = OptionParser() | ||||||
|  |  | ||||||
|  | @ -542,18 +542,13 @@ class Sql: | ||||||
| 
 | 
 | ||||||
|             self.query['get_common_cards'] = """ |             self.query['get_common_cards'] = """ | ||||||
|                     select |                     select | ||||||
|                         card1Value AS card1value, |                     boardcard1,  | ||||||
|                         card1Suit  AS card1suit, |                     boardcard2,  | ||||||
|                         card2Value AS card2value, |                     boardcard3,  | ||||||
|                         card2Suit  AS card2suit, |                     boardcard4,  | ||||||
|                         card3Value AS card3value, |                     boardcard5  | ||||||
|                         card3Suit  AS card3suit, |                     from Hands | ||||||
|                         card4Value AS card4value, |                     where Id = %s | ||||||
|                         card4Suit  AS card4suit, |  | ||||||
|                         card5Value AS card5value, |  | ||||||
|                         card5Suit  AS card5suit |  | ||||||
|                     from BoardCards |  | ||||||
|                     where handId = %s |  | ||||||
|                 """ |                 """ | ||||||
| 
 | 
 | ||||||
|             self.query['get_action_from_hand'] = """ |             self.query['get_action_from_hand'] = """ | ||||||
|  |  | ||||||
|  | @ -231,7 +231,7 @@ def discover_nt_by_name(c, tablename): | ||||||
|     titles = {} |     titles = {} | ||||||
|     win32gui.EnumWindows(win_enum_handler, titles) |     win32gui.EnumWindows(win_enum_handler, titles) | ||||||
|     for hwnd in titles: |     for hwnd in titles: | ||||||
|         print "Tbales.py: tablename =", tablename, "title =", titles[hwnd] |         #print "Tables.py: tablename =", tablename, "title =", titles[hwnd] | ||||||
|         try: |         try: | ||||||
|             # this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html |             # this can blow up in XP on some windows, eg firefox displaying http://docs.python.org/tutorial/classes.html | ||||||
|             if not tablename in titles[hwnd]: continue |             if not tablename in titles[hwnd]: continue | ||||||
|  | @ -314,6 +314,10 @@ def get_site_from_exe(c, exe): | ||||||
|             return params['site_name'] |             return params['site_name'] | ||||||
|     return None |     return None | ||||||
| 
 | 
 | ||||||
|  | def everleaf_decode_table(tw): | ||||||
|  | # 2 - Tournament ID: 573256 - NL Hold'em - 150/300 blinds - Good luck <username>! - [Connection is ...]     | ||||||
|  |     pass | ||||||
|  | 
 | ||||||
| def pokerstars_decode_table(tw): | def pokerstars_decode_table(tw): | ||||||
| #    Extract poker information from the window title.  This is not needed for | #    Extract poker information from the window title.  This is not needed for | ||||||
| #    fpdb, since all that information is available in the db via new_hand_number. | #    fpdb, since all that information is available in the db via new_hand_number. | ||||||
|  | @ -365,7 +369,7 @@ def clean_title(name): | ||||||
|     for pattern in [' \(6 max\)', ' \(heads up\)', ' \(deep\)', |     for pattern in [' \(6 max\)', ' \(heads up\)', ' \(deep\)', | ||||||
|                 ' \(deep hu\)', ' \(deep 6\)', ' \(2\)', |                 ' \(deep hu\)', ' \(deep 6\)', ' \(2\)', | ||||||
|                 ' \(edu\)', ' \(edu, 6 max\)', ' \(6\)', |                 ' \(edu\)', ' \(edu, 6 max\)', ' \(6\)', | ||||||
|                 ' \(speed\)',  |                 ' \(speed\)', 'special', 'newVPP',  | ||||||
|                 ' no all-in', ' fast', ',', ' 50BB min', '50bb min', '\s+$']: |                 ' no all-in', ' fast', ',', ' 50BB min', '50bb min', '\s+$']: | ||||||
|         name = re.sub(pattern, '', name) |         name = re.sub(pattern, '', name) | ||||||
|     name = name.rstrip() |     name = name.rstrip() | ||||||
|  |  | ||||||
|  | @ -92,6 +92,8 @@ if __name__=="__main__": | ||||||
|     print "game =", table.get_game() |     print "game =", table.get_game() | ||||||
| 
 | 
 | ||||||
|     fake = fake_hud(table) |     fake = fake_hud(table) | ||||||
|  |     print "fake =", fake | ||||||
|     gobject.timeout_add(100, check_on_table, table, fake) |     gobject.timeout_add(100, check_on_table, table, fake) | ||||||
|  |     print "calling main" | ||||||
|     gtk.main() |     gtk.main() | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -65,8 +65,11 @@ class Table(Table_Window): | ||||||
|         print "x = %s y = %s width = %s height = %s" % (x, y, width, height) |         print "x = %s y = %s width = %s height = %s" % (x, y, width, height) | ||||||
|         self.x      = int(x) + b_width |         self.x      = int(x) + b_width | ||||||
|         self.y      = int(y) + tb_height |         self.y      = int(y) + tb_height | ||||||
|         self.height = int(height) - b_width - tb_height |         self.width  = width - x | ||||||
|         self.width  = int(width) - 2*b_width |         self.height = height - y | ||||||
|  |         print "x = %s y = %s width = %s height = %s" % (self.x, self.y, self.width, self.height) | ||||||
|  |         #self.height = int(height) - b_width - tb_height | ||||||
|  |         #self.width  = int(width) - 2*b_width | ||||||
|          |          | ||||||
|         self.exe    = self.get_nt_exe(hwnd) |         self.exe    = self.get_nt_exe(hwnd) | ||||||
|         self.title  = titles[hwnd] |         self.title  = titles[hwnd] | ||||||
|  | @ -76,12 +79,13 @@ class Table(Table_Window): | ||||||
|         self.gdkhandle = gtk.gdk.window_foreign_new(long(self.window)) |         self.gdkhandle = gtk.gdk.window_foreign_new(long(self.window)) | ||||||
| 
 | 
 | ||||||
|     def get_geometry(self): |     def get_geometry(self): | ||||||
| 
 |         if not win32gui.IsWindow(self.number):  # window closed | ||||||
|         if not win32gui.IsWindow(self.window):  # window closed |  | ||||||
|             return None |             return None | ||||||
| 
 | 
 | ||||||
|         try: |         try: | ||||||
|             (x, y, width, height) = win32gui.GetWindowRect(hwnd) |             (x, y, width, height) = win32gui.GetWindowRect(self.number) | ||||||
|  |             width = width - x | ||||||
|  |             height = height - y | ||||||
|             return {'x'      : int(x) + b_width, |             return {'x'      : int(x) + b_width, | ||||||
|                     'y'      : int(y) + tb_height, |                     'y'      : int(y) + tb_height, | ||||||
|                     'width'  : int(height) - b_width - tb_height, |                     'width'  : int(height) - b_width - tb_height, | ||||||
|  | @ -116,27 +120,32 @@ class Table(Table_Window): | ||||||
|     def topify(self, hud): |     def topify(self, hud): | ||||||
|         """Set the specified gtk window to stayontop in MS Windows.""" |         """Set the specified gtk window to stayontop in MS Windows.""" | ||||||
|      |      | ||||||
|         def windowEnumerationHandler(hwnd, resultList): | #        def windowEnumerationHandler(hwnd, resultList): | ||||||
|             '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | #            '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | ||||||
|             resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | #            resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | ||||||
|      | #     | ||||||
|         unique_name = 'unique name for finding this window' | #        unique_name = 'unique name for finding this window' | ||||||
|         real_name = hud.main_window.get_title() | #        real_name = hud.main_window.get_title() | ||||||
|         hud.main_window.set_title(unique_name) | #        hud.main_window.set_title(unique_name) | ||||||
|         tl_windows = [] | #        tl_windows = [] | ||||||
|         win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | #        win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | ||||||
|              | #             | ||||||
|         for w in tl_windows: | #        for w in tl_windows: | ||||||
|             if w[1] == unique_name: | #            if w[1] == unique_name: | ||||||
|                 hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) | #                hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) | ||||||
|                 hud.main_window.gdkhandle.set_transient_for(self.gdkhandle) |         hud.main_window.gdkhandle = hud.main_window.window | ||||||
|  |         hud.main_window.gdkhandle.set_transient_for(self.gdkhandle) | ||||||
|  |         rect = self.gdkhandle.get_frame_extents() | ||||||
|  |         (innerx, innery) = self.gdkhandle.get_origin() | ||||||
|  |         b_width = rect.x - innerx | ||||||
|  |         tb_height = rect.y - innery | ||||||
| #                 | #                 | ||||||
| #                style = win32gui.GetWindowLong(self.number, win32con.GWL_EXSTYLE) | #                style = win32gui.GetWindowLong(self.number, win32con.GWL_EXSTYLE) | ||||||
| #                style |= win32con.WS_CLIPCHILDREN | #                style |= win32con.WS_CLIPCHILDREN | ||||||
| #                win32gui.SetWindowLong(self.number, win32con.GWL_EXSTYLE, style) | #                win32gui.SetWindowLong(self.number, win32con.GWL_EXSTYLE, style) | ||||||
|                 break | #                break | ||||||
|                  |                  | ||||||
|         hud.main_window.set_title(real_name) | #        hud.main_window.set_title(real_name) | ||||||
| 
 | 
 | ||||||
| def win_enum_handler(hwnd, titles): | def win_enum_handler(hwnd, titles): | ||||||
|     titles[hwnd] = win32gui.GetWindowText(hwnd) |     titles[hwnd] = win32gui.GetWindowText(hwnd) | ||||||
|  |  | ||||||
							
								
								
									
										101
									
								
								pyfpdb/fpdb.py
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								pyfpdb/fpdb.py
									
									
									
									
									
								
							|  | @ -33,7 +33,7 @@ import pygtk | ||||||
| pygtk.require('2.0') | pygtk.require('2.0') | ||||||
| import gtk | import gtk | ||||||
| 
 | 
 | ||||||
| import fpdb_db | 
 | ||||||
| import fpdb_simple | import fpdb_simple | ||||||
| import GuiBulkImport | import GuiBulkImport | ||||||
| import GuiPlayerStats | import GuiPlayerStats | ||||||
|  | @ -42,6 +42,8 @@ import GuiTableViewer | ||||||
| import GuiAutoImport | import GuiAutoImport | ||||||
| import GuiGraphViewer | import GuiGraphViewer | ||||||
| import GuiSessionViewer | import GuiSessionViewer | ||||||
|  | import SQL | ||||||
|  | import Database | ||||||
| import FpdbSQLQueries | import FpdbSQLQueries | ||||||
| import Configuration | import Configuration | ||||||
| 
 | 
 | ||||||
|  | @ -179,20 +181,21 @@ class fpdb: | ||||||
|     def dia_load_profile(self, widget, data=None): |     def dia_load_profile(self, widget, data=None): | ||||||
|         """Dialogue to select a file to load a profile from""" |         """Dialogue to select a file to load a profile from""" | ||||||
|         if self.obtain_global_lock() == 0:  # returns 0 if successful |         if self.obtain_global_lock() == 0:  # returns 0 if successful | ||||||
|             try: |             #try: | ||||||
|                 chooser = gtk.FileChooserDialog(title="Please select a profile file to load", |             #    chooser = gtk.FileChooserDialog(title="Please select a profile file to load", | ||||||
|                         action=gtk.FILE_CHOOSER_ACTION_OPEN, |             #            action=gtk.FILE_CHOOSER_ACTION_OPEN, | ||||||
|                         buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) |             #            buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) | ||||||
|                 chooser.set_filename(self.profile) |             #    chooser.set_filename(self.profile) | ||||||
| 
 | 
 | ||||||
|                 response = chooser.run() |             #    response = chooser.run() | ||||||
|                 chooser.destroy()     |             #    chooser.destroy()     | ||||||
|                 if response == gtk.RESPONSE_OK: |             #    if response == gtk.RESPONSE_OK: | ||||||
|                     self.load_profile(chooser.get_filename()) |             #        self.load_profile(chooser.get_filename()) | ||||||
|                 elif response == gtk.RESPONSE_CANCEL: |             #    elif response == gtk.RESPONSE_CANCEL: | ||||||
|                     print 'User cancelled loading profile' |             #        print 'User cancelled loading profile' | ||||||
|             except: |             #except: | ||||||
|                 pass |             #    pass | ||||||
|  |             self.load_profile() | ||||||
|             self.release_global_lock() |             self.release_global_lock() | ||||||
|     #end def dia_load_profile |     #end def dia_load_profile | ||||||
| 
 | 
 | ||||||
|  | @ -204,22 +207,23 @@ class fpdb: | ||||||
|             try: |             try: | ||||||
|                 dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, |                 dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, | ||||||
|                         buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") |                         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." |                 diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database " \ | ||||||
|  |                             +self.db.fdb.database+" on "+self.db.fdb.host+" they will be deleted." | ||||||
|                 dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted |                 dia_confirm.format_secondary_text(diastring)#todo: make above string with bold for db, host and deleted | ||||||
| 
 | 
 | ||||||
|                 response = dia_confirm.run() |                 response = dia_confirm.run() | ||||||
|                 dia_confirm.destroy() |                 dia_confirm.destroy() | ||||||
|                 if response == gtk.RESPONSE_YES: |                 if response == gtk.RESPONSE_YES: | ||||||
|                     if self.db.backend == self.fdb_lock.MYSQL_INNODB: |                     if self.db.fdb.backend == self.fdb_lock.fdb.MYSQL_INNODB: | ||||||
|                         # mysql requires locks on all tables or none - easier to release this lock  |                         # mysql requires locks on all tables or none - easier to release this lock  | ||||||
|                         # than lock all the other tables |                         # than lock all the other tables | ||||||
|                         # ToDo: lock all other tables so that lock doesn't have to be released |                         # ToDo: lock all other tables so that lock doesn't have to be released | ||||||
|                         self.release_global_lock() |                         self.release_global_lock() | ||||||
|                         lock_released = True |                         lock_released = True | ||||||
|                         self.db.recreate_tables() |                         self.db.fdb.recreate_tables() | ||||||
|                     else: |                     else: | ||||||
|                         # for other dbs use same connection as holds global lock |                         # for other dbs use same connection as holds global lock | ||||||
|                         self.fdb_lock.recreate_tables() |                         self.fdb_lock.fdb.recreate_tables() | ||||||
|                 elif response == gtk.RESPONSE_NO: |                 elif response == gtk.RESPONSE_NO: | ||||||
|                     print 'User cancelled recreating tables' |                     print 'User cancelled recreating tables' | ||||||
|             except: |             except: | ||||||
|  | @ -347,6 +351,7 @@ class fpdb: | ||||||
| 
 | 
 | ||||||
|     def load_profile(self): |     def load_profile(self): | ||||||
|         """Loads profile from the provided path name.""" |         """Loads profile from the provided path name.""" | ||||||
|  |         self.config = Configuration.Config(file=options.config, dbname=options.dbname) | ||||||
|         self.settings = {} |         self.settings = {} | ||||||
|         if (os.sep=="/"): |         if (os.sep=="/"): | ||||||
|             self.settings['os']="linuxmac" |             self.settings['os']="linuxmac" | ||||||
|  | @ -359,17 +364,13 @@ class fpdb: | ||||||
|         self.settings.update(self.config.get_import_parameters()) |         self.settings.update(self.config.get_import_parameters()) | ||||||
|         self.settings.update(self.config.get_default_paths()) |         self.settings.update(self.config.get_default_paths()) | ||||||
| 
 | 
 | ||||||
|         if self.db!=None: |         if self.db != None and self.db.fdb != None: | ||||||
|             self.db.disconnect() |             self.db.disconnect() | ||||||
| 
 | 
 | ||||||
|         self.db = fpdb_db.fpdb_db() |         self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) | ||||||
|         #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] |         self.db = Database.Database(self.config, sql = self.sql) | ||||||
|         self.db.connect(self.settings['db-backend'], | 
 | ||||||
|             self.settings['db-host'], |         if self.db.fdb.wrongDbVersion: | ||||||
|             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)) |             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.") |             label = gtk.Label("An invalid DB version or missing tables have been detected.") | ||||||
|  | @ -387,9 +388,16 @@ class fpdb: | ||||||
|             response = diaDbVersionWarning.run() |             response = diaDbVersionWarning.run() | ||||||
|             diaDbVersionWarning.destroy() |             diaDbVersionWarning.destroy() | ||||||
| 
 | 
 | ||||||
|  |         if self.status_bar == None: | ||||||
|  |             self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) | ||||||
|  |             self.main_vbox.pack_end(self.status_bar, False, True, 0) | ||||||
|  |             self.status_bar.show() | ||||||
|  |         else: | ||||||
|  |             self.status_bar.set_text("Status: Connected to %s database named %s on host %s" % (self.db.get_backend_name(),self.db.fdb.database, self.db.fdb.host)) | ||||||
|  | 
 | ||||||
|         # Database connected to successfully, load queries to pass on to other classes |         # Database connected to successfully, load queries to pass on to other classes | ||||||
|         self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) |         self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) | ||||||
|         self.db.db.rollback() |         self.db.connection.rollback() | ||||||
|     #end def load_profile |     #end def load_profile | ||||||
| 
 | 
 | ||||||
|     def not_implemented(self, widget, data=None): |     def not_implemented(self, widget, data=None): | ||||||
|  | @ -398,13 +406,9 @@ class fpdb: | ||||||
| 
 | 
 | ||||||
|     def obtain_global_lock(self): |     def obtain_global_lock(self): | ||||||
|         print "\nTaking global lock ..." |         print "\nTaking global lock ..." | ||||||
|         self.fdb_lock = fpdb_db.fpdb_db() |         self.fdb_lock = Database.Database(self.config, sql = self.sql) | ||||||
|         self.fdb_lock.connect(self.settings['db-backend'], |         self.fdb_lock.do_connect(self.config) | ||||||
|                               self.settings['db-host'], |         return self.fdb_lock.fdb.get_global_lock() | ||||||
|                               self.settings['db-databaseName'], |  | ||||||
|                               self.settings['db-user'],  |  | ||||||
|                               self.settings['db-password']) |  | ||||||
|         return self.fdb_lock.get_global_lock() |  | ||||||
|     #end def obtain_global_lock |     #end def obtain_global_lock | ||||||
| 
 | 
 | ||||||
|     def quit(self, widget, data=None): |     def quit(self, widget, data=None): | ||||||
|  | @ -415,9 +419,9 @@ class fpdb: | ||||||
|     #end def quit_cliecked |     #end def quit_cliecked | ||||||
| 
 | 
 | ||||||
|     def release_global_lock(self): |     def release_global_lock(self): | ||||||
|         self.fdb_lock.db.rollback() |         self.fdb_lock.fdb.db.rollback() | ||||||
|         self.fdb_lock.disconnect() |         self.fdb_lock.fdb.disconnect() | ||||||
|         print "Global lock released." |         print "Global lock released.\n" | ||||||
|     #end def release_global_lock |     #end def release_global_lock | ||||||
| 
 | 
 | ||||||
|     def tab_abbreviations(self, widget, data=None): |     def tab_abbreviations(self, widget, data=None): | ||||||
|  | @ -466,7 +470,7 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") | ||||||
|     def tab_table_viewer(self, widget, data=None): |     def tab_table_viewer(self, widget, data=None): | ||||||
|         """opens a table viewer tab""" |         """opens a table viewer tab""" | ||||||
|         #print "start of tab_table_viewer" |         #print "start of tab_table_viewer" | ||||||
|         new_tv_thread=GuiTableViewer.GuiTableViewer(self.db, self.settings) |         new_tv_thread=GuiTableViewer.GuiTableViewer(self.db.fdb, self.settings) | ||||||
|         self.threads.append(new_tv_thread) |         self.threads.append(new_tv_thread) | ||||||
|         tv_tab=new_tv_thread.get_vbox() |         tv_tab=new_tv_thread.get_vbox() | ||||||
|         self.add_and_display_tab(tv_tab, "Table Viewer") |         self.add_and_display_tab(tv_tab, "Table Viewer") | ||||||
|  | @ -475,22 +479,16 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") | ||||||
|     def tabGraphViewer(self, widget, data=None): |     def tabGraphViewer(self, widget, data=None): | ||||||
|         """opens a graph viewer tab""" |         """opens a graph viewer tab""" | ||||||
|         #print "start of tabGraphViewer" |         #print "start of tabGraphViewer" | ||||||
|         new_gv_thread=GuiGraphViewer.GuiGraphViewer(self.db, self.settings, self.querydict, self.config) |         new_gv_thread = GuiGraphViewer.GuiGraphViewer(self.querydict, self.config) | ||||||
|         self.threads.append(new_gv_thread) |         self.threads.append(new_gv_thread) | ||||||
|         gv_tab=new_gv_thread.get_vbox() |         gv_tab=new_gv_thread.get_vbox() | ||||||
|         self.add_and_display_tab(gv_tab, "Graphs") |         self.add_and_display_tab(gv_tab, "Graphs") | ||||||
|     #end def tabGraphViewer |     #end def tabGraphViewer | ||||||
| 
 | 
 | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|         LOG_FILENAME = './logging.out' |         self.threads = [] | ||||||
|         LOG_FORMAT = "%(asctime)-15s %(levelname)-8s %(message)s" |         self.db = None | ||||||
|         logging.basicConfig(filename=LOG_FILENAME,level=10,format=LOG_FORMAT) |         self.status_bar = None | ||||||
|         logging.info("Fpdb started") |  | ||||||
|          |  | ||||||
|         self.threads=[] |  | ||||||
|         self.db=None |  | ||||||
|         self.config = Configuration.Config(file=options.config, dbname=options.dbname) |  | ||||||
|         self.load_profile() |  | ||||||
| 
 | 
 | ||||||
|         self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) |         self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) | ||||||
|         self.window.connect("delete_event", self.delete_event) |         self.window.connect("delete_event", self.delete_event) | ||||||
|  | @ -525,11 +523,8 @@ This program is licensed under the AGPL3, see docs"""+os.sep+"agpl-3.0.txt") | ||||||
| 
 | 
 | ||||||
|         self.tab_main_help(None, None) |         self.tab_main_help(None, None) | ||||||
| 
 | 
 | ||||||
|         self.status_bar = gtk.Label("Status: Connected to %s database named %s on host %s"%(self.db.get_backend_name(),self.db.database, self.db.host)) |  | ||||||
|         self.main_vbox.pack_end(self.status_bar, False, True, 0) |  | ||||||
|         self.status_bar.show() |  | ||||||
| 
 |  | ||||||
|         self.window.show() |         self.window.show() | ||||||
|  |         self.load_profile() | ||||||
|         sys.stderr.write("fpdb starting ...") |         sys.stderr.write("fpdb starting ...") | ||||||
|     #end def __init__ |     #end def __init__ | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -255,7 +255,6 @@ class fpdb_db: | ||||||
|         self.cursor.execute(self.sql.query['createPlayersTable']) |         self.cursor.execute(self.sql.query['createPlayersTable']) | ||||||
|         self.cursor.execute(self.sql.query['createAutoratesTable']) |         self.cursor.execute(self.sql.query['createAutoratesTable']) | ||||||
|         self.cursor.execute(self.sql.query['createHandsTable']) |         self.cursor.execute(self.sql.query['createHandsTable']) | ||||||
|         self.cursor.execute(self.sql.query['createBoardCardsTable']) |  | ||||||
|         self.cursor.execute(self.sql.query['createTourneyTypesTable']) |         self.cursor.execute(self.sql.query['createTourneyTypesTable']) | ||||||
|         self.cursor.execute(self.sql.query['createTourneysTable']) |         self.cursor.execute(self.sql.query['createTourneysTable']) | ||||||
|         self.cursor.execute(self.sql.query['createTourneysPlayersTable']) |         self.cursor.execute(self.sql.query['createTourneysPlayersTable']) | ||||||
|  | @ -587,17 +586,18 @@ class fpdb_db: | ||||||
|         print "analyze took", atime, "seconds" |         print "analyze took", atime, "seconds" | ||||||
|     #end def analyzeDB |     #end def analyzeDB | ||||||
| 
 | 
 | ||||||
|     # Currently uses an exclusive lock on the Hands table as a global lock |     # Currently uses an exclusive lock on the Players table as a global lock  | ||||||
|  |     # ( Changed because Hands is used in Database.init() ) | ||||||
|     # Return values are Unix style, 0 for success, positive integers for errors |     # Return values are Unix style, 0 for success, positive integers for errors | ||||||
|     # 1 = generic error |     # 1 = generic error | ||||||
|     # 2 = hands table does not exist (error message is suppressed) |     # 2 = players table does not exist (error message is suppressed) | ||||||
|     def get_global_lock(self): |     def get_global_lock(self): | ||||||
|         if self.backend == self.MYSQL_INNODB: |         if self.backend == self.MYSQL_INNODB: | ||||||
|             try: |             try: | ||||||
|                 self.cursor.execute( "lock tables Hands write" ) |                 self.cursor.execute( "lock tables Players write" ) | ||||||
|             except: |             except: | ||||||
|                 # Table 'fpdb.hands' doesn't exist |                 # Table 'fpdb.players' doesn't exist | ||||||
|                 if str(sys.exc_value).find(".Hands' doesn't exist") >= 0: |                 if str(sys.exc_value).find(".Players' doesn't exist") >= 0: | ||||||
|                     return(2) |                     return(2) | ||||||
|                 print "Error! failed to obtain global lock. Close all programs accessing " \ |                 print "Error! failed to obtain global lock. Close all programs accessing " \ | ||||||
|                       + "database (including fpdb) and try again (%s)." \ |                       + "database (including fpdb) and try again (%s)." \ | ||||||
|  | @ -605,11 +605,11 @@ class fpdb_db: | ||||||
|                 return(1) |                 return(1) | ||||||
|         elif self.backend == self.PGSQL: |         elif self.backend == self.PGSQL: | ||||||
|             try: |             try: | ||||||
|                 self.cursor.execute( "lock table Hands in exclusive mode nowait" ) |                 self.cursor.execute( "lock table Players in exclusive mode nowait" ) | ||||||
|                 #print "... after lock table, status =", self.cursor.statusmessage |                 #print "... after lock table, status =", self.cursor.statusmessage | ||||||
|             except: |             except: | ||||||
|                 # relation "hands" does not exist |                 # relation "players" does not exist | ||||||
|                 if str(sys.exc_value).find('relation "hands" does not exist') >= 0: |                 if str(sys.exc_value).find('relation "players" does not exist') >= 0: | ||||||
|                     return(2) |                     return(2) | ||||||
|                 print "Error! failed to obtain global lock. Close all programs accessing " \ |                 print "Error! failed to obtain global lock. Close all programs accessing " \ | ||||||
|                       + "database (including fpdb) and try again (%s)." \ |                       + "database (including fpdb) and try again (%s)." \ | ||||||
|  |  | ||||||
|  | @ -32,6 +32,7 @@ import re | ||||||
| 
 | 
 | ||||||
| import fpdb_simple | import fpdb_simple | ||||||
| import fpdb_db | import fpdb_db | ||||||
|  | import Database | ||||||
| import fpdb_parse_logic | import fpdb_parse_logic | ||||||
| import Configuration | import Configuration | ||||||
| 
 | 
 | ||||||
|  | @ -58,7 +59,8 @@ class Importer: | ||||||
|         self.settings   = settings |         self.settings   = settings | ||||||
|         self.caller     = caller |         self.caller     = caller | ||||||
|         self.config     = config |         self.config     = config | ||||||
|         self.fdb        = None |         self.database   = None       # database will be the main db interface eventually | ||||||
|  |         self.fdb        = None       # fdb may disappear or just hold the simple db connection | ||||||
|         self.cursor     = None |         self.cursor     = None | ||||||
|         self.filelist   = {} |         self.filelist   = {} | ||||||
|         self.dirlist    = {} |         self.dirlist    = {} | ||||||
|  | @ -76,6 +78,7 @@ class Importer: | ||||||
|         self.settings.setdefault("minPrint", 30) |         self.settings.setdefault("minPrint", 30) | ||||||
|         self.settings.setdefault("handCount", 0) |         self.settings.setdefault("handCount", 0) | ||||||
|          |          | ||||||
|  |         self.database = Database.Database(self.config)  # includes .connection and .sql variables | ||||||
|         self.fdb = fpdb_db.fpdb_db()   # sets self.fdb.db self.fdb.cursor and self.fdb.sql |         self.fdb = fpdb_db.fpdb_db()   # sets self.fdb.db self.fdb.cursor and self.fdb.sql | ||||||
|         self.fdb.do_connect(self.config) |         self.fdb.do_connect(self.config) | ||||||
|         self.fdb.db.rollback() |         self.fdb.db.rollback() | ||||||
|  | @ -393,8 +396,9 @@ class Importer: | ||||||
|                     self.hand=hand |                     self.hand=hand | ||||||
| 
 | 
 | ||||||
|                     try: |                     try: | ||||||
|                         handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb |                         handsId = fpdb_parse_logic.mainParser( self.settings, self.fdb | ||||||
|                                                            , self.siteIds[site], category, hand, self.config) |                                                              , self.siteIds[site], category, hand | ||||||
|  |                                                              , self.config, self.database ) | ||||||
|                         self.fdb.db.commit() |                         self.fdb.db.commit() | ||||||
| 
 | 
 | ||||||
|                         stored += 1 |                         stored += 1 | ||||||
|  |  | ||||||
|  | @ -21,10 +21,13 @@ import fpdb_simple | ||||||
| import Database | import Database | ||||||
| 
 | 
 | ||||||
| #parses a holdem hand | #parses a holdem hand | ||||||
| def mainParser(settings, fdb, siteID, category, hand, config): | def mainParser(settings, fdb, siteID, category, hand, config, db = None): | ||||||
|     backend = settings['db-backend'] |     backend = settings['db-backend'] | ||||||
|     #This is redundant - hopefully fdb will be a Database object in an interation soon |     if db == None: | ||||||
|     db = Database.Database(config, 'fpdb', '') |         #This is redundant - hopefully fdb will be a Database object in an iteration soon | ||||||
|  |         db = Database.Database(c = config, sql = None) | ||||||
|  |     else: | ||||||
|  |         db = db | ||||||
|     category = fpdb_simple.recogniseCategory(hand[0]) |     category = fpdb_simple.recogniseCategory(hand[0]) | ||||||
| 
 | 
 | ||||||
|     base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud" |     base = "hold" if category == "holdem" or category == "omahahi" or category == "omahahilo" else "stud" | ||||||
|  |  | ||||||
|  | @ -1136,16 +1136,6 @@ def storeActions(cursor, handsPlayersIds, actionTypes, allIns, actionAmounts, ac | ||||||
|     cursor.executemany("INSERT INTO HandsActions (handsPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)", inserts) |     cursor.executemany("INSERT INTO HandsActions (handsPlayerId, street, actionNo, action, allIn, amount) VALUES (%s, %s, %s, %s, %s, %s)", inserts) | ||||||
| #end def storeActions | #end def storeActions | ||||||
|   |   | ||||||
| def store_board_cards(cursor, hands_id, board_values, board_suits): |  | ||||||
| #stores into table board_cards |  | ||||||
|     cursor.execute ("""INSERT INTO BoardCards (handId, card1Value, card1Suit, |  | ||||||
| card2Value, card2Suit, card3Value, card3Suit, card4Value, card4Suit, |  | ||||||
| card5Value, card5Suit) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""", |  | ||||||
|     (hands_id, board_values[0], board_suits[0], board_values[1], board_suits[1], |  | ||||||
|     board_values[2], board_suits[2], board_values[3], board_suits[3], |  | ||||||
|     board_values[4], board_suits[4])) |  | ||||||
| #end def store_board_cards |  | ||||||
|   |  | ||||||
| def storeHands(backend, conn, cursor, site_hand_no, gametype_id | def storeHands(backend, conn, cursor, site_hand_no, gametype_id | ||||||
|               ,hand_start_time, names, tableName, maxSeats, hudCache, |               ,hand_start_time, names, tableName, maxSeats, hudCache, | ||||||
|               board_values, board_suits): |               board_values, board_suits): | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user