Coverage for TableWindow.py: 14%

147 statements  

« prev     ^ index     » next       coverage.py v7.6.7, created at 2024-11-18 00:10 +0000

1#!/usr/bin/env python 

2# -*- coding: utf-8 -*- 

3"""Base class for interacting with poker client windows. 

4 

5There are currently subclasses for X, OSX, and Windows. 

6 

7The class queries the poker client window for data of interest, such as 

8size and location. It also controls the signals to alert the HUD when the 

9client has been resized, destroyed, etc. 

10""" 

11# Copyright 2008 - 2011, Ray E. Barker 

12 

13# This program is free software; you can redistribute it and/or modify 

14# it under the terms of the GNU General Public License as published by 

15# the Free Software Foundation; either version 2 of the License, or 

16# (at your option) any later version. 

17# 

18# This program is distributed in the hope that it will be useful, 

19# but WITHOUT ANY WARRANTY; without even the implied warranty of 

20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

21# GNU General Public License for more details. 

22# 

23# You should have received a copy of the GNU General Public License 

24# along with this program; if not, write to the Free Software 

25# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

26 

27######################################################################## 

28 

29 

30# import L10n 

31# _ = L10n.get_translation() 

32 

33# Standard Library modules 

34import re 

35import logging 

36from time import sleep 

37 

38# FreePokerTools modules 

39import Configuration 

40from HandHistoryConverter import getTableTitleRe 

41from HandHistoryConverter import getTableNoRe 

42 

43c = Configuration.Config() 

44log = logging.getLogger("hud") 

45 

46# Global used for figuring out the current game being played from the title. 

47# The dict key is a tuple of (limit type, category) for the game. 

48# The list is the names for those games used by the supported poker sites 

49# This is currently only used for mixed games, so it only needs to support those 

50# games on PokerStars and Full Tilt. 

51nlpl_game_names = { # fpdb name Stars Name FTP Name (if different) 

52 ("nl", "holdem"): ("No Limit Hold'em",), 

53 ("pl", "holdem"): ("Pot Limit Hold'em",), 

54 ("pl", "omahahi"): ("Pot Limit Omaha", "Pot Limit Omaha Hi"), 

55} 

56limit_game_names = { # fpdb name Stars Name FTP Name 

57 ("fl", "holdem"): ("Limit Hold'em",), 

58 ("fl", "omahahilo"): ("Limit Omaha H/L",), 

59 ("fl", "studhilo"): ("Limit Stud H/L",), 

60 ("fl", "razz"): ("Limit Razz",), 

61 ("fl", "studhi"): ("Limit Stud", "Stud Hi"), 

62 ("fl", "27_3draw"): ("Limit Triple Draw 2-7 Lowball",), 

63} 

64 

65# A window title might have our table name + one of these words/ 

66# phrases. If it has this word in the title, it is not a table. 

67bad_words = ("History for table:", "HUD:", "Chat:", "FPDBHUD", "Lobby") 

68 

69# Each TableWindow object must have the following attributes correctly populated: 

70# tw.name = the table name from the title bar, which must to match the table name 

71# from the corresponding hand record in the db. 

72# tw.number = This is the system id number for the client table window in the 

73# format that the system presents it. This is Xid in Xwindows and 

74# hwnd in Microsoft Windows. 

75# tw.title = The full title from the window title bar. 

76# tw.width, tw.height = The width and height of the window in pixels. This is 

77# the internal width and height, not including the title bar and 

78# window borders. 

79# tw.x, tw.y = The x, y (horizontal, vertical) location of the window relative 

80# to the top left of the display screen. This also does not include the 

81# title bar and window borders. To put it another way, this is the 

82# screen location of (0, 0) in the working window. 

83# tournament = Tournament number for a tournament or None for a cash game. 

84# table = Table number for a tournament. 

85# gdkhandle = 

86# window = 

87# parent = 

88# game = 

89# search_string = 

90 

91 

92class Table_Window(object): 

93 def __init__(self, config, site, table_name=None, tournament=None, table_number=None): 

94 self.config = config 

95 self.site = site 

96 self.hud = None # fill in later 

97 self.gdkhandle = None 

98 self.number = None 

99 # check if  

100 if isinstance(table_name, bytes): 

101 log.debug(f"Décodage de table_name en UTF-8 : {table_name}") 

102 table_name = table_name.decode('utf-8') 

103 if isinstance(tournament, bytes): 

104 log.debug(f"Décodage de table_name en UTF-8 : {tournament}") 

105 tournament = tournament.decode('utf-8') 

106 if isinstance(table_number, bytes): 

107 log.debug(f"Décodage de table_name en UTF-8 : {table_number}") 

108 table_number = table_number.decode('utf-8') 

109 

110 if tournament is not None and table_number is not None: 

111 log.debug(tournament) 

112 self.tournament = int(tournament) 

113 log.debug(" tournement:") 

114 log.debug(self.tournament) 

115 log.debug("table_number:") 

116 log.debug(type(table_number)) 

117 log.debug(table_number) 

118 # temp bug correction for ipoker must investigate 

119 # if table_number is not an interger 

120 

121 log.debug("table_number error:") 

122 log.debug(type(table_number)) 

123 log.debug(table_number) 

124 self.table = int(table_number) 

125 log.debug(self.table) 

126 self.name = "%s - %s" % (self.tournament, self.table) 

127 self.type = "tour" 

128 table_kwargs = dict(tournament=self.tournament, table_number=self.table) 

