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.font         = node.getAttribute("font") | ||||
|         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.xpad         = node.getAttribute("xpad") | ||||
|         self.ypad         = node.getAttribute("ypad") | ||||
|         self.layout       = {} | ||||
| 
 | ||||
|         for layout_node in node.getElementsByTagName('layout'): | ||||
|             lo = Layout(layout_node) | ||||
|             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): | ||||
|         temp = "Site = " + self.site_name + "\n" | ||||
|         for key in dir(self): | ||||
|  | @ -119,9 +139,16 @@ class Stat: | |||
| class Game: | ||||
|     def __init__(self, node): | ||||
|         self.game_name = node.getAttribute("game_name") | ||||
|         self.db        = node.getAttribute("db") | ||||
|         self.rows      = int( node.getAttribute("rows") ) | ||||
|         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_list = aux_text.split(',') | ||||
|  | @ -146,9 +173,10 @@ class Game: | |||
|              | ||||
|     def __str__(self): | ||||
|         temp = "Game = " + self.game_name + "\n" | ||||
|         temp = temp + "    db = %s\n" % self.db | ||||
|         temp = temp + "    rows = %d\n" % self.rows | ||||
|         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 | ||||
|          | ||||
|         for stat in self.stats.keys(): | ||||
|  | @ -633,6 +661,8 @@ class Config: | |||
|         parms["font"]         = self.supported_sites[site].font | ||||
|         parms["font_size"]    = self.supported_sites[site].font_size | ||||
|         parms["enabled"]      = self.supported_sites[site].enabled | ||||
|         parms["xpad"]         = self.supported_sites[site].xpad | ||||
|         parms["ypad"]         = self.supported_sites[site].ypad | ||||
|         return parms | ||||
| 
 | ||||
|     def set_site_parameters(self, site_name, converter = None, decoder = None, | ||||
|  | @ -683,9 +713,10 @@ class Config: | |||
|         param = {} | ||||
|         if self.supported_games.has_key(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['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 | ||||
|         return param | ||||
| 
 | ||||
|  |  | |||
|  | @ -39,7 +39,8 @@ import SQL | |||
| import Card | ||||
| 
 | ||||
| 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.do_connect(c) | ||||
|         self.connection = self.fdb.db | ||||
|  | @ -48,7 +49,12 @@ class Database: | |||
|         self.import_options = c.get_import_parameters() | ||||
|         self.type = db_params['db-type'] | ||||
|         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() | ||||
|          | ||||
|                                    # To add to config: | ||||
|  | @ -81,6 +87,8 @@ class Database: | |||
|         #row = cur.fetchone() | ||||
|         self.saveActions = False if self.import_options['saveActions'] == False else True | ||||
| 
 | ||||
|     def do_connect(self, c): | ||||
|         self.fdb.do_connect(c) | ||||
| 
 | ||||
|     def commit(self): | ||||
|         self.fdb.db.commit() | ||||
|  | @ -88,6 +96,19 @@ class Database: | |||
|     def close_connection(self): | ||||
|         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): | ||||
|         c = self.connection.cursor() | ||||
|         c.execute(self.sql.query['get_table_name'], (hand_id, )) | ||||
|  | @ -138,12 +159,8 @@ class Database: | |||
|         cards = {} | ||||
|         c = self.connection.cursor() | ||||
|         c.execute(self.sql.query['get_common_cards'], [hand]) | ||||
|         colnames = [desc[0] for desc in c.description] | ||||
|         for row in c.fetchall(): | ||||
|             s_dict = {} | ||||
|             for name, val in zip(colnames, row): | ||||
|                 s_dict[name] = val | ||||
|             cards['common'] = (self.convert_cards(s_dict)) | ||||
| #        row = c.fetchone() | ||||
|         cards['common'] = c.fetchone() | ||||
|         return cards | ||||
| 
 | ||||
|     def convert_cards(self, d): | ||||
|  | @ -285,7 +302,8 @@ class Database: | |||
|         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 | ||||
|                                        ,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 | ||||
|         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': | ||||
|             fpdb_simple.storeHudCache(self.backend, cursor, base, category, gametype_id, hand_start_time, player_ids, hudImportData) | ||||
|         t5 = time() | ||||
|         fpdb_simple.store_board_cards(cursor, hands_id, board_values, board_suits) | ||||
|         t6 = time() | ||||
|         if self.saveActions: | ||||
|             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': | ||||
|             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: | ||||
|             fpdb_simple.storeActions(cursor, hands_players_ids, action_types, allIns, action_amounts, actionNos) | ||||
|         return hands_id | ||||
|  |  | |||
|  | @ -30,12 +30,11 @@ import fpdb_db | |||
| import FpdbSQLQueries | ||||
| 
 | ||||
| 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 | ||||
|         #print "start of GraphViewer constructor" | ||||
|         self.db=db | ||||
|         self.cursor=db.cursor | ||||
|         self.settings=settings | ||||
|         self.sql=qdict | ||||
|         self.conf = config | ||||
|         self.display = display | ||||
|  | @ -235,7 +234,7 @@ class Filters(threading.Thread): | |||
| 
 | ||||
|     def __set_hero_name(self, w, site): | ||||
|         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): | ||||
|         cb = gtk.CheckButton(site) | ||||
|  | @ -556,23 +555,12 @@ def main(argv=None): | |||
|     config = Configuration.Config() | ||||
|     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.connect(settings['db-backend'], | ||||
|                settings['db-host'], | ||||
|                settings['db-databaseName'], | ||||
|                settings['db-user'], | ||||
|                settings['db-password']) | ||||
|     db.do_connect(config) | ||||
| 
 | ||||
|     qdict = FpdbSQLQueries.FpdbSQLQueries(db.get_backend_name()) | ||||
| 
 | ||||
|     i = Filters(db, settings, config, qdict) | ||||
|     i = Filters(db, config, qdict) | ||||
|     main_window = gtk.Window() | ||||
|     main_window.connect('destroy', destroy) | ||||
|     main_window.add(i.get_vbox()) | ||||
|  |  | |||
|  | @ -282,43 +282,6 @@ class FpdbSQLQueries: | |||
|                             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 | ||||
|         ################################ | ||||
|  | @ -1598,136 +1561,6 @@ class FpdbSQLQueries: | |||
|         elif(self.dbname == 'SQLite'): | ||||
|             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'): | ||||
|             self.query['getGames'] = """SELECT DISTINCT category from Gametypes""" | ||||
|          | ||||
|  |  | |||
|  | @ -43,14 +43,14 @@ import Filters | |||
| 
 | ||||
| class GuiGraphViewer (threading.Thread): | ||||
| 
 | ||||
|     def __init__(self, db, settings, querylist, config, debug=True): | ||||
|     def __init__(self, querylist, config, debug=True): | ||||
|         """Constructor for GraphViewer""" | ||||
|         self.debug=debug | ||||
|         #print "start of GraphViewer constructor" | ||||
|         self.db=db | ||||
|         self.cursor=db.cursor | ||||
|         self.settings=settings | ||||
|         self.sql=querylist | ||||
|         self.db = fpdb_db.fpdb_db()   # sets self.fdb.db self.fdb.cursor and self.fdb.sql | ||||
|         self.db.do_connect(config) | ||||
| 
 | ||||
|         self.sql = querylist | ||||
|         self.conf = config | ||||
| 
 | ||||
|         filters_display = { "Heroes"  :  True, | ||||
|  | @ -63,7 +63,7 @@ class GuiGraphViewer (threading.Thread): | |||
|                             "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.registerButton1Callback(self.generateGraph) | ||||
|         self.filters.registerButton2Name("Export to File") | ||||
|  | @ -146,7 +146,7 @@ class GuiGraphViewer (threading.Thread): | |||
|         for site in sites: | ||||
|             if sites[site] == True: | ||||
|                 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() | ||||
|                 if len(result) == 1: | ||||
|                     playerids.append(result[0][0]) | ||||
|  | @ -226,7 +226,7 @@ class GuiGraphViewer (threading.Thread): | |||
| 
 | ||||
|         #print "DEBUG: sql query:" | ||||
|         #print tmp | ||||
|         self.cursor.execute(tmp) | ||||
|         self.db.cursor.execute(tmp) | ||||
|         #returns (HandId,Winnings,Costs,Profit) | ||||
|         winnings = self.db.cursor.fetchall() | ||||
|         self.db.db.rollback() | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ class GuiPlayerStats (threading.Thread): | |||
|                             "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.registerButton1Callback(self.showDetailFilter) | ||||
|         self.filters.registerButton2Name("_Refresh") | ||||
|  | @ -227,11 +227,6 @@ class GuiPlayerStats (threading.Thread): | |||
|         if not flags:  holecards = False | ||||
|         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.refineQuery(tmp, flags, playerids, sitenos, limits, seats, groups, dates) | ||||
|         self.cursor.execute(tmp) | ||||
|  | @ -279,10 +274,6 @@ class GuiPlayerStats (threading.Thread): | |||
| 
 | ||||
|         while sqlrow < rows: | ||||
|             treerow = [] | ||||
|             if(row%2 == 0): | ||||
|                 bgcolor = "white" | ||||
|             else: | ||||
|                 bgcolor = "lightgrey" | ||||
|             for col,column in enumerate(cols_to_show): | ||||
|                 if column[colalias] in colnames: | ||||
|                     value = result[sqlrow][colnames.index(column[colalias])] | ||||
|  |  | |||
|  | @ -20,6 +20,7 @@ import pygtk | |||
| pygtk.require('2.0') | ||||
| import gtk | ||||
| import os | ||||
| from time import time, strftime | ||||
|      | ||||
| import fpdb_import | ||||
| import fpdb_db | ||||
|  | @ -58,21 +59,50 @@ class GuiPositionalStats (threading.Thread): | |||
|                             "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.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.stats_frame = None | ||||
|         self.stats_vbox = None | ||||
|          | ||||
|         self.main_hbox = gtk.HBox(False, 0) | ||||
|         self.main_hbox.show() | ||||
| 
 | ||||
|         statsFrame = gtk.Frame("Stats:") | ||||
|         statsFrame.set_label_align(0.0, 0.0) | ||||
|         statsFrame.show() | ||||
|         self.stats_frame = gtk.VBox(False, 0) | ||||
|         self.stats_frame = gtk.Frame() | ||||
|         self.stats_frame.set_label_align(0.0, 0.0) | ||||
|         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. | ||||
|         # 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" | ||||
|                          ) | ||||
| 
 | ||||
|         self.fillStatsFrame(self.stats_frame) | ||||
|         statsFrame.add(self.stats_frame) | ||||
|         self.fillStatsFrame(self.stats_vbox) | ||||
|         self.stats_frame.add(self.stats_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): | ||||
|  | @ -107,9 +137,12 @@ class GuiPositionalStats (threading.Thread): | |||
|         print "DEBUG: activesite set to %s" %(self.activesite) | ||||
| 
 | ||||
|     def refreshStats(self, widget, data): | ||||
|         try: self.stats_table.destroy() | ||||
|         try: self.stats_vbox.destroy() | ||||
|         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): | ||||
|         sites = self.filters.getSites() | ||||
|  | @ -144,66 +177,104 @@ class GuiPositionalStats (threading.Thread): | |||
|         self.createStatsTable(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 | ||||
|         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.refineQuery(tmp, playerids, sitenos, limits, seats, dates) | ||||
|         self.cursor.execute(tmp) | ||||
|         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) | ||||
|         colnames = [desc[0].lower() for desc in self.cursor.description] | ||||
| 
 | ||||