129 self.tableno_re = getTableNoRe(self.config, self.site, tournament=self.tournament) 

130 elif table_name is not None: 

131 log.debug("table_number cash:") 

132 log.debug(type(table_name)) 

133 log.debug((table_name)) 

134 self.name = table_name 

135 self.type = "cash" 

136 self.tournament = None 

137 table_kwargs = dict(table_name=table_name) 

138 log.debug("table_kwarg cash:") 

139 log.debug(type(table_kwargs)) 

140 log.debug((table_kwargs)) 

141 else: 

142 return None 

143 

144 self.search_string = getTableTitleRe(self.config, self.site, self.type, **table_kwargs) 

145 log.debug(f"search string: {self.search_string}") 

146 # make a small delay otherwise Xtables.root.get_windows() 

147 # returns empty for unknown reasons 

148 sleep(0.1) 

149 

150 self.find_table_parameters() 

151 if not self.number: 

152 log.error(('Can\'t find table "%s" with search string "%s"'), table_name, self.search_string) 

153 

154 geo = self.get_geometry() 

155 if geo is None: 

156 return None 

157 self.width = geo["width"] 

158 self.height = geo["height"] 

159 self.x = geo["x"] 

160 log.debug(self.x) 

161 self.y = geo["y"] 

162 log.debug(self.y) 

163 self.oldx = self.x # attn ray: remove these two lines and update Hud.py::update_table_position() 

164 log.debug(self.oldx) 

165 self.oldy = self.y 

166 log.debug(self.oldy) 

167 self.game = self.get_game() 

168 

169 def __str__(self): 

170 likely_attrs = ( 

171 "number", 

172 "title", 

173 "site", 

174 "width", 

175 "height", 

176 "x", 

177 "y", 

178 "tournament", 

179 "table", 

180 "gdkhandle", 

181 "window", 

182 "parent", 

183 "key", 

184 "hud", 

185 "game", 

186 "search_string", 

187 "tableno_re", 

188 ) 

189 temp = "TableWindow object\n" 

190 for a in likely_attrs: 

191 if getattr(self, a, 0): 

192 temp += " %s = %s\n" % (a, getattr(self, a)) 

193 return temp 

194 

195 #################################################################### 

196 # "get" methods. These query the table and return the info to get. 

197 # They don't change the data in the table and are generally used 

198 # by the "check" methods. Most of the get methods are in the 

199 # subclass because they are specific to X, Windows, etc. 

200 def get_game(self): 

201 # title = self.get_window_title() 

202 # if title is None: 

203 # return False 

204 title = self.title 

205 

206 # check for nl and pl games first, to avoid bad matches 

207 for game, names in list(nlpl_game_names.items()): 

208 for name in names: 

209 if name in title: 

210 return game 

211 for game, names in list(limit_game_names.items()): 

212 for name in names: 

213 if name in title: 

214 return game 

215 return False 

216 

217 def get_table_no(self): 

218 new_title = self.get_window_title() 

219 log.debug(f"new table title: {new_title}") 

220 if new_title is None: 

221 return False 

222 

223 try: 

224 log.debug(f"before searching: {new_title}") 

225 mo = re.search(self.tableno_re, new_title) 

226 except AttributeError: #'Table' object has no attribute 'tableno_re' 

227 log.debug("'Table' object has no attribute 'tableno_re'") 

228 return False 

229 

230 if mo is not None: 

231 return int(mo.group(1)) 

232 return False 

233 

234 #################################################################### 

235 # check_table() is meant to be called by the hud periodically to 

236 # determine if the client has been moved or resized. check_table() 

237 # also checks and signals if the client has been closed. 

238 def check_table(self): 

239 return self.check_size() or self.check_loc() 

240 

241 #################################################################### 

242 # "check" methods. They use the corresponding get method, update the 

243 # table object and return the name of the signal to be emitted or 

244 # False if unchanged. These do not signal for destroyed 

245 # clients to prevent a race condition. 

246 

247 # These might be called by a Window.timeout, so they must not 

248 # return False, or the timeout will be cancelled. 

249 def check_size(self): 

250 new_geo = self.get_geometry() 

251 if new_geo is None: # window destroyed 

252 return "client_destroyed" 

253 

254 elif self.width != new_geo["width"] or self.height != new_geo["height"]: # window resized 

255 self.oldwidth = self.width 

256 self.width = new_geo["width"] 

257 self.oldheight = self.height 

258 self.height = new_geo["height"] 

259 return "client_resized" 

260 return False # no change 

261 

262 def check_loc(self): 

263 new_geo = self.get_geometry() 

264 if new_geo is None: # window destroyed 

265 return "client_destroyed" 

266 

267 if self.x != new_geo["x"] or self.y != new_geo["y"]: # window moved 

268 self.x = new_geo["x"] 

269 self.y = new_geo["y"] 

270 return "client_moved" 

271 return False # no change 

272 

273 def has_table_title_changed(self, hud): 

274 log.debug("before get_table_no()") 

275 result = self.get_table_no() 

276 log.debug(f"tb has change nb {result}") 

277 if result is not False and result != self.table: 

278 log.debug(f"compare result and self.table {result} {self.table}") 

279 self.table = result 

280 if hud is not None: 

281 log.debug("return True") 

282 return True 

283 log.debug("return False") 

284 return False 

285 

286 def check_bad_words(self, title): 

287 for word in bad_words: 

288 if word in title: 

289 return True 

290 return False