|         last_game,last_seats,sqlrow = "","",0 | ||||
|         while sqlrow < rows: | ||||
|             if(row%2 == 0): | ||||
|                 bgcolor = "white" | ||||
|             else: | ||||
|                 bgcolor = "lightgrey" | ||||
|             rowprinted=0 | ||||
|             treerow = [] | ||||
|             avgcol = colnames.index('avgseats') | ||||
|             for col,colname in enumerate(self.posncols): | ||||
|                 if colname in colnames: | ||||
|                     sqlcol = colnames.index(colname) | ||||
|                 else: | ||||
|                     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 sqlrow == 0: | ||||
|                         l = gtk.Label(result[sqlrow][sqlcol]) | ||||
|                         value = result[sqlrow][sqlcol] | ||||
|                         rowprinted=1 | ||||
|                     elif result[sqlrow][0] != last_game: | ||||
|                         l = gtk.Label(' ') | ||||
|                         value = ' ' | ||||
|                     elif 'show' in seats and seats['show'] and result[sqlrow][avgcol] != last_seats: | ||||
|                         l = gtk.Label(' ') | ||||
|                         value = ' ' | ||||
|                     else: | ||||
|                         l = gtk.Label(result[sqlrow][sqlcol]) | ||||
|                         value = result[sqlrow][sqlcol] | ||||
|                         rowprinted=1 | ||||
|                 else: | ||||
|                     l = gtk.Label(' ') | ||||
|                 if col == 0: | ||||
|                     l.set_alignment(xalign=0.0, yalign=0.5) | ||||
|                 elif col == 1: | ||||
|                     l.set_alignment(xalign=0.5, yalign=0.5) | ||||
|                     value = ' ' | ||||
|                 if value and value != -999: | ||||
|                     treerow.append(value) | ||||
|                 else: | ||||
|                     l.set_alignment(xalign=1.0, yalign=0.5) | ||||
|                 eb.add(l) | ||||
|                 self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) | ||||
|                 l.show() | ||||
|                 eb.show() | ||||
|                     treerow.append(' ') | ||||
|             iter = liststore.append(treerow) | ||||
|             last_game = result[sqlrow][0] | ||||
|             last_seats = result[sqlrow][avgcol] | ||||
|             if rowprinted: | ||||
|  | @ -220,50 +291,36 @@ class GuiPositionalStats (threading.Thread): | |||
| 
 | ||||
|         # blank row between main stats and totals: | ||||
|         col = 0 | ||||
|         if(row%2 == 0): | ||||
|             bgcolor = "white" | ||||
|         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() | ||||
|         treerow = [' ' for x in self.posncols] | ||||
|         iter = liststore.append(treerow) | ||||
|         row = row + 1 | ||||
| 
 | ||||
|         for sqlrow in range(rows): | ||||
|             if(row%2 == 0): | ||||
|                 bgcolor = "white" | ||||
|             else: | ||||
|                 bgcolor = "lightgrey" | ||||
|             treerow = [] | ||||
|             for col,colname in enumerate(self.posncols): | ||||
|                 if colname in colnames: | ||||
|                     sqlcol = colnames.index(colname) | ||||
|                 elif colname != "plposition": | ||||
|                     continue | ||||
|                 eb = gtk.EventBox() | ||||
|                 eb.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse(bgcolor)) | ||||
|                 if colname == 'plposition': | ||||
|                     l = gtk.Label('Totals') | ||||
|                     value = 'Totals' | ||||
|                 elif result[sqlrow][sqlcol]: | ||||
|                     l = gtk.Label(result[sqlrow][sqlcol]) | ||||
|                     value = result[sqlrow][sqlcol] | ||||
|                 else: | ||||
|                     l = gtk.Label(' ') | ||||
|                 if col == 0: | ||||
|                     l.set_alignment(xalign=0.0, yalign=0.5) | ||||
|                 elif col == 1: | ||||
|                     l.set_alignment(xalign=0.5, yalign=0.5) | ||||
|                     value = ' ' | ||||
|                 if value and value != -999: | ||||
|                     treerow.append(value) | ||||
|                 else: | ||||
|                     l.set_alignment(xalign=1.0, yalign=0.5) | ||||
|                 eb.add(l) | ||||
|                 self.stats_table.attach(eb, col, col+1, row+1, row+2, yoptions=gtk.SHRINK) | ||||
|                 l.show() | ||||
|                 eb.show() | ||||
|                     treerow.append(' ') | ||||
|             iter = liststore.append(treerow) | ||||
|             row = row + 1 | ||||
|         vbox.show_all() | ||||
| 
 | ||||
|         self.db.db.rollback() | ||||
|         print "Positional Stats page displayed in %4.2f seconds" % (time() - starttime) | ||||
|     #end def fillStatsFrame(self, vbox): | ||||
| 
 | ||||
|     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 | ||||
| #agpl-3.0.txt in the docs folder of the package. | ||||
| 
 | ||||
| # TODO: get writehand() encoding correct | ||||
| 
 | ||||
| import re | ||||
| import sys | ||||
| import traceback | ||||
|  | @ -26,12 +28,20 @@ import operator | |||
| import time,datetime | ||||
| from copy import deepcopy | ||||
| from Exceptions import * | ||||
| import pprint | ||||
| import DerivedStats | ||||
| import Card | ||||
| 
 | ||||
| class Hand: | ||||
| 
 | ||||
| ###############################################################3 | ||||
| #    Class Variables | ||||
|     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'} | ||||
|     SYMBOL = {'USD': '$', 'EUR': u'E', 'T$': '', 'play': ''} | ||||
|     MS = {'horse' : 'HORSE', '8game' : '8-Game', 'hose'  : 'HOSE'} | ||||
| 
 | ||||
| 
 | ||||
|     def __init__(self, sitename, gametype, handText, builtFrom = "HHC"): | ||||
|         self.sitename = sitename | ||||
|         self.stats = DerivedStats.DerivedStats(self) | ||||
|  | @ -44,6 +54,10 @@ class Hand: | |||
|         self.maxseats = 10 | ||||
|         self.counted_seats = 0 | ||||
|         self.buttonpos = 0 | ||||
|         self.tourNo = None | ||||
|         self.buyin = None | ||||
|         self.level = None | ||||
|         self.mixed = None | ||||
|         self.seating = [] | ||||
|         self.players = [] | ||||
|         self.posted = [] | ||||
|  | @ -55,17 +69,19 @@ class Hand: | |||
|         self.actions = {} # [['mct','bets','$10'],['mika','folds'],['carlg','raises','$20']] | ||||
|         self.board = {} # dict from street names to community cards | ||||
|         self.holecards = {} | ||||
|         self.discards = {} | ||||
|         for street in self.allStreets: | ||||
|             self.streets[street] = "" # portions of the handText, filled by markStreets() | ||||
|             self.actions[street] = [] | ||||
|         for street in self.actionStreets: | ||||
|             self.bets[street] = {} | ||||
|             self.lastBet[street] = 0 | ||||
|             self.actions[street] = [] | ||||
|             self.board[street] = [] | ||||
|         for street in self.holeStreets: | ||||
|             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 | ||||
| #        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.collected = [] #list of ? | ||||
|         self.collectees = {} # dict from player names to amounts collected (?) | ||||
|  | @ -74,6 +90,7 @@ class Hand: | |||
|         self.folded = set() | ||||
|         self.dealt = set()  # 'dealt to' line to be printed | ||||
|         self.shown = set()  # cards were shown | ||||
|         self.mucked = set() # cards were mucked at showdown | ||||
| 
 | ||||
| #        self.action = [] | ||||
|         # Things to do with money | ||||
|  | @ -83,10 +100,77 @@ class Hand: | |||
|         self.rake = None | ||||
| 
 | ||||
|     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 + "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 | ||||
| 
 | ||||
|     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): | ||||
|         """ Function to insert Hand into database | ||||
| 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.stacks[name] = Decimal(chips) | ||||
|             self.pot.addPlayer(name) | ||||
|             for street in self.allStreets: | ||||
|             for street in self.actionStreets: | ||||
|                 self.bets[street][name] = [] | ||||
|                 #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): | ||||
|  | @ -202,7 +286,7 @@ If a player has None chips he won't be added.""" | |||
|     def setCommunityCards(self, street, cards): | ||||
|         logging.debug("setCommunityCards %s %s" %(street,  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): | ||||
|         """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) | ||||
| 
 | ||||
| 
 | ||||
|     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): | ||||
|         """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 | ||||
| """ | ||||
|         # currently it appears to be something like ["ring", "hold", "nl", sb, bb]: | ||||
|         gs = {"holdem"       : "Hold'em", | ||||
|         gs = {"holdem"     : "Hold'em", | ||||
|               "omahahi"    : "Omaha", | ||||
|               "omahahilo"  : "Omaha Hi/Lo", | ||||
|               "razz"       : "Razz", | ||||
|  | @ -410,7 +508,6 @@ Map the tuple self.gametype onto the pokerstars string describing it | |||
| 
 | ||||
|         logging.debug("gametype: %s" %(self.gametype)) | ||||
|         retstring = "%s %s" %(gs[self.gametype['category']], ls[self.gametype['limitType']]) | ||||
|              | ||||
|         return retstring | ||||
| 
 | ||||
| 
 | ||||
|  | @ -447,6 +544,33 @@ Map the tuple self.gametype onto the pokerstars string describing it | |||
|         elif act[1] == 'stands pat': | ||||
|             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): | ||||
|     def __init__(self, hhc, sitename, gametype, handText, builtFrom = "HHC", handid=None): | ||||
|  | @ -494,45 +618,12 @@ class HoldemOmahaHand(Hand): | |||
|             pass | ||||
|                  | ||||
| 
 | ||||
|     def addHoleCards(self, cards, player, shown=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 | ||||
| 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) | ||||
|     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.holecards['PREFLOP'][player] = cardset | ||||
| 
 | ||||
|     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) | ||||
|             self.addHoleCards('PREFLOP', player, open=[], closed=cards, shown=shown, mucked=mucked, dealt=dealt) | ||||
| 
 | ||||
| 
 | ||||
|     def writeHTMLHand(self, fh=sys.__stdout__): | ||||
|  | @ -632,8 +723,11 @@ Card ranks will be uppercased | |||
|          | ||||
|     def writeHand(self, fh=sys.__stdout__): | ||||
|         # 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, ("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) | ||||
| #        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_act_preflop = set(([x[0] for x in self.actions['PREFLOP']]+[x[0] for x in self.actions['BLINDSANTES']])) | ||||
|         logging.debug(self.actions['PREFLOP']) | ||||
|  | @ -647,10 +741,10 @@ Card ranks will be uppercased | |||
|          | ||||
|         print >>fh, ("*** HOLE CARDS ***") | ||||
|         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 == "": | ||||
|             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']: | ||||
|             for act in self.actions['PREFLOP']: | ||||
|  | @ -689,7 +783,7 @@ Card ranks will be uppercased | |||
|                 elif self.gametype['category'] in ('holdem'): | ||||
|                     numOfHoleCardsNeeded = 2 | ||||
|                 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: | ||||
|         # Uncalled bet ($111.25) returned to s0rrow | ||||
|  | @ -716,7 +810,7 @@ Card ranks will be uppercased | |||
|             seatnum = player[0] | ||||
|             name = player[1] | ||||
|             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: | ||||
|                 print >>fh, ("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) | ||||
|             #~ elif name in self.shown: | ||||
|  | @ -725,7 +819,9 @@ Card ranks will be uppercased | |||
|                 print >>fh, ("Seat %d: %s folded" % (seatnum, name)) | ||||
|             else: | ||||
|                 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: | ||||
|                     print >>fh, ("Seat %d: %s mucked" % (seatnum, name)) | ||||
| 
 | ||||
|  | @ -736,8 +832,10 @@ class DrawHand(Hand): | |||
|         if gametype['base'] != 'draw': | ||||
|             pass # or indeed don't pass and complain instead | ||||
|         self.streetList = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||
|         self.allStreets = ['BLINDSANTES', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||
|         self.holeStreets = ['DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||
|         self.actionStreets =  ['PREDEAL', 'DEAL', 'DRAWONE', 'DRAWTWO', 'DRAWTHREE'] | ||||
|         self.communityStreets = [] | ||||
|         Hand.__init__(self, sitename, gametype, handText) | ||||
|         self.sb = gametype['sb'] | ||||
|         self.bb = gametype['bb'] | ||||
|  | @ -749,12 +847,13 @@ class DrawHand(Hand): | |||
|             hhc.markStreets(self) | ||||
|             hhc.readBlinds(self) | ||||
|             hhc.readButton(self) | ||||
|             hhc.readHeroCards(self) | ||||
|             hhc.readShowdownActions(self) | ||||
|             # Read actions in street order | ||||
|             for street in self.streetList: | ||||
|                 if self.streets[street]: | ||||
|                     # hhc.readCommunityCards(self, street) | ||||
|                     hhc.readDrawCards(self, street) | ||||
| #                    hhc.readDrawCards(self, street) | ||||
|                     hhc.readAction(self, street) | ||||
|             hhc.readCollectPot(self) | ||||
|             hhc.readShownCards(self) | ||||
|  | @ -790,25 +889,33 @@ class DrawHand(Hand): | |||
|         #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): | ||||
|         """\ | ||||
| Assigns observed holecards to a player. | ||||
| cards   list of card bigrams e.g. ['2h','Jc'] | ||||
| player  (string) name of player | ||||
| """ | ||||
|         try: | ||||
|             self.checkPlayerExists(player) | ||||
| #            if shown and len(cardset) > 0: | ||||
| #                self.shown.add(player) | ||||
|             self.holecards[player][street] = (newcards,oldcards) | ||||
|         except FpdbParseError, e: | ||||
|             print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) | ||||
| 
 | ||||
| #    def addDrawHoleCards(self, newcards, oldcards, player, street, shown=False): | ||||
| #        """\ | ||||
| #Assigns observed holecards to a player. | ||||
| #cards   list of card bigrams e.g. ['2h','Jc'] | ||||
| #player  (string) name of player | ||||
| #""" | ||||
| #        try: | ||||
| #            self.checkPlayerExists(player) | ||||
| ##            if shown and len(cardset) > 0: | ||||
| ##                self.shown.add(player) | ||||
| #            self.holecards[street][player] = (newcards,oldcards) | ||||
| #        except FpdbParseError, e: | ||||
| #            print "[ERROR] Tried to add holecards for unknown player: %s" % (player,) | ||||
| 
 | ||||
| 
 | ||||
|     def discardDrawHoleCards(self, 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): | ||||
|  | @ -821,12 +928,12 @@ player  (string) name of player | |||
|         self.actions[street].append(act) | ||||
| 
 | ||||
| 
 | ||||
|     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)) | ||||
| #    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). | ||||
| #Card ranks will be uppercased | ||||
| #""" | ||||
| #        logging.debug("addShownCards %s hole=%s all=%s" % (player, cards,  holeandboard)) | ||||
| #        if cards is not None: | ||||
| #            self.shown.add(player) | ||||
| #            self.addHoleCards(cards,player) | ||||
|  | @ -836,10 +943,39 @@ Card ranks will be uppercased | |||
| #            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__): | ||||
|         # 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, _("Table '%s' %d-max Seat #%s is the button" %(self.tablename, self.maxseats, self.buttonpos)) | ||||
| #        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, 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']])) | ||||
| 
 | ||||
|  | @ -865,8 +1001,8 @@ Card ranks will be uppercased | |||
|             for act in self.actions['DRAWONE']: | ||||
|                 print >>fh, self.actionString(act) | ||||
|                 if act[0] == self.hero and act[1] == 'discards': | ||||
|                     (nc,oc) = self.holecards[act[0]]['DRAWONE'] | ||||
|                     dc = self.discards[act[0]]['DRAWONE'] | ||||
|                     (nc,oc) = self.holecards['DRAWONE'][act[0]] | ||||
|                     dc = self.discards['DRAWONE'][act[0]] | ||||
|                     kc = oc - dc | ||||
|                     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']: | ||||
|                 print >>fh, self.actionString(act) | ||||
|                 if act[0] == self.hero and act[1] == 'discards': | ||||
|                     (nc,oc) = self.holecards[act[0]]['DRAWTWO'] | ||||
|                     dc = self.discards[act[0]]['DRAWTWO'] | ||||
|                     (nc,oc) = self.holecards['DRAWTWO'][act[0]] | ||||
|                     dc = self.discards['DRAWTWO'][act[0]] | ||||
|                     kc = oc - dc | ||||
|                     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']: | ||||
|                 print >>fh, self.actionString(act) | ||||
|                 if act[0] == self.hero and act[1] == 'discards': | ||||
|                     (nc,oc) = self.holecards[act[0]]['DRAWTHREE'] | ||||
|                     dc = self.discards[act[0]]['DRAWTHREE'] | ||||
|                     (nc,oc) = self.holecards['DRAWTHREE'][act[0]] | ||||
|                     dc = self.discards['DRAWTHREE'][act[0]] | ||||
|                     kc = oc - dc | ||||
|                     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"): | ||||
|         if gametype['base'] != 'stud': | ||||
|             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.holeStreets = ['ANTES','THIRD','FOURTH','FIFTH','SIXTH','SEVENTH'] | ||||
|         Hand.__init__(self, sitename, gametype, handText) | ||||
|  | @ -931,21 +1072,35 @@ class StudHand(Hand): | |||
|             hhc.markStreets(self) | ||||
|             hhc.readAntes(self) | ||||
|             hhc.readBringIn(self) | ||||
|             hhc.readHeroCards(self) | ||||
|             #hhc.readShowdownActions(self) # not done yet | ||||
|             # Read actions in street order | ||||
|             for street in self.streetList: | ||||
|                 if self.streets[street]: | ||||
|                     logging.debug(street) | ||||
|                     logging.debug(self.streets[street]) | ||||
|                     hhc.readStudPlayerCards(self, street) | ||||
| #                    hhc.readStudPlayerCards(self, street) | ||||
|                     hhc.readAction(self, street) | ||||
|             hhc.readCollectPot(self) | ||||
|             #hhc.readShownCards(self) # not done yet | ||||
|             hhc.readShownCards(self) # not done yet | ||||
|             self.totalPot() # finalise it (total the pot) | ||||
|             hhc.getRake(self) | ||||
|         elif builtFrom == "DB": | ||||
|             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=[]): | ||||
|         """\ | ||||
| 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)) | ||||
|         try: | ||||
|             self.checkPlayerExists(player) | ||||
|             self.holecards[player][street] = (open, closed) | ||||
|             self.holecards[street][player] = (open, closed) | ||||
| #            cards = set([self.card(c) for c in cards]) | ||||
| #            self.holecards[player].update(cards) | ||||
|         except FpdbParseError, e: | ||||
|             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): | ||||
|     def addComplete(self, street, player, amountTo): | ||||
|         # assert street=='THIRD' | ||||
|  | @ -995,11 +1185,19 @@ Add a complete on [street] by [player] to [amountTo] | |||
|             self.lastBet['THIRD'] = Decimal(bringin) | ||||
|             self.pot.addMoney(player, Decimal(bringin)) | ||||
| 
 | ||||
|      | ||||
|     def writeHand(self, fh=sys.__stdout__): | ||||
|         # 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, 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']]) | ||||
| 
 | ||||
|  | @ -1015,8 +1213,8 @@ Add a complete on [street] by [player] to [amountTo] | |||
|             dealt = 0 | ||||
|             #~ print >>fh, _("*** 3RD STREET ***") | ||||
|             for player in [x[1] for x in self.players if x[1] in players_who_post_antes]: | ||||
|                 if 'THIRD' in self.holecards[player]: | ||||
|                     (open,  closed) = self.holecards[player]['THIRD'] | ||||
|                 if self.holecards['THIRD'].has_key(player): | ||||
|                     (open,  closed) = self.holecards['THIRD'][player] | ||||
|                     dealt+=1 | ||||
|                     if dealt==1: | ||||
|                         print >>fh, _("*** 3RD STREET ***") | ||||
|  | @ -1029,12 +1227,12 @@ Add a complete on [street] by [player] to [amountTo] | |||
|             dealt = 0 | ||||
|             #~ print >>fh, _("*** 4TH STREET ***") | ||||
|             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 = [] | ||||
|                     (o,c) = self.holecards[player]['THIRD'] | ||||
|                     (o,c) = self.holecards['THIRD'][player] | ||||
|                     if o:old.extend(o) | ||||
|                     if c:old.extend(c) | ||||
|                     new = self.holecards[player]['FOURTH'][0] | ||||
|                     new = self.holecards['FOURTH'][player][0] | ||||
|                     dealt+=1 | ||||
|                     if dealt==1: | ||||
|                         print >>fh, _("*** 4TH STREET ***") | ||||
|  | @ -1046,13 +1244,13 @@ Add a complete on [street] by [player] to [amountTo] | |||
|             dealt = 0 | ||||
|             #~ print >>fh, _("*** 5TH STREET ***") | ||||
|             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 = [] | ||||
|                     for street in ('THIRD','FOURTH'): | ||||
|                         (o,c) = self.holecards[player][street] | ||||
|                         (o,c) = self.holecards[street][player] | ||||
|                         if o:old.extend(o) | ||||
|                         if c:old.extend(c) | ||||
|                     new = self.holecards[player]['FIFTH'][0] | ||||
|                     new = self.holecards['FIFTH'][player][0] | ||||
|                     dealt+=1 | ||||
|                     if dealt==1: | ||||
|                         print >>fh, _("*** 5TH STREET ***") | ||||
|  | @ -1064,13 +1262,13 @@ Add a complete on [street] by [player] to [amountTo] | |||
|             dealt = 0 | ||||
|             #~ print >>fh, _("*** 6TH STREET ***") | ||||
|             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 = [] | ||||
|                     for street in ('THIRD','FOURTH','FIFTH'): | ||||
|                         (o,c) = self.holecards[player][street] | ||||
|                         (o,c) = self.holecards[street][player] | ||||
|                         if o:old.extend(o) | ||||
|                         if c:old.extend(c) | ||||
|                     new = self.holecards[player]['SIXTH'][0] | ||||
|                     new = self.holecards['SIXTH'][player][0] | ||||
|                     dealt += 1 | ||||
|                     if dealt == 1: | ||||
|                         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. | ||||
|             print >>fh, _("*** 7TH STREET ***") | ||||
|             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 = [] | ||||
|                     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 c:old.extend(c) | ||||
|                     new = self.holecards[player]['SEVENTH'][0] | ||||
|                     new = self.holecards['SEVENTH'][player][0] | ||||
|                     if new: | ||||
|                         print >>fh, _("Dealt to %s:%s%s") % (player, " [" + " ".join(old) + "] " if old else " ", "[" + " ".join(new) + "]" if new else "") | ||||
|             for act in self.actions['SEVENTH']: | ||||
|  | @ -1130,11 +1328,13 @@ Add a complete on [street] by [player] to [amountTo] | |||
|             seatnum = player[0] | ||||
|             name = player[1] | ||||
|             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: | ||||
|                 print >>fh, _("Seat %d: %s collected ($%s)" % (seatnum, name, self.collectees[name])) | ||||
|             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: | ||||
|                 print >>fh, _("Seat %d: %s folded" % (seatnum, name)) | ||||
|             else: | ||||
|  | @ -1143,6 +1343,12 @@ Add a complete on [street] by [player] to [amountTo] | |||
|         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): | ||||
| 
 | ||||
|  |  | |||
|  | @ -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) | ||||
| 
 | ||||
|         if hand: | ||||
| #            print hand | ||||
|             hand.writeHand(self.out_fh) | ||||
|         else: | ||||
|             logging.info("Unsupported game type: %s" % gametype) | ||||
|  |  | |||
|  | @ -34,10 +34,13 @@ import gobject | |||
| 
 | ||||
| #    FreePokerTools modules | ||||
| from Mucked import Aux_Window | ||||
| from Mucked import Seat_Window | ||||
| from Mucked import Aux_Seats | ||||
| 
 | ||||
| class Hello(Aux_Window): | ||||
|     """A 'Hello World' Aux_Window demo.""" | ||||
|     def create(self): | ||||
|         print "creating Hello" | ||||
| #    This demo simply creates a label in a window. | ||||
|         self.container = gtk.Window() | ||||
|         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. | ||||
|         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): | ||||
|     """A 'Hello World' Aux_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() | ||||
| class Hello_Seats(Aux_Seats): | ||||
|     """A 'Hello World' Seat_Window demo.""" | ||||
| 
 | ||||
|     def print_cards(self, *args): | ||||
| #    callback for the menu item | ||||
|         print "cards =", self.hud.cards | ||||
|     def create_contents(self, container, i): | ||||
|         container.label = gtk.Label("empty") | ||||
|         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) | ||||
| 
 | ||||
|     def topify_window(self, window): | ||||
|         """Set the specified gtk window to stayontop in MS Windows.""" | ||||
| 
 | ||||
|         def windowEnumerationHandler(hwnd, resultList): | ||||
|             '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | ||||
|             resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | ||||
| 
 | ||||
|         unique_name = 'unique name for finding this window' | ||||
|         real_name = window.get_title() | ||||
|         window.set_title(unique_name) | ||||
|         tl_windows = [] | ||||
|         win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | ||||
|          | ||||
|         for w in tl_windows: | ||||
|             if w[1] == unique_name: | ||||
| #        """Set the specified gtk window to stayontop in MS Windows.""" | ||||
| # | ||||
| #        def windowEnumerationHandler(hwnd, resultList): | ||||
| #            '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | ||||
| #            resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | ||||
| #        unique_name = 'unique name for finding this window' | ||||
| #        real_name = window.get_title() | ||||
| #        window.set_title(unique_name) | ||||
| #        tl_windows = [] | ||||
| #        win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | ||||
| #         | ||||
| #        for w in tl_windows: | ||||
| #            if w[1] == unique_name: | ||||
|                 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) | ||||
|                  | ||||
|                 style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) | ||||
|                 style |= win32con.WS_CLIPCHILDREN | ||||
|                 win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) | ||||
|                 break | ||||
| #                break | ||||
|              | ||||
|         window.set_title(real_name) | ||||
| #        window.set_title(real_name) | ||||
| 
 | ||||
| class Stat_Window: | ||||
| 
 | ||||
|  | @ -445,10 +445,10 @@ class Stat_Window: | |||
|                  | ||||
|                 Stats.do_tip(e_box[r][c], 'stuff') | ||||
|                 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]) | ||||
|                 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') ) | ||||
|                  | ||||
|                 if usegtkframes: | ||||
|  | @ -473,6 +473,7 @@ class Popup_window: | |||
|     def __init__(self, parent, stat_window): | ||||
|         self.sb_click = 0 | ||||
|         self.stat_window = stat_window | ||||
|         self.parent = parent | ||||
| 
 | ||||
| #    create the popup window | ||||
|         self.window = gtk.Window() | ||||
|  | @ -532,11 +533,15 @@ class Popup_window: | |||
| #        db_connection.close_connection() | ||||
|         stat_dict = stat_window.parent.stat_dict | ||||
|         pu_text = "" | ||||
|         mo_text = "" | ||||
|         for s in stat_list: | ||||
|             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" | ||||
|              | ||||
| 
 | ||||
|         self.lab.set_text(pu_text) | ||||
|         Stats.do_tip(self.lab, mo_text) | ||||
|         self.window.show_all() | ||||
|          | ||||
|         self.window.set_transient_for(stat_window.window) | ||||
|  | @ -572,25 +577,25 @@ class Popup_window: | |||
|     def topify_window(self, window): | ||||
|         """Set the specified gtk window to stayontop in MS Windows.""" | ||||
| 
 | ||||
|         def windowEnumerationHandler(hwnd, resultList): | ||||
|             '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | ||||
|             resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | ||||
| #        def windowEnumerationHandler(hwnd, resultList): | ||||
| #            '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | ||||
| #            resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | ||||
| 
 | ||||
|         unique_name = 'unique name for finding this window' | ||||
|         real_name = window.get_title() | ||||
|         window.set_title(unique_name) | ||||
|         tl_windows = [] | ||||
|         win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | ||||
| #        unique_name = 'unique name for finding this window' | ||||
| #        real_name = window.get_title() | ||||
| #        window.set_title(unique_name) | ||||
| #        tl_windows = [] | ||||
| #        win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | ||||
|          | ||||
|         for w in tl_windows: | ||||
|             if w[1] == unique_name: | ||||
|                 window.set_transient_for(self.parent.main_window)                | ||||
|                 style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) | ||||
|                 style |= win32con.WS_CLIPCHILDREN | ||||
|                 win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) | ||||
|                 break | ||||
| #        for w in tl_windows: | ||||
| #            if w[1] == unique_name: | ||||
|         window.set_transient_for(self.parent.main_window)                | ||||
|         style = win32gui.GetWindowLong(self.table.number, win32con.GWL_EXSTYLE) | ||||
|         style |= win32con.WS_CLIPCHILDREN | ||||
|         win32gui.SetWindowLong(self.table.number, win32con.GWL_EXSTYLE, style) | ||||
| #                break | ||||
|                  | ||||
|         window.set_title(real_name) | ||||
| #        window.set_title(real_name) | ||||
| 
 | ||||
| if __name__== "__main__": | ||||
|     main_window = gtk.Window() | ||||
|  |  | |||
							
								
								
									
										253
									
								
								pyfpdb/Mucked.py
									
									
									
									
									
								
							
							
						
						
									
										253
									
								
								pyfpdb/Mucked.py
									
									
									
									
									
								
							|  | @ -37,27 +37,18 @@ import Configuration | |||
| import Database | ||||
| import Card | ||||
| 
 | ||||
| class Aux_Window: | ||||
| class Aux_Window(object): | ||||
|     def __init__(self, hud, params, config): | ||||
|         self.hud     = hud | ||||
|         self.params  = params | ||||
|         self.config  = config | ||||
| 
 | ||||
|     def update_data(self, *args): | ||||
|         pass | ||||
| 
 | ||||
|     def update_gui(self, *args): | ||||
|         pass | ||||
| 
 | ||||
|     def create(self, *args): | ||||
|         pass | ||||
| 
 | ||||
|     def relocate(self, *args): | ||||
|         pass | ||||
| 
 | ||||
|     def save_layout(self, *args): | ||||
|         pass | ||||
| 
 | ||||
| #   Override these methods as needed | ||||
|     def update_data(self, *args): pass | ||||
|     def update_gui(self, *args):  pass | ||||
|     def create(self, *args):      pass | ||||
|     def relocate(self, *args):    pass | ||||
|     def save_layout(self, *args): pass | ||||
|     def destroy(self): | ||||
|         try: | ||||
|             self.container.destroy() | ||||
|  | @ -89,14 +80,19 @@ class Aux_Window: | |||
|         pb.copy_area(30*j, 42*i, 30, 42, temp_pb, 0, 0) | ||||
|         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): | ||||
|         """Returns the number of cards in the list.""" | ||||
|         n = 0 | ||||
|         for c in cards: | ||||
|             if c in set('shdc'): return True | ||||
|         return False | ||||
|             if c != None and c > 0: n = n + 1 | ||||
|         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): | ||||
|     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.eb[(c, r)].set_tooltip_text('') | ||||
| 
 | ||||
| class Flop_Mucked(Aux_Window): | ||||
|     """Aux_Window class for displaying mucked cards for flop games.""" | ||||
| class Seat_Window(gtk.Window): | ||||
|     """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): | ||||
|         self.hud     = hud       # hud object that this aux window supports | ||||
|         self.config  = config    # configuration object for this aux window to use | ||||
|         self.params  = params    # dict aux params from config | ||||
|         self.positions = {}      # dict of window positions | ||||
| #        self.rel_positions = {}  # dict of window positions, relative to the table origin | ||||
|         self.displayed_cards = False | ||||
|         self.displayed = False   # the seat windows are displayed | ||||
|         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.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): | ||||
|         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)) | ||||
|          | ||||
|         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']):            | ||||
|             if i == 'common': | ||||
|                 (x, y) = self.params['layout'][self.hud.max].common | ||||
|             else: | ||||
|                 (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_property("skip-taskbar-hint", True) | ||||
|             self.m_windows[i].set_transient_for(self.hud.main_window) | ||||
|             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].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.rel_positions[i] = (int(x), int(y)) | ||||
|             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].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): | ||||
|         """Prepare and show the mucked cards.""" | ||||
|         if self.displayed_cards: | ||||
|             self.hide_mucked_cards() | ||||
|             self.displayed_cards = False | ||||
|         if self.displayed: self.hide() | ||||
| 
 | ||||
| #   See how many players showed a hand. Skip if only 1 shows (= hero) | ||||
|         n_sd = 0 | ||||
|         for (i, cards) in self.hud.cards.iteritems(): | ||||
|             if self.has_cards(cards): | ||||
| #    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'])*len(cards)/2, | ||||
|                                          int(self.params['card_ht'])) | ||||
|                 x = 0 # x coord where the next card starts in scratch | ||||
|                 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 | ||||
|             n_cards = self.has_cards(cards) | ||||
|             if n_cards > 0 and i != 'common': | ||||
|                 n_sd = n_sd + 1 | ||||
|         if n_sd < 2:  | ||||
|             print "skipping, n_sd =", n_sd | ||||
|             return | ||||
| 
 | ||||
|         for stats in self.hud.stat_dict.itervalues(): | ||||
|             self.eb[stats['seat']].set_tooltip_text(stats['screen_name']) | ||||
|         super(Flop_Mucked, self).update_gui(new_hand_id) | ||||
| 
 | ||||
|         if self.displayed_cards and float(self.params['timeout']) > 0: | ||||
|         if self.displayed and float(self.params['timeout']) > 0: | ||||
|             self.timer_on = True | ||||
|             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): | ||||
| #    this is the callback from the timeout | ||||
| 
 | ||||
|  | @ -418,15 +479,9 @@ class Flop_Mucked(Aux_Window): | |||
|         if not self.timer_on: | ||||
|             return False | ||||
|         else: | ||||
|             self.hide_mucked_cards() | ||||
|             self.hide() | ||||
|             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): | ||||
|         """Handle button clicks in the event boxes.""" | ||||
| 
 | ||||
|  | @ -444,58 +499,14 @@ class Flop_Mucked(Aux_Window): | |||
|                 self.timer_on = False | ||||
|             else: | ||||
|                 self.timer_on = False | ||||
|                 self.hide_mucked_cards() | ||||
|                 self.hide() | ||||
| 
 | ||||
|         elif event.button == 1:   # left button event | ||||
|             window = widget.get_parent() | ||||
|             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): | ||||
|         for (i, cards) in self.hud.cards.iteritems(): | ||||
|             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 | ||||
| 
 | ||||
|     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() | ||||
|             self.displayed = True | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ | |||
| #    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||||
| ######################################################################## | ||||
| 
 | ||||
| # TODO: straighten out discards for draw games | ||||
| import sys | ||||
| from HandHistoryConverter import * | ||||
| 
 | ||||
|  | @ -25,16 +26,35 @@ from HandHistoryConverter import * | |||
| 
 | ||||
| class PokerStars(HandHistoryConverter): | ||||
| 
 | ||||
| ############################################################ | ||||
| #    Class Variables | ||||
| 
 | ||||
|     # 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_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_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>.+)\]") | ||||
| #        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): | ||||
|         """\ | ||||
| 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]) | ||||
|         if not players <= self.compiledPlayers: # x <= y means 'x is subset of y' | ||||
|             # 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 | ||||
|             player_re = "(?P<PNAME>" + "|".join(map(re.escape, players)) + ")" | ||||
|             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_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_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_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_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): | ||||
|         return [["ring", "hold", "nl"], | ||||
|                 ["ring", "hold", "pl"], | ||||
|                 ["ring", "hold", "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): | ||||
|         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) | ||||
|         if not m: | ||||
|             return None | ||||
| 
 | ||||
|         mg = m.groupdict() | ||||
|          | ||||
|         # translations from captured groups to our info strings | ||||
|         # translations from captured groups to fpdb info strings | ||||
|         limits = { 'No Limit':'nl', 'Pot Limit':'pl', 'Limit':'fl' } | ||||
|         games = {              # base, category | ||||
|                   "Hold'em" : ('hold','holdem'),  | ||||
|                     'Omaha' : ('hold','omahahi'), | ||||
|               'Omaha Hi/Lo' : ('hold','omahahilo'), | ||||
|                      'Razz' : ('stud','razz'),  | ||||
|               '7 Card Stud' : ('stud','studhi'), | ||||
|         '7 Card Stud Hi/Lo' : ('stud','studhilo'), | ||||
|                    'Badugi' : ('draw','badugi') | ||||
|         games = {                          # base, category | ||||
|                               "Hold'em" : ('hold','holdem'),  | ||||
|                                 'Omaha' : ('hold','omahahi'), | ||||
|                           'Omaha Hi/Lo' : ('hold','omahahilo'), | ||||
|                                  'Razz' : ('stud','razz'),  | ||||
|                           '7 Card Stud' : ('stud','studhi'), | ||||
|                     '7 Card Stud Hi/Lo' : ('stud','studhilo'), | ||||
|                                'Badugi' : ('draw','badugi'), | ||||
|               'Triple Draw 2-7 Lowball' : ('draw','27_3draw'), | ||||
|                } | ||||
|         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: | ||||
|             info['limitType'] = limits[mg['LIMIT']] | ||||
|         if 'GAME' in mg: | ||||
|  | @ -109,8 +148,13 @@ follow :  whether to tail -f the input""" | |||
|             info['bb'] = mg['BB'] | ||||
|         if 'CURRENCY' in mg: | ||||
|             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 | ||||
| 
 | ||||
| 
 | ||||
|  | @ -119,14 +163,13 @@ follow :  whether to tail -f the input""" | |||
|         m = self.re_HandInfo.search(hand.handText,re.DOTALL) | ||||
|         if m: | ||||
|             info.update(m.groupdict()) | ||||
|             # TODO: Be less lazy and parse maxseats from the HandInfo regex | ||||
|             if m.group('TABLEATTRIBUTES'): | ||||
|                 m2 = re.search("\s*(\d+)-max", m.group('TABLEATTRIBUTES')) | ||||
|                 hand.maxseats = int(m2.group(1)) | ||||
| #                hand.maxseats = int(m2.group(1)) | ||||
|         else: | ||||
|             pass  # throw an exception here, eh? | ||||
|         m = self.re_GameInfo.search(hand.handText) | ||||
|         if m: info.update(m.groupdict()) | ||||
|         m = self.re_Button.search(hand.handText) | ||||
|         if m: info.update(m.groupdict())  | ||||
| #        m = self.re_Button.search(hand.handText) | ||||
| #        if m: info.update(m.groupdict())  | ||||
|         # TODO : I rather like the idea of just having this dict as hand.info | ||||
|         logging.debug("readHandInfo: %s" % info) | ||||
|         for key in info: | ||||
|  | @ -143,6 +186,22 @@ follow :  whether to tail -f the input""" | |||
|                 hand.tablename = info[key] | ||||
|             if key == 'BUTTON': | ||||
|                 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): | ||||
|         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): | ||||
|             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): | ||||
|         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')) | ||||
| #    streets PREFLOP, PREDRAW, and THIRD are special cases beacause | ||||
| #    we need to grab hero's cards | ||||
|         for street in ('PREFLOP', 'DEAL'): | ||||
|             if street in hand.streets.keys(): | ||||
|                 m = self.re_HeroCards.finditer(hand.streets[street]) | ||||
|                 for found in m: | ||||
| #                    if m == None: | ||||
| #                        hand.involved = False | ||||
| #                    else: | ||||
|                     hand.hero = found.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): | ||||
|         logging.debug("readDrawCards") | ||||
|         m = self.re_HeroCards.finditer(hand.streets[street]) | ||||
|         if m == None: | ||||
|             hand.involved = False | ||||
|         else: | ||||
|             for player in m: | ||||
|                 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() | ||||
|         for street, text in hand.streets.iteritems(): | ||||
|             if street in ('PREFLOP', 'DEAL'): continue  # already done these | ||||
|             m = self.re_HeroCards.finditer(hand.streets[street]) | ||||
|             for found in m: | ||||
|                 player = found.group('PNAME') | ||||
|                 if found.group('NEWCARDS') == None: | ||||
|                     newcards = [] | ||||
|                 else: | ||||
|                     newcards = set(newcards.split(' ')) | ||||
|                 if oldcards == None: | ||||
|                     oldcards = set() | ||||
|                     newcards = found.group('NEWCARDS').split(' ') | ||||
|                 if found.group('OLDCARDS') == None: | ||||
|                     oldcards = [] | ||||
|                 else: | ||||
|                     oldcards = set(oldcards.split(' ')) | ||||
|                 hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street) | ||||
|                     oldcards = found.group('OLDCARDS').split(' ') | ||||
| 
 | ||||
|                 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): | ||||
|         # See comments of reference implementation in FullTiltToFpdb.py | ||||
|         logging.debug("readStudPlayerCards") | ||||
|         m = self.re_HeroCards.finditer(hand.streets[street]) | ||||
|         for player in m: | ||||
|             #~ logging.debug(player.groupdict()) | ||||
|             (pname,  oldcards,  newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS')) | ||||
|             if oldcards: | ||||
|                 oldcards = [c.strip() for c in oldcards.split(' ')] | ||||
|             if newcards: | ||||
|                 newcards = [c.strip() for c in newcards.split(' ')] | ||||
|             if street=='ANTES': | ||||
|                 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 readDrawCards(self, hand, street): | ||||
| #        logging.debug("readDrawCards") | ||||
| #        m = self.re_HeroCards.finditer(hand.streets[street]) | ||||
| #        if m == None: | ||||
| #            hand.involved = False | ||||
| #        else: | ||||
| #            for player in m: | ||||
| #                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: | ||||
| #                    newcards = set(newcards.split(' ')) | ||||
| #                if oldcards == None: | ||||
| #                    oldcards = set() | ||||
| #                else: | ||||
| #                    oldcards = set(oldcards.split(' ')) | ||||
| #                hand.addDrawHoleCards(newcards, oldcards, player.group('PNAME'), street) | ||||
| 
 | ||||
| 
 | ||||
| #    def readStudPlayerCards(self, hand, street): | ||||
| #        # See comments of reference implementation in FullTiltToFpdb.py | ||||
| #        logging.debug("readStudPlayerCards") | ||||
| #        m = self.re_HeroCards.finditer(hand.streets[street]) | ||||
| #        for player in m: | ||||
| #            #~ logging.debug(player.groupdict()) | ||||
| #            (pname,  oldcards,  newcards) = (player.group('PNAME'), player.group('OLDCARDS'), player.group('NEWCARDS')) | ||||
| #            if oldcards: | ||||
| #                oldcards = [c.strip() for c in oldcards.split(' ')] | ||||
| #            if newcards: | ||||
| #                newcards = [c.strip() for c in newcards.split(' ')] | ||||
| #            if street=='ANTES': | ||||
| #                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): | ||||
|         m = self.re_Action.finditer(hand.streets[street]) | ||||
|         for action in m: | ||||
|             acts = action.groupdict() | ||||
|             if action.group('ATYPE') == ' raises': | ||||
|                 hand.addRaiseBy( street, action.group('PNAME'), action.group('BET') ) | ||||
|             elif action.group('ATYPE') == ' calls': | ||||
|  | @ -294,7 +390,7 @@ follow :  whether to tail -f the input""" | |||
|             elif action.group('ATYPE') == ' checks': | ||||
|                 hand.addCheck( street, action.group('PNAME')) | ||||
|             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': | ||||
|                 hand.addStandsPat( street, action.group('PNAME')) | ||||
|             else: | ||||
|  | @ -302,9 +398,9 @@ follow :  whether to tail -f the input""" | |||
| 
 | ||||
| 
 | ||||
|     def readShowdownActions(self, hand): | ||||
| # TODO: pick up mucks also | ||||
|         for shows in self.re_ShowdownAction.finditer(hand.handText):             | ||||
|             cards = shows.group('CARDS') | ||||
|             cards = set(cards.split(' ')) | ||||
|             cards = shows.group('CARDS').split(' ') | ||||
|             hand.addShownCards(cards, shows.group('PNAME')) | ||||
| 
 | ||||
|     def readCollectPot(self,hand): | ||||
|  | @ -315,8 +411,13 @@ follow :  whether to tail -f the input""" | |||
|         for m in self.re_ShownCards.finditer(hand.handText): | ||||
|             if m.group('CARDS') is not None: | ||||
|                 cards = m.group('CARDS') | ||||
|                 cards = set(cards.split(' ')) | ||||
|                 hand.addShownCards(cards=cards, player=m.group('PNAME')) | ||||
|                 cards = cards.split(' ') # needs to be a list, not a set--stud needs the order | ||||
| 
 | ||||
|                 (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__": | ||||
|     parser = OptionParser() | ||||
|  |  | |||
|  | @ -542,18 +542,13 @@ class Sql: | |||
| 
 | ||||
|             self.query['get_common_cards'] = """ | ||||
|                     select | ||||
|                         card1Value AS card1value, | ||||
|                         card1Suit  AS card1suit, | ||||
|                         card2Value AS card2value, | ||||
|                         card2Suit  AS card2suit, | ||||
|                         card3Value AS card3value, | ||||
|                         card3Suit  AS card3suit, | ||||
|                         card4Value AS card4value, | ||||
|                         card4Suit  AS card4suit, | ||||
|                         card5Value AS card5value, | ||||
|                         card5Suit  AS card5suit | ||||
|                     from BoardCards | ||||
|                     where handId = %s | ||||
|                     boardcard1,  | ||||
|                     boardcard2,  | ||||
|                     boardcard3,  | ||||
|                     boardcard4,  | ||||
|                     boardcard5  | ||||
|                     from Hands | ||||
|                     where Id = %s | ||||
|                 """ | ||||
| 
 | ||||
|             self.query['get_action_from_hand'] = """ | ||||
|  |  | |||
|  | @ -231,7 +231,7 @@ def discover_nt_by_name(c, tablename): | |||
|     titles = {} | ||||
|     win32gui.EnumWindows(win_enum_handler, titles) | ||||
|     for hwnd in titles: | ||||
|         print "Tbales.py: tablename =", tablename, "title =", titles[hwnd] | ||||
|         #print "Tables.py: tablename =", tablename, "title =", titles[hwnd] | ||||
|         try: | ||||
|             # 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 | ||||
|  | @ -314,6 +314,10 @@ def get_site_from_exe(c, exe): | |||
|             return params['site_name'] | ||||
|     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): | ||||
| #    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. | ||||
|  | @ -365,7 +369,7 @@ def clean_title(name): | |||
|     for pattern in [' \(6 max\)', ' \(heads up\)', ' \(deep\)', | ||||
|                 ' \(deep hu\)', ' \(deep 6\)', ' \(2\)', | ||||
|                 ' \(edu\)', ' \(edu, 6 max\)', ' \(6\)', | ||||
|                 ' \(speed\)',  | ||||
|                 ' \(speed\)', 'special', 'newVPP',  | ||||
|                 ' no all-in', ' fast', ',', ' 50BB min', '50bb min', '\s+$']: | ||||
|         name = re.sub(pattern, '', name) | ||||
|     name = name.rstrip() | ||||
|  |  | |||
|  | @ -92,6 +92,8 @@ if __name__=="__main__": | |||
|     print "game =", table.get_game() | ||||
| 
 | ||||
|     fake = fake_hud(table) | ||||
|     print "fake =", fake | ||||
|     gobject.timeout_add(100, check_on_table, table, fake) | ||||
|     print "calling main" | ||||
|     gtk.main() | ||||
| 
 | ||||
|  |  | |||
|  | @ -65,8 +65,11 @@ class Table(Table_Window): | |||
|         print "x = %s y = %s width = %s height = %s" % (x, y, width, height) | ||||
|         self.x      = int(x) + b_width | ||||
|         self.y      = int(y) + tb_height | ||||
|         self.height = int(height) - b_width - tb_height | ||||
|         self.width  = int(width) - 2*b_width | ||||
|         self.width  = width - x | ||||
|         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.title  = titles[hwnd] | ||||
|  | @ -76,12 +79,13 @@ class Table(Table_Window): | |||
|         self.gdkhandle = gtk.gdk.window_foreign_new(long(self.window)) | ||||
| 
 | ||||
|     def get_geometry(self): | ||||
| 
 | ||||
|         if not win32gui.IsWindow(self.window):  # window closed | ||||
|         if not win32gui.IsWindow(self.number):  # window closed | ||||
|             return None | ||||
| 
 | ||||
|         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, | ||||
|                     'y'      : int(y) + tb_height, | ||||
|                     'width'  : int(height) - b_width - tb_height, | ||||
|  | @ -116,27 +120,32 @@ class Table(Table_Window): | |||
|     def topify(self, hud): | ||||
|         """Set the specified gtk window to stayontop in MS Windows.""" | ||||
|      | ||||
|         def windowEnumerationHandler(hwnd, resultList): | ||||
|             '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | ||||
|             resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | ||||
|      | ||||
|         unique_name = 'unique name for finding this window' | ||||
|         real_name = hud.main_window.get_title() | ||||
|         hud.main_window.set_title(unique_name) | ||||
|         tl_windows = [] | ||||
|         win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | ||||
|              | ||||
|         for w in tl_windows: | ||||
|             if w[1] == unique_name: | ||||
|                 hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) | ||||
|                 hud.main_window.gdkhandle.set_transient_for(self.gdkhandle) | ||||
| #        def windowEnumerationHandler(hwnd, resultList): | ||||
| #            '''Callback for win32gui.EnumWindows() to generate list of window handles.''' | ||||
| #            resultList.append((hwnd, win32gui.GetWindowText(hwnd))) | ||||
| #     | ||||
| #        unique_name = 'unique name for finding this window' | ||||
| #        real_name = hud.main_window.get_title() | ||||
| #        hud.main_window.set_title(unique_name) | ||||
| #        tl_windows = [] | ||||
| #        win32gui.EnumWindows(windowEnumerationHandler, tl_windows) | ||||
| #             | ||||
| #        for w in tl_windows: | ||||
| #            if w[1] == unique_name: | ||||
| #                hud.main_window.gdkhandle = gtk.gdk.window_foreign_new(w[0]) | ||||
|         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 |= win32con.WS_CLIPCHILDREN | ||||
| #                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): | ||||
|     titles[hwnd] = win32gui.GetWindowText(hwnd) | ||||
|  |  | |||
							
								
								
									
										101
									
								
								pyfpdb/fpdb.py
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								pyfpdb/fpdb.py
									
									
									
									
									
								
							|  | @ -33,7 +33,7 @@ import pygtk | |||
| pygtk.require('2.0') | ||||
| import gtk | ||||
| 
 | ||||
| import fpdb_db | ||||
| 
 | ||||
| import fpdb_simple | ||||
| import GuiBulkImport | ||||
| import GuiPlayerStats | ||||
|  | @ -42,6 +42,8 @@ import GuiTableViewer | |||
| import GuiAutoImport | ||||
| import GuiGraphViewer | ||||
| import GuiSessionViewer | ||||
| import SQL | ||||
| import Database | ||||
| import FpdbSQLQueries | ||||
| import Configuration | ||||
| 
 | ||||
|  | @ -179,20 +181,21 @@ class fpdb: | |||
|     def dia_load_profile(self, widget, data=None): | ||||
|         """Dialogue to select a file to load a profile from""" | ||||
|         if self.obtain_global_lock() == 0:  # returns 0 if successful | ||||
|             try: | ||||
|                 chooser = gtk.FileChooserDialog(title="Please select a profile file to load", | ||||
|                         action=gtk.FILE_CHOOSER_ACTION_OPEN, | ||||
|                         buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) | ||||
|                 chooser.set_filename(self.profile) | ||||
|             #try: | ||||
|             #    chooser = gtk.FileChooserDialog(title="Please select a profile file to load", | ||||
|             #            action=gtk.FILE_CHOOSER_ACTION_OPEN, | ||||
|             #            buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK)) | ||||
|             #    chooser.set_filename(self.profile) | ||||
| 
 | ||||
|                 response = chooser.run() | ||||
|                 chooser.destroy()     | ||||
|                 if response == gtk.RESPONSE_OK: | ||||
|                     self.load_profile(chooser.get_filename()) | ||||
|                 elif response == gtk.RESPONSE_CANCEL: | ||||
|                     print 'User cancelled loading profile' | ||||
|             except: | ||||
|                 pass | ||||
|             #    response = chooser.run() | ||||
|             #    chooser.destroy()     | ||||
|             #    if response == gtk.RESPONSE_OK: | ||||
|             #        self.load_profile(chooser.get_filename()) | ||||
|             #    elif response == gtk.RESPONSE_CANCEL: | ||||
|             #        print 'User cancelled loading profile' | ||||
|             #except: | ||||
|             #    pass | ||||
|             self.load_profile() | ||||
|             self.release_global_lock() | ||||
|     #end def dia_load_profile | ||||
| 
 | ||||
|  | @ -204,22 +207,23 @@ class fpdb: | |||
|             try: | ||||
|                 dia_confirm = gtk.MessageDialog(parent=None, flags=0, type=gtk.MESSAGE_WARNING, | ||||
|                         buttons=(gtk.BUTTONS_YES_NO), message_format="Confirm deleting and recreating tables") | ||||
|                 diastring = "Please confirm that you want to (re-)create the tables. If there already are tables in the database "+self.db.database+" on "+self.db.host+" they will be deleted." | ||||
|                 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 | ||||
| 
 | ||||
|                 response = dia_confirm.run() | ||||
|                 dia_confirm.destroy() | ||||
|                 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  | ||||
|                         # than lock all the other tables | ||||
|                         # ToDo: lock all other tables so that lock doesn't have to be released | ||||
|                         self.release_global_lock() | ||||
|                         lock_released = True | ||||
|                         self.db.recreate_tables() | ||||
|                         self.db.fdb.recreate_tables() | ||||
|                     else: | ||||
|                         # 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: | ||||
|                     print 'User cancelled recreating tables' | ||||
|             except: | ||||
|  | @ -347,6 +351,7 @@ class fpdb: | |||
| 
 | ||||
|     def load_profile(self): | ||||
|         """Loads profile from the provided path name.""" | ||||
|         self.config = Configuration.Config(file=options.config, dbname=options.dbname) | ||||
|         self.settings = {} | ||||
|         if (os.sep=="/"): | ||||
|             self.settings['os']="linuxmac" | ||||
|  | @ -359,17 +364,13 @@ class fpdb: | |||
|         self.settings.update(self.config.get_import_parameters()) | ||||
|         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 = fpdb_db.fpdb_db() | ||||
|         #print "end of fpdb.load_profile, databaseName:",self.settings['db-databaseName'] | ||||
|         self.db.connect(self.settings['db-backend'], | ||||
|             self.settings['db-host'], | ||||
|             self.settings['db-databaseName'], | ||||
|             self.settings['db-user'],  | ||||
|             self.settings['db-password']) | ||||
|         if self.db.wrongDbVersion: | ||||
|         self.sql = SQL.Sql(type = self.settings['db-type'], db_server = self.settings['db-server']) | ||||
|         self.db = Database.Database(self.config, sql = self.sql) | ||||
| 
 | ||||
|         if self.db.fdb.wrongDbVersion: | ||||
|             diaDbVersionWarning = gtk.Dialog(title="Strong Warning - Invalid database version", parent=None, flags=0, buttons=(gtk.STOCK_OK,gtk.RESPONSE_OK)) | ||||
| 
 | ||||
|             label = gtk.Label("An invalid DB version or missing tables have been detected.") | ||||
|  | @ -387,9 +388,16 @@ class fpdb: | |||
|             response = diaDbVersionWarning.run() | ||||
|             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 | ||||
|         self.querydict = FpdbSQLQueries.FpdbSQLQueries(self.db.get_backend_name()) | ||||
|         self.db.db.rollback() | ||||
|         self.db.connection.rollback() | ||||
|     #end def load_profile | ||||
| 
 | ||||
|     def not_implemented(self, widget, data=None): | ||||
|  | @ -398,13 +406,9 @@ class fpdb: | |||
| 
 | ||||
|     def obtain_global_lock(self): | ||||
|         print "\nTaking global lock ..." | ||||
|         self.fdb_lock = fpdb_db.fpdb_db() | ||||
|         self.fdb_lock.connect(self.settings['db-backend'], | ||||
|                               self.settings['db-host'], | ||||
|                               self.settings['db-databaseName'], | ||||
|                               self.settings['db-user'],  | ||||
|                               self.settings['db-password']) | ||||
|         return self.fdb_lock.get_global_lock() | ||||
|         self.fdb_lock = Database.Database(self.config, sql = self.sql) | ||||
|         self.fdb_lock.do_connect(self.config) | ||||
|         return self.fdb_lock.fdb.get_global_lock() | ||||
|     #end def obtain_global_lock | ||||
| 
 | ||||
|     def quit(self, widget, data=None): | ||||
|  | @ -415,9 +419,9 @@ class fpdb: | |||
|     #end def quit_cliecked | ||||
| 
 | ||||
|     def release_global_lock(self): | ||||
|         self.fdb_lock.db.rollback() | ||||
|         self.fdb_lock.disconnect() | ||||
|         print "Global lock released." | ||||
|         self.fdb_lock.fdb.db.rollback() | ||||
|         self.fdb_lock.fdb.disconnect() | ||||
|         print "Global lock released.\n" | ||||
|     #end def release_global_lock | ||||
| 
 | ||||
|     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): | ||||
|         """opens a table viewer tab""" | ||||
|         #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) | ||||
|         tv_tab=new_tv_thread.get_vbox() | ||||
|         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): | ||||
|         """opens a graph viewer tab""" | ||||
|         #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) | ||||
|         gv_tab=new_gv_thread.get_vbox() | ||||
|         self.add_and_display_tab(gv_tab, "Graphs") | ||||
|     #end def tabGraphViewer | ||||
| 
 | ||||
|     def __init__(self): | ||||
|         LOG_FILENAME = './logging.out' | ||||
|         LOG_FORMAT = "%(asctime)-15s %(levelname)-8s %(message)s" | ||||
|         logging.basicConfig(filename=LOG_FILENAME,level=10,format=LOG_FORMAT) | ||||
|         logging.info("Fpdb started") | ||||
|          | ||||
|         self.threads=[] | ||||
|         self.db=None | ||||
|         self.config = Configuration.Config(file=options.config, dbname=options.dbname) | ||||
|         self.load_profile() | ||||
|         self.threads = [] | ||||
|         self.db = None | ||||
|         self.status_bar = None | ||||
| 
 | ||||
|         self.window = gtk.Window(gtk.WINDOW_TOPLEVEL) | ||||
|         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.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.load_profile() | ||||
|         sys.stderr.write("fpdb starting ...") | ||||
|     #end def __init__ | ||||
| 
 | ||||
|  |  | |||
|  | @ -255,7 +255,6 @@ class fpdb_db: | |||
|         self.cursor.execute(self.sql.query['createPlayersTable']) | ||||
|         self.cursor.execute(self.sql.query['createAutoratesTable']) | ||||
|         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['createTourneysTable']) | ||||
|         self.cursor.execute(self.sql.query['createTourneysPlayersTable']) | ||||
|  | @ -587,17 +586,18 @@ class fpdb_db: | |||
|         print "analyze took", atime, "seconds" | ||||
|     #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 | ||||
|     # 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): | ||||
|         if self.backend == self.MYSQL_INNODB: | ||||
|             try: | ||||
|                 self.cursor.execute( "lock tables Hands write" ) | ||||
|                 self.cursor.execute( "lock tables Players write" ) | ||||
|             except: | ||||
|                 # Table 'fpdb.hands' doesn't exist | ||||
|                 if str(sys.exc_value).find(".Hands' doesn't exist") >= 0: | ||||
|                 # Table 'fpdb.players' doesn't exist | ||||
|                 if str(sys.exc_value).find(".Players' doesn't exist") >= 0: | ||||
|                     return(2) | ||||
|                 print "Error! failed to obtain global lock. Close all programs accessing " \ | ||||
|                       + "database (including fpdb) and try again (%s)." \ | ||||
|  | @ -605,11 +605,11 @@ class fpdb_db: | |||
|                 return(1) | ||||
|         elif self.backend == self.PGSQL: | ||||
|             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 | ||||
|             except: | ||||
|                 # relation "hands" does not exist | ||||
|                 if str(sys.exc_value).find('relation "hands" does not exist') >= 0: | ||||
|                 # relation "players" does not exist | ||||
|                 if str(sys.exc_value).find('relation "players" does not exist') >= 0: | ||||
|                     return(2) | ||||
|                 print "Error! failed to obtain global lock. Close all programs accessing " \ | ||||
|                       + "database (including fpdb) and try again (%s)." \ | ||||
|  |  | |||
|  | @ -32,6 +32,7 @@ import re | |||
| 
 | ||||
| import fpdb_simple | ||||
| import fpdb_db | ||||
| import Database | ||||
| import fpdb_parse_logic | ||||
| import Configuration | ||||
| 
 | ||||
|  | @ -58,7 +59,8 @@ class Importer: | |||
|         self.settings   = settings | ||||
|         self.caller     = caller | ||||
|         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.filelist   = {} | ||||
|         self.dirlist    = {} | ||||
|  | @ -76,6 +78,7 @@ class Importer: | |||
|         self.settings.setdefault("minPrint", 30) | ||||
|         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.do_connect(self.config) | ||||
|         self.fdb.db.rollback() | ||||
|  | @ -393,8 +396,9 @@ class Importer: | |||
|                     self.hand=hand | ||||
| 
 | ||||
|                     try: | ||||
|                         handsId = fpdb_parse_logic.mainParser(self.settings, self.fdb | ||||
|                                                            , self.siteIds[site], category, hand, self.config) | ||||
|                         handsId = fpdb_parse_logic.mainParser( self.settings, self.fdb | ||||
|                                                              , self.siteIds[site], category, hand | ||||
|                                                              , self.config, self.database ) | ||||
|                         self.fdb.db.commit() | ||||
| 
 | ||||
|                         stored += 1 | ||||
|  |  | |||
|  | @ -21,10 +21,13 @@ import fpdb_simple | |||
| import Database | ||||
| 
 | ||||
| #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'] | ||||
|     #This is redundant - hopefully fdb will be a Database object in an interation soon | ||||
|     db = Database.Database(config, 'fpdb', '') | ||||
|     if db == None: | ||||
|         #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]) | ||||
| 
 | ||||
|     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) | ||||
| #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 | ||||
|               ,hand_start_time, names, tableName, maxSeats, hudCache, | ||||
|               board_values, board_suits): | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	Block a user