Coverage for WinningToFpdb.py: 0%

618 statements  

« prev     ^ index     » next       coverage.py v7.6.1, created at 2024-09-27 18:50 +0000

1#!/usr/bin/env python 

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

3# 

4# Copyright 2016, Chaz Littlejohn 

5#  

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

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

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

9# (at your option) any later version. 

10#  

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

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

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

14# GNU General Public License for more details. 

15#  

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

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

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

19######################################################################## 

20 

21#import L10n 

22#_ = L10n.get_translation() 

23 

24# TODO: straighten out discards for draw games 

25 

26import sys 

27from HandHistoryConverter import * 

28from decimal_wrapper import Decimal 

29 

30# Winning HH Format 

31 

32class Winning(HandHistoryConverter): 

33 

34 # Class Variables 

35 

36 version = 0 

37 sitename = "WinningPoker" 

38 filetype = "text" 

39 codepage = ("utf-16", "utf8", "cp1252") 

40 siteId = 24 # Needs to match id entry in Sites database 

41 sym = { 

42 'USD': "\$", 

43 'T$': "", 

44 "play": "" 

45 } 

46 substitutions = { 

47 'LEGAL_ISO': "USD|TB|CP", # legal ISO currency codes 

48 'LS': u"\$|", # legal currency symbols - Euro(cp1252, utf-8) 

49 'PLYR': r'(?P<PNAME>.+?)', 

50 'NUM':u".,\dK", 

51 'CUR': u"(\$|)", 

52 'BRKTS': r'(\(button\)\s|\(small\sblind\)\s|\(big\sblind\)\s|\(button\)\s\(small\sblind\)\s|\(button\)\s\(big\sblind\)\s)?', 

53 } 

54 games1 = {# base, category 

55 "Hold'em": ('hold', 'holdem'), 

56 "Six Plus Hold'em": ('hold', '6_holdem'), 

57 'Omaha': ('hold', 'omahahi'), 

58 'Omaha HiLow': ('hold', 'omahahilo'), 

59 '5Card Omaha H/L': ('hold', '5_omaha8'), 

60 '5Card Omaha': ('hold', '5_omaha'), 

61 'Seven Cards Stud': ('stud', 'studhi'), 

62 'Seven Cards Stud HiLow': ('stud', 'studhilo') 

63 } 

64 games2 = {# base, category 

65 "Holdem": ('hold', 'holdem'), 

66 'Omaha': ('hold', 'omahahi'), 

67 'Omaha H/L': ('hold', 'omahahilo'), 

68 '5Card Omaha H/L': ('hold', '5_omaha8'), 

69 '5Card Omaha': ('hold', '5_omaha'), 

70 #"Six Plus Hold'em" : ('hold','6_holdem'), 

71 '7Stud': ('stud', 'studhi'), 

72 '7Stud H/L': ('stud', 'studhilo') 

73 } 

74 limits = { 

75 'No Limit': 'nl', 

76 'Pot Limit': 'pl', 

77 'Fixed Limit': 'fl', 

78 'All-in or Fold Limit': 'al' 

79 } 

80 speeds = { 

81 'Turbo': 'Turbo', 

82 'Hyper Turbo': 'Hyper', 

83 'Regular': 'Normal' 

84 } 

85 buyin = { 

86 'CAP': 'cap', 

87 'Short': 'shallow' 

88 } 

89 

90 SnG_Fee = { 

91 50: {'Hyper': 0, 'Turbo': 0, 'Normal': 5}, 

92 100: {'Hyper': 0, 'Turbo': 0, 'Normal': 10}, 

93 150: {'Hyper': 11, 'Turbo': 12, 'Normal': 15}, 

94 300: {'Hyper': 20, 'Turbo': 25, 'Normal': 30}, 

95 500: {'Hyper': 30, 'Turbo': 45, 'Normal': 50}, 

96 1000: {'Hyper': 55, 'Turbo': 90, 'Normal': 100}, 

97 1500: {'Hyper': 80, 'Turbo': 140, 'Normal': 150}, 

98 2000: {'Hyper': 100, 'Turbo': 175, 'Normal': 200}, 

99 3000: {'Hyper': 130, 'Turbo': 275, 'Normal': 300}, 

100 5000: {'Hyper': 205, 'Turbo': 475, 'Normal': 500}, 

101 8000: {'Hyper': 290, 'Turbo': 650, 'Normal': 800}, 

102 10000: {'Hyper': 370, 'Turbo': 800, 'Normal': 900} 

103 } 

104 

105 HUSnG_Fee = { 

106 200: {'Hyper': 10, 'Turbo': 0, 'Normal': 17}, 

107 220: {'Hyper': 0, 'Turbo': 16, 'Normal': 0}, 

108 240: {'Hyper': 10, 'Turbo': 0, 'Normal': 0}, 

109 500: {'Hyper': 0, 'Turbo': 0, 'Normal': 25}, 

110 550: {'Hyper': 0, 'Turbo': 25, 'Normal': 0}, 

111 600: {'Hyper': 18, 'Turbo': 0, 'Normal': 0}, 

112 1000: {'Hyper': 25, 'Turbo': 0, 'Normal': 50}, 

113 1100: {'Hyper': 0, 'Turbo': 50, 'Normal': 0}, 

114 1200: {'Hyper': 25, 'Turbo': 0, 'Normal': 0}, 

115 2000: {'Hyper': 50, 'Turbo': 0, 'Normal': 100}, 

116 2200: {'Hyper': 0, 'Turbo': 100, 'Normal': 0}, 

117 2400: {'Hyper': 50, 'Turbo': 0, 'Normal': 0}, 

118 3000: {'Hyper': 70, 'Turbo': 0, 'Normal': 150}, 

119 3300: {'Hyper': 0, 'Turbo': 150, 'Normal': 0}, 

120 3600: {'Hyper': 75, 'Turbo': 0, 'Normal': 0}, 

121 5000: {'Hyper': 100, 'Turbo': 0, 'Normal': 250}, 

122 5500: {'Hyper': 0, 'Turbo': 250, 'Normal': 0}, 

123 6000: {'Hyper': 125, 'Turbo': 0, 'Normal': 0}, 

124 10000: {'Hyper': 200, 'Turbo': 0, 'Normal': 450}, 

125 11000: {'Hyper': 0, 'Turbo': 450, 'Normal': 0}, 

126 12000: {'Hyper': 225, 'Turbo': 0, 'Normal': 0}, 

127 15000: {'Hyper': 266, 'Turbo': 0, 'Normal': 0}, 

128 20000: {'Hyper': 400, 'Turbo': 0, 'Normal': 900}, 

129 22000: {'Hyper': 0, 'Turbo': 900, 'Normal': 0}, 

130 24000: {'Hyper': 450, 'Turbo': 0, 'Normal': 0}, 

131 30000: {'Hyper': 600, 'Turbo': 0, 'Normal': 1200}, 

132 33000: {'Hyper': 0, 'Turbo': 1200, 'Normal': 0}, 

133 36000: {'Hyper': 600, 'Turbo': 0, 'Normal': 0}, 

134 40000: {'Hyper': 800, 'Turbo': 0, 'Normal': 0}, 

135 50000: {'Hyper': 0, 'Turbo': 0, 'Normal': 5000}, 

136 55000: {'Hyper': 0, 'Turbo': 2000, 'Normal': 0}, 

137 60000: {'Hyper': 1000, 'Turbo': 0, 'Normal': 0}, 

138 110000: {'Hyper': 0, 'Turbo': 3000, 'Normal': 0}, 

139 120000: {'Hyper': 1500, 'Turbo': 0, 'Normal': 0} 

140 } 

141 currencies = { '$':'USD', '':'T$'} 

142 

143 re_GameInfo1 = re.compile(u""" 

144 Game\sID:\s(?P<HID>\d+)\s 

145 (?P<SB>[%(NUM)s]+)/(?P<BB>[%(NUM)s]+)\s 

146 (?P<TABLE>.+?)?\s 

147 \((?P<GAME>(Six\sPlus\s)?Hold\'em|Omaha|Omaha\sHiLow|Seven\sCards\sStud|Seven\sCards\sStud\sHiLow)\) 

148 (\s(?P<MAX>\d+\-max))?$ 

149 """ % substitutions, 

150 re.MULTILINE|re.VERBOSE 

151 ) 

152 

153 #Hand #78708209 - Omaha H/L(Fixed Limit) - $20.00/$40.00 - 2019/07/18 15:13:01 UTC 

154 #Hand #68217077 - Holdem(No Limit) - $0.05/$0.10 - 2019/06/28 02:38:17 UTC 

155 #Game Hand #80586589 - Tournament #11182752 - Holdem(No Limit) - Level 15 (250.00/500.00)- 2019/07/21 17:44:50 UTC 

156 #Game Hand #82980175 - Tournament #11212445 - Omaha H/L(Pot Limit) - Level 1 (250.00/500.00)- 2019/07/25 02:31:33 UTC 

157 

158 re_GameInfo2 = re.compile(u""" 

159 (Game\s)?Hand\s\#(?P<HID>[0-9]+)\s\-\s 

160 ( 

161 (?P<TOUR>([\$.,\dK]+\sGTD\s)?Tournament\s\#(?P<TOURNO>\d+)\s\-\s) # open paren of tournament info 

162 )? 

163 # close paren of tournament info 

164 (?P<GAME>Holdem|Omaha|Omaha\sH/L|5Card\sOmaha\sH/L|5Card\sOmaha|7Stud|7Stud\sH/L) 

165 \((?P<LIMIT>No\sLimit|Fixed\sLimit|Pot\sLimit|All\-in\sor\sFold\sLimit)\)\s\-\s 

166 (Level\s(?P<LEVEL>[IVXLC\d]+)\s)? 

167 \(? # open paren of the stakes 

168 (?P<CURRENCY>%(LS)s|)? 

169 ((?P<SB>[.0-9]+)/(%(LS)s)?(?P<BB>[.0-9]+)) 

170 \)? # close paren of the stakes 

171 \s?\-\s 

172 (?P<DATETIME>.*$) 

173 """ % substitutions, re.MULTILINE|re.VERBOSE) 

174 

175 #Seat 6: puccini (5.34). 

176 re_PlayerInfo1 = re.compile(u""" 

177 ^Seat\s(?P<SEAT>[0-9]+):\s 

178 (?P<PNAME>.*)\s 

179 \((?P<CASH>[%(NUM)s]+)\) 

180 \.$ 

181 """ % substitutions, 

182 re.MULTILINE|re.VERBOSE 

183 ) 

184 

185 re_PlayerInfo2 = re.compile(u""" 

186 ^\s?Seat\s(?P<SEAT>[0-9]+):\s 

187 (?P<PNAME>.*)\s 

188 \((%(LS)s)?(?P<CASH>[,.0-9]+) 

189 \) 

190 (?P<SITOUT>\sis\ssitting\sout)?""" % substitutions, 

191 re.MULTILINE|re.VERBOSE 

192 ) 

193 

194 re_DateTime1 = re.compile(""" 

195 ^Game\sstarted\sat:\s 

196 (?P<Y>[0-9]{4})/(?P<M>[0-9]{1,2})/(?P<D>[0-9]{1,2})\s 

197 (?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+) 

198 $""", 

199 re.MULTILINE|re.VERBOSE 

200 ) 

201 

202 #2019/07/18 15:13:01 UTC 

203 re_DateTime2 = re.compile("""(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+)""", re.MULTILINE) 

204 

205 #$2.20 Turbo Heads-up, Table 1 

206 #$2.40 Hyper Turbo Heads-up, Table 1 

207 #$10 Freeroll - On Demand, Table 13 

208 #$25 GTD - On Demand, Table 1 

209 #$5 Regular 9-Max, Table 1 (Hold'em) 

210 

211 re_Table1 = re.compile(u""" 

212 ^(?P<CURRENCY>[%(LS)s]|)?(?P<BUYIN>[%(NUM)s]+)\s 

213 ((?P<GAME>(Six\sPlus\s)?Holdem|PLO|PLO8|Omaha\sHi/Lo|Omaha|PL\sOmaha|PL\sOmaha\sHi/Lo|PLO\sHi/Lo)\s?)? 

214 ((?P<SPECIAL>(GTD|Freeroll|FREEBUY|Freebuy))\s?)? 

215 ((?P<SPEED>(Turbo|Hyper\sTurbo|Regular))\s?)? 

216 ((?P<MAX>(\d+\-Max|Heads\-up|Heads\-Up))\s?)? 

217 (?P<OTHER>.*?) 

218 ,\sTable\s(?P<TABLENO>\d+) 

219 """ % substitutions, 

220 re.VERBOSE|re.MULTILINE 

221 ) 

222 

223 re_Table2 = re.compile("Table\s\'(?P<TABLENO>\d+)\'") 

224 

225 #St. Lucie 6-max Seat #1 is the button 

226 #Table '1' 9-max Seat #3 is the button 

227 #Blitz Poker 6-max Seat #1 is the button 

228 #Table '25' 9-max Seat #8 is the button 

229 

230 re_HandInfo = re.compile(""" 

231 ^(?P<TABLE>.+?)\s 

232 ((?P<MAX>\d+)-max\s) 

233 (?P<PLAY>\(Play\sMoney\)\s)? 

234 (Seat\s\#(?P<BUTTON>\d+)\sis\sthe\sbutton)?""", 

235 re.MULTILINE|re.VERBOSE) 

236 

237 re_TourneyName1 = re.compile(u"(?P<TOURNAME>.*),\sTable\s\d+") 

238 re_TourneyName2 = re.compile(u"TN\-(?P<TOURNAME>.+?)\sGAMETYPE") 

239 re_GTD = re.compile(u"(?P<GTD>[%(NUM)s]+)\sGTD" % substitutions) 

240 re_buyinType = re.compile("\((?P<BUYINTYPE>CAP|Short)\)", re.MULTILINE) 

241 re_buyin = re.compile("%(CUR)s(?P<BUYIN>[,.0-9]+)" % substitutions, re.MULTILINE) 

242 re_Step = re.compile("\sStep\s(?P<STEPNO>\d+)") 

243 

244 re_Identify = re.compile(u'Game\sID:\s\d+|Hand\s\#\d+\s\-\s') 

245 re_Identify_Old = re.compile(u'Game\sID:\s\d+') 

246 re_SplitHands = re.compile('\n\n') 

247 re_Button1 = re.compile('Seat (?P<BUTTON>\d+) is the button') 

248 re_Button2 = re.compile('Seat #(?P<BUTTON>\d+) is the button') 

249 re_Board = re.compile(r"\[(?P<CARDS>.+)\]") 

250 re_TourNo = re.compile("\sT(?P<TOURNO>\d+)\-") 

251 re_File1 = re.compile("HH\d{8}\s(T\d+\-)?G\d+") 

252 re_File2 = re.compile("(?P<TYPE>CASHID|SITGOID|RUSHID|SCHEDULEDID)") 

253 

254 re_PostSB1 = re.compile(r"^Player %(PLYR)s has small blind \((?P<SB>[%(NUM)s]+)\)" % substitutions, re.MULTILINE) 

255 re_PostBB1 = re.compile(r"^Player %(PLYR)s has big blind \((?P<BB>[%(NUM)s]+)\)" % substitutions, re.MULTILINE) 

256 re_Posts1 = re.compile(r"^Player %(PLYR)s posts \((?P<SBBB>[%(NUM)s]+)\)" % substitutions, re.MULTILINE) 

257 re_Antes1 = re.compile(r"^Player %(PLYR)s (posts )?ante \((?P<ANTE>[%(NUM)s]+)\)" % substitutions, re.MULTILINE) 

258 re_BringIn1 = re.compile(r"^Player %(PLYR)s bring in \((?P<BRINGIN>[%(NUM)s]+)\)" % substitutions, re.MULTILINE) 

259 re_HeroCards1 = re.compile(r"^Player %(PLYR)s received card: \[(?P<CARD>.+)\]" % substitutions, re.MULTILINE) 

260 

261 re_PostSB2 = re.compile(r"^%(PLYR)s posts the small blind %(CUR)s(?P<SB>[,.0-9]+)" % substitutions, re.MULTILINE) 

262 re_PostBB2 = re.compile(r"^%(PLYR)s posts the big blind %(CUR)s(?P<BB>[,.0-9]+)" % substitutions, re.MULTILINE) 

263 re_PostBoth2 = re.compile(r"^%(PLYR)s posts dead %(CUR)s(?P<SBBB>[,.0-9]+)" % substitutions, re.MULTILINE) 

264 re_Posts2 = re.compile(r"^%(PLYR)s posts %(CUR)s(?P<SBBB>[,.0-9]+)" % substitutions, re.MULTILINE) 

265 re_Antes2 = re.compile(r"^%(PLYR)s posts ante %(CUR)s(?P<ANTE>[,.0-9]+)" % substitutions, re.MULTILINE) 

266 re_BringIn2 = re.compile(r"^%(PLYR)s brings[- ]in( low|) %(CUR)s(?P<BRINGIN>[,.0-9]+)" % substitutions, re.MULTILINE) 

267 re_HeroCards2 = re.compile(r"^Dealt to %(PLYR)s(?: \[(?P<OLDCARDS>.+?)\])?( \[(?P<NEWCARDS>.+?)\])" % substitutions, re.MULTILINE) 

268 re_Uncalled = re.compile('Uncalled bet \(%(CUR)s(?P<BET>[,.\d]+)\) returned to' % substitutions, re.MULTILINE) 

269 

270 re_Action1 = re.compile(r""" 

271 ^Player\s(%(PLYR)s)?\s(?P<ATYPE>bets|checks|raises|calls|folds|allin|straddle|caps|cap) 

272 (\s\((?P<BET>[%(NUM)s]+)\))? 

273 $""" % substitutions, 

274 re.MULTILINE|re.VERBOSE 

275 ) 

276 

277 re_Action2 = re.compile(r""" 

278 ^%(PLYR)s(?P<ATYPE>\sbets|\schecks|\sraises|\scalls|\sfolds|\scaps|\scap|\sstraddle) 

279 (\s%(CUR)s(?P<BET>[,.\d]+))?(\sto\s%(CUR)s(?P<BETTO>[,.\d]+))?  

280 \s*(and\sis\sall\-in)?\s*$""" 

281 % substitutions, re.MULTILINE|re.VERBOSE 

282 ) 

283 

284 #Player lessthanrocko shows: Two pairs. 8s and 5s [3s 3h]. Bets: 420. Collects: 0. Loses: 420. 

285 #*Player ChazDazzle shows: Full House (5/8) [7s 5s]. Bets: 420. Collects: 840. Wins: 420. 

286 #*Player fullstacker shows: Flush, A high [2s 8h 2h Jd] Low hand (A A 2 3 4 8 ).Bets: 0.50. Collects: 0.95. Wins: 0.45. 

287 

288 #*Player ChazDazzle shows: High card A [6h 10d 2c As 7d 4d 9s] Low hand (A A 2 4 6 7 ).Bets: 3.55. Collects: 3.53. Loses: 0.02. 

289 #*Player KickAzzJohnny shows: Two pairs. 8s and 3s [5d 3d 3s 6s 8s 8h Ad]. Bets: 3.55. Collects: 3.52. Loses: 0.03. 

290 

291 re_ShownCards1 = re.compile(r""" 

292 ^\*?Player\s%(PLYR)s\sshows:\s 

293 (?P<STRING>.+?)\s 

294 \[(?P<CARDS>.*)\] 

295 (\sLow\shand\s\((?P<STRING2>.+?)\s?\))? 

296 \.""" % substitutions, 

297 re.MULTILINE|re.VERBOSE 

298 ) 

299 

300 #Seat 5: LitAF did not show and won $0.25 

301 #Seat 6: Thrash370 showed [Td Ad Qd 4s] and won 60600.00 with HI - a straight, Queen high [Qd Jh Td 9d 8d] | LO - [8,5,4,2,1] 

302 re_ShownCards2 = re.compile(r""" 

303 ^Seat\s(?P<SEAT>[0-9]+):\s%(PLYR)s\s%(BRKTS)s 

304 (?P<SHOWED>showed|mucked)\s\[(?P<CARDS>.+?)\](\sand\s(lost|(won|collected)\s%(CUR)s(?P<POT>[,\.\d]+)) 

305 \swith (?P<STRING>.+?) 

306 (,\sand\s(won\s\(%(CUR)s[\.\d]+\)|lost)\swith\s(?P<STRING2>.*))?)?  

307 $""" 

308 % substitutions, 

309 re.MULTILINE|re.VERBOSE 

310 ) 

311 

312 re_CollectPot1 = re.compile(r""" 

313 ^\*?Player\s%(PLYR)s\s 

314 (does\snot\sshow|shows|mucks) 

315 .+?\.\s? 

316 Bets:\s[%(NUM)s]+\.\s 

317 Collects:\s(?P<POT>[%(NUM)s]+)\.\s 

318 (Wins|Loses):\s[%(NUM)s]+\.? 

319 $""" % substitutions, 

320 re.MULTILINE|re.VERBOSE 

321 ) 

322 

323 #Seat 5: LitAF did not show and won $0.25 

324 #Seat 6: Thrash370 showed [Td Ad Qd 4s] and won 60600.00 with HI - a straight, Queen high [Qd Jh Td 9d 8d] | LO - [8,5,4,2,1] 

325 re_CollectPot2 = re.compile(r""" 

326 Seat\s(?P<SEAT>[0-9]+):\s%(PLYR)s\s%(BRKTS)s 

327 (did\snot\sshow\sand\swon|showed\s\[.+?\]\sand\s(won|collected))\s%(CUR)s(?P<POT>[,.\d]+) 

328 (,\smucked|\swith.*|) 

329 """ % substitutions, 

330 re.MULTILINE|re.VERBOSE 

331 ) 

332 #AssFungus collected $92.25 from main pot 1 

333 re_CollectPot3 = re.compile(r"^%(PLYR)s collected %(CUR)s(?P<POT>[,.\d]+)" % substitutions, re.MULTILINE) 

334 

335 def compilePlayerRegexs(self, hand): 

336 pass 

337 

338 def readSupportedGames(self): 

339 return [ 

340 ["ring", "hold", "nl"], 

341 ["ring", "hold", "fl"], 

342 ["ring", "hold", "pl"], 

343 ["ring", "hold", "al"], 

344 

345 ["ring", "stud", "fl"], 

346 

347 ["tour", "hold", "nl"], 

348 ["tour", "hold", "fl"], 

349 ["tour", "hold", "pl"], 

350 ["tour", "hold", "al"], 

351 

352 ["tour", "stud", "fl"] 

353 ] 

354 

355 def determineGameType(self, handText): 

356 if self.re_Identify_Old.search(handText): 

357 self.version = 1 

358 return self._determineGameType1(handText) 

359 else: 

360 self.version = 2 

361 return self._determineGameType2(handText) 

362 

363 def _determineGameType1(self, handText): 

364 info = {} 

365 if not self.re_File1.search(self.in_path): 

366 tmp = "Invalid filename: %s" % self.in_path 

367 log.debug(("WinningToFpdb.determineGameType: '%s'") % tmp) 

368 raise FpdbHandPartial(tmp) 

369 

370 m = self.re_GameInfo1.search(handText) 

371 if not m: 

372 tmp = handText[0:200] 

373 log.error(("WinningToFpdb.determineGameType: '%s'") % tmp) 

374 raise FpdbParseError 

375 

376 mg = m.groupdict() 

377 m1 = self.re_TourNo.search(self.in_path) 

378 if m1: mg.update(m1.groupdict()) 

379 

380 if 'GAME' in mg: 

381 (info['base'], info['category']) = self.games1[mg['GAME']] 

382 if 'SB' in mg: 

383 info['sb'] = mg['SB'] 

384 if 'BB' in mg: 

385 info['bb'] = mg['BB'] 

386 

387 if info['base'] == 'stud': 

388 info['limitType'] = 'fl' 

389 else: 

390 m2 = self.re_PostBB1.search(handText) 

391 if m2: 

392 bb = self.clearMoneyString(m2.group('BB')) 

393 if Decimal(self.clearMoneyString(info['sb'])) == Decimal(bb): 

394 info['limitType'] = 'fl' 

395 

396 if info.get('limitType') == None: 

397 if 'omaha' in info['category']: 

398 info['limitType'] = 'pl' 

399 else: 

400 info['limitType'] = 'nl' 

401 

402 if 'TOURNO' in mg and mg['TOURNO'] is not None: 

403 info['type'] = 'tour' 

404 else: 

405 info['type'] = 'ring' 

406 

407 if 'TABLE' in mg and mg['TABLE'] is not None: 

408 if re.match('PM\s',mg['TABLE']): 

409 info['currency'] = 'play' 

410 elif info['type'] == 'tour': 

411 info['currency'] = 'T$' 

412 else: 

413 info['currency'] = 'USD' 

414 

415 if '(Cap)' in mg['TABLE']: 

416 info['buyinType'] = 'cap' 

417 elif '(Short)' in mg['TABLE']: 

418 info['buyinType'] = 'shallow' 

419 else: 

420 info['buyinType'] = 'regular' 

421 else: 

422 info['currency'] = 'T$' 

423 

424 if info['limitType'] == 'fl' and info['bb'] is not None: 

425 info['sb'] = str((Decimal(mg['SB'])/2).quantize(Decimal("0.01"))) 

426 info['bb'] = str(Decimal(mg['SB']).quantize(Decimal("0.01"))) 

427 

428 return info 

429 

430 def _determineGameType2(self, handText): 

431 info = {} 

432 m = self.re_GameInfo2.search(handText) 

433 if not m: 

434 tmp = handText[0:200] 

435 log.error(("WinningToFpdb._determineGameType2: '%s'") % tmp) 

436 raise FpdbParseError 

437 

438 mg = m.groupdict() 

439 

440 m1 = self.re_File2.search(self.in_path) 

441 if m1: mg.update(m1.groupdict()) 

442 

443 if 'LIMIT' in mg: 

444 info['limitType'] = self.limits[mg['LIMIT']] 

445 if 'GAME' in mg: 

446 (info['base'], info['category']) = self.games2[mg['GAME']] 

447 if 'SB' in mg: 

448 info['sb'] = mg['SB'] 

449 if 'BB' in mg: 

450 info['bb'] = mg['BB'] 

451 if 'CURRENCY' in mg and mg['CURRENCY'] is not None: 

452 info['currency'] = self.currencies[mg['CURRENCY']] 

453 

454 if 'TYPE' in mg and 'RUSHID' == mg['TYPE']: 

455 info['fast'] = True 

456 else: 

457 info['fast'] = False 

458 

459 if 'TOURNO' in mg and mg['TOURNO'] is None: 

460 info['type'] = 'ring' 

461 else: 

462 info['type'] = 'tour' 

463 

464 if info.get('currency') in ('T$', None) and info['type']=='ring': 

465 info['currency'] = 'play' 

466 

467 if info['limitType'] == 'fl' and info['bb'] is not None: 

468 info['sb'] = str((Decimal(mg['SB'])/2).quantize(Decimal("0.01"))) 

469 info['bb'] = str(Decimal(mg['SB']).quantize(Decimal("0.01"))) 

470 

471 return info 

472 

473 def readHandInfo(self, hand): 

474 if self.version == 1: 

475 self._readHandInfo1(hand) 

476 else: 

477 self._readHandInfo2(hand) 

478 

479 def _readHandInfo1(self, hand): 

480 #First check if partial 

481 if hand.handText.count('------ Summary ------')!=1: 

482 raise FpdbHandPartial(("Hand is not cleanly split into pre and post Summary")) 

483 

484 info = {} 

485 m = self.re_GameInfo1.search(hand.handText) 

486 m2 = self.re_DateTime1.search(hand.handText) 

487 if m is None or m2 is None: 

488 tmp = hand.handText[0:200] 

489 log.error(("WinningToFpdb.readHandInfo: '%s'") % tmp) 

490 raise FpdbParseError 

491 

492 info.update(m.groupdict()) 

493 

494 m1 = self.re_TourNo.search(self.in_path) 

495 if m1: info.update(m1.groupdict()) 

496 

497 datetimestr = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), m2.group('M'), m2.group('D'), m2.group('H'), m2.group('MIN'), m2.group('S')) 

498 hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET" 

499 hand.startTime = HandHistoryConverter.changeTimezone(hand.startTime, self.import_parameters['timezone'], "UTC") 

500 

501 if 'TOURNO' in info: 

502 hand.tourNo = info['TOURNO'] 

503 

504 if 'HID' in info: 

505 hand.handid = info['HID'] 

506 

507 if 'MAX' in info and info['MAX'] != None: 

508 hand.maxseats = int(info['MAX'].replace('-max', '')) 

509 

510 if not hand.maxseats: 

511 if hand.gametype['base'] == 'stud': 

512 hand.maxseats = 8 

513 elif hand.gametype['type'] == 'ring': 

514 hand.maxseats = 9 

515 else: 

516 hand.maxseats = 10 

517 

518 if 'TABLE' in info and info['TABLE'] is not None: 

519 if hand.tourNo: 

520 hand.buyin = 0 

521 hand.fee = 0 

522 hand.buyinCurrency="NA" 

523 hand.tablename = 1 

524 m3 = self.re_Table1.search(info['TABLE']) 

525 if m3 is not None: 

526 tableinfo = m3.groupdict() 

527 if 'SPECIAL' in tableinfo and tableinfo['SPECIAL'] != None: 

528 if tableinfo['SPECIAL'] in ('Freeroll', 'FREEBUY', 'Freebuy'): 

529 hand.buyinCurrency="FREE" 

530 hand.guaranteeAmt = int(100*Decimal(self.clearMoneyString(tableinfo['BUYIN']))) 

531 

532 if hand.guaranteeAmt == 0: 

533 hand.buyinCurrency="USD" 

534 hand.buyin = int(100*Decimal(self.clearMoneyString(tableinfo['BUYIN']))) 

535 

536 if 'MAX' in tableinfo and tableinfo['MAX'] != None: 

537 n = tableinfo['MAX'].replace('-Max', '') 

538 if n in ('Heads-up', 'Heads-Up'): 

539 hand.maxseats = 2 

540 else: 

541 hand.maxseats = int(n) 

542 

543 if 'SPEED' in tableinfo and tableinfo['SPEED'] != None: 

544 hand.speed = self.speeds[tableinfo['SPEED']] 

545 if hand.maxseats==2 and hand.buyin in self.HUSnG_Fee: 

546 hand.fee = self.HUSnG_Fee[hand.buyin][hand.speed] 

547 hand.isSng = True 

548 if hand.maxseats!=2 and hand.buyin in self.SnG_Fee: 

549 hand.fee = self.SnG_Fee[hand.buyin][hand.speed] 

550 hand.isSng = True 

551 

552 hand.tablename = int(m3.group('TABLENO')) 

553 

554 if "On Demand" in info['TABLE']: 

555 hand.isOnDemand = True 

556 

557 if " KO" in info['TABLE'] or "Knockout" in info['TABLE']: 

558 hand.isKO = True 

559 

560 if "R/A" in info['TABLE']: 

561 hand.isRebuy = True 

562 hand.isAddOn = True 

563 

564 m4 = self.re_TourneyName1.search(info['TABLE']) 

565 if m4: 

566 hand.tourneyName = m4.group('TOURNAME') 

567 else: 

568 hand.tablename = info['TABLE'] 

569 buyin_type = self.re_buyinType.search(info['TABLE']) 

570 if buyin_type: 

571 hand.gametype['buyinType'] = self.buyin[buyin_type.group('BUYINTYPE')] 

572 else: 

573 hand.buyin = 0 

574 hand.fee = 0 

575 hand.buyinCurrency="NA" 

576 hand.tablename = 1 

577 

578 def _readHandInfo2(self, hand): 

579 #First check if partial 

580 if hand.handText.count('*** SUMMARY ***')!=1: 

581 raise FpdbHandPartial(("Hand is not cleanly split into pre and post Summary")) 

582 

583 info = {} 

584 m = self.re_GameInfo2.search(hand.handText) 

585 m1 = self.re_HandInfo.search(hand.handText) 

586 if m is None or m1 is None: 

587 tmp = hand.handText[0:200] 

588 log.error(("WinningToFpdb.readHandInfo: '%s'") % tmp) 

589 raise FpdbParseError 

590 

591 info.update(m.groupdict()) 

592 info.update(m1.groupdict()) 

593 

594 for key in info: 

595 if key == 'DATETIME': 

596 datetimestr = "2000/01/01 00:00:00" # default used if time not found 

597 m2 = self.re_DateTime2.finditer(info[key]) 

598 for a in m2: 

599 datetimestr = "%s/%s/%s %s:%s:%s" % (a.group('Y'), a.group('M'),a.group('D'),a.group('H'),a.group('MIN'),a.group('S')) 

600 #tz = a.group('TZ') # just assume ET?? 

601 #print " tz = ", tz, " datetime =", datetimestr 

602 hand.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S") # also timezone at end, e.g. " ET" 

603 if key == 'HID': 

604 hand.handid = info[key] 

605 if key == 'TOURNO': 

606 hand.tourNo = info[key] 

607 if key == 'LEVEL': 

608 hand.level = info[key] 

609 if key == 'TABLE': 

610 if info['TOURNO'] is not None: 

611 hand.buyin = 0 

612 hand.fee = 0 

613 hand.buyinCurrency = "FREE" #FIXME 

614 

615 m2 = self.re_Table2.match(info[key]) 

616 if m2: 

617 hand.tablename = m2.group('TABLENO') 

618 else: 

619 hand.tablename = info[key] 

620 if key == 'BUTTON': 

621 hand.buttonpos = info[key] 

622 if key == 'MAX' and info[key] != None: 

623 hand.maxseats = int(info[key]) 

624 

625 if 'SCHEDULEDID' in self.in_path: 

626 m3 = self.re_TourneyName2.search(self.in_path) 

627 if m3: 

628 hand.tourneyName = m3.group('TOURNAME').replace('{BACKSLASH}', '\\') 

629 m4 = self.re_GTD.search(hand.tourneyName) 

630 if m4: 

631 hand.isGuarantee = True 

632 hand.guaranteeAmt = int(100*Decimal(self.clearMoneyString(m4.group('GTD')))) 

633 if 'Satellite' in hand.tourneyName: 

634 hand.isSatellite = True 

635 if 'Shootout' in hand.tourneyName: 

636 hand.isShootout = True 

637 

638 elif 'SITGOID' in self.in_path: 

639 hand.isSng = True 

640 m3 = self.re_TourneyName2.search(self.in_path) 

641 if m3: 

642 hand.tourneyName = m3.group('TOURNAME').replace('{BACKSLASH}', '\\') 

643 if ' Hyper Turbo ' in hand.tourneyName: 

644 speed = 'Hyper Turbo' 

645 elif ' Turbo ' in hand.tourneyName: 

646 speed = 'Turbo' 

647 else: 

648 speed = 'Regular' 

649 

650 hand.speed = self.speeds[speed] 

651 

652 m4 = self.re_buyin.match(hand.tourneyName) 

653 if m4: 

654 hand.buyinCurrency="USD" 

655 hand.buyin = int(100*Decimal(self.clearMoneyString(m4.group('BUYIN')))) 

656 

657 if hand.maxseats==2 and hand.buyin in self.HUSnG_Fee: 

658 hand.fee = self.HUSnG_Fee[hand.buyin][hand.speed] 

659 if hand.maxseats!=2 and hand.buyin in self.SnG_Fee: 

660 hand.fee = self.SnG_Fee[hand.buyin][hand.speed] 

661 

662 m5 = self.re_Step.search(hand.tourneyName) 

663 if m5: 

664 hand.isStep = True 

665 hand.stepNo = int(m5.group('STEPNO')) 

666 

667 elif 'RUSHID' in self.in_path: 

668 (hand.gametype['fast'], hand.isFast) = (True, True) 

669 

670 def readButton(self, hand): 

671 if self.version == 1: 

672 self._readButton1(hand) 

673 else: 

674 self._readButton2(hand) 

675 

676 def _readButton1(self, hand): 

677 m = self.re_Button1.search(hand.handText) 

678 if m: 

679 hand.buttonpos = int(m.group('BUTTON')) 

680 else: 

681 log.info('readButton: ' + ('not found')) 

682 

683 def _readButton2(self, hand): 

684 m = self.re_Button2.search(hand.handText) 

685 if m: 

686 hand.buttonpos = int(m.group('BUTTON')) 

687 else: 

688 log.info('readButton: ' + ('not found')) 

689 

690 def readPlayerStacks(self, hand): 

691 if self.version == 1: 

692 self._readPlayerStacks1(hand) 

693 else: 

694 self._readPlayerStacks2(hand) 

695 

696 def _readPlayerStacks1(self, hand): 

697 pre, post = hand.handText.split('------ Summary ------') 

698 m = self.re_PlayerInfo1.finditer(pre) 

699 for a in m: 

700 hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), self.clearMoneyString(a.group('CASH'))) 

701 

702 def _readPlayerStacks2(self, hand): 

703 pre, post = hand.handText.split('*** SUMMARY ***') 

704 m = self.re_PlayerInfo2.finditer(pre) 

705 for a in m: 

706 hand.addPlayer(int(a.group('SEAT')), a.group('PNAME'), self.clearMoneyString(a.group('CASH'))) 

707 

708 def markStreets(self, hand): 

709 if self.version ==1: 

710 self._markStreets1(hand) 

711 else: 

712 self._markStreets2(hand) 

713 

714 def _markStreets1(self, hand): 

715 if hand.gametype['base'] in ("hold"): 

716 m = re.search(r"(?P<PREFLOP>.+(?=\*\*\* FLOP \*\*\*:)|.+)" 

717 r"(\*\*\* FLOP \*\*\*:(?P<FLOP> (\[\S\S\S?] )?\[\S\S\S? ?\S\S\S? \S\S\S?].+(?=\*\*\* TURN \*\*\*:)|.+))?" 

718 r"(\*\*\* TURN \*\*\*: \[\S\S\S? \S\S\S? \S\S\S?] (?P<TURN>\[\S\S\S?\].+(?=\*\*\* RIVER \*\*\*:)|.+))?" 

719 r"(\*\*\* RIVER \*\*\*: \[\S\S\S? \S\S\S? \S\S\S? \S\S\S?] ?(?P<RIVER>\[\S\S\S?\].+))?", hand.handText,re.DOTALL) 

720 elif hand.gametype['base'] in ("stud"): 

721 m = re.search(r"(?P<THIRD>.+(?=\*\*\* Third street \*\*\*)|.+)" 

722 r"(\*\*\* Third street \*\*\*(?P<FOURTH>.+(?=\*\*\* Fourth street \*\*\*)|.+))?" 

723 r"(\*\*\* Fourth street \*\*\*(?P<FIFTH>.+(?=\*\*\* Fifth street \*\*\*)|.+))?" 

724 r"(\*\*\* Fifth street \*\*\*(?P<SIXTH>.+(?=\*\*\* Sixth street \*\*\*)|.+))?" 

725 r"(\*\*\* Sixth street \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL) 

726 hand.addStreets(m) 

727 

728 def _markStreets2(self, hand): 

729 if hand.gametype['base'] in ("hold"): 

730 m = re.search(r"\*\*\* HOLE CARDS \*\*\*(?P<PREFLOP>(.+(?P<FLOPET>\[\S\S\]))?.+(?=\*\*\* (FLOP|FIRST FLOP|FLOP 1) \*\*\*)|.+)" 

731 r"(\*\*\* FLOP \*\*\*(?P<FLOP> (\[\S\S\] )?\[(\S\S ?)?\S\S \S\S\].+(?=\*\*\* (TURN|FIRST TURN|TURN 1) \*\*\*)|.+))?" 

732 r"(\*\*\* TURN \*\*\* \[\S\S \S\S \S\S] (?P<TURN>\[\S\S\].+(?=\*\*\* (RIVER|FIRST RIVER|RIVER 1) \*\*\*)|.+))?" 

733 r"(\*\*\* RIVER \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER>\[\S\S\].+))?" 

734 r"(\*\*\* (FIRST FLOP|FLOP 1) \*\*\*(?P<FLOP1> (\[\S\S\] )?\[(\S\S ?)?\S\S \S\S\].+(?=\*\*\* (FIRST TURN|TURN 1) \*\*\*)|.+))?" 

735 r"(\*\*\* (FIRST TURN|TURN 1) \*\*\* \[\S\S \S\S \S\S] (?P<TURN1>\[\S\S\].+(?=\*\*\* (FIRST RIVER|RIVER 1) \*\*\*)|.+))?" 

736 r"(\*\*\* (FIRST RIVER|RIVER 1) \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER1>\[\S\S\].+?(?=\*\*\* (SECOND (FLOP|TURN|RIVER)|(FLOP|TURN|RIVER) 2) \*\*\*)|.+))?" 

737 r"(\*\*\* (SECOND FLOP|FLOP 2) \*\*\*(?P<FLOP2> (\[\S\S\] )?\[\S\S ?\S\S \S\S\].+(?=\*\*\* (SECOND TURN|TURN 2) \*\*\*)|.+))?" 

738 r"(\*\*\* (SECOND TURN|TURN 2) \*\*\* \[\S\S \S\S \S\S] (?P<TURN2>\[\S\S\].+(?=\*\*\* (SECOND RIVER|RIVER 2) \*\*\*)|.+))?" 

739 r"(\*\*\* (SECOND RIVER|RIVER 2) \*\*\* \[\S\S \S\S \S\S \S\S] (?P<RIVER2>\[\S\S\].+))?", hand.handText,re.DOTALL) 

740 elif hand.gametype['base'] in ("stud"): 

741 m = re.search(r"(?P<ANTES>.+(?=\*\*\* 3rd STREET \*\*\*)|.+)" 

742 r"(\*\*\* 3rd STREET \*\*\*(?P<THIRD>.+(?=\*\*\* 4th STREET \*\*\*)|.+))?" 

743 r"(\*\*\* 4th STREET \*\*\*(?P<FOURTH>.+(?=\*\*\* 5th STREET \*\*\*)|.+))?" 

744 r"(\*\*\* 5th STREET \*\*\*(?P<FIFTH>.+(?=\*\*\* 6th STREET \*\*\*)|.+))?" 

745 r"(\*\*\* 6th STREET \*\*\*(?P<SIXTH>.+(?=\*\*\* 7th STREET \*\*\*)|.+))?" 

746 r"(\*\*\* 7th STREET \*\*\*(?P<SEVENTH>.+))?", hand.handText,re.DOTALL) 

747 hand.addStreets(m) 

748 

749 def readCommunityCards(self, hand, street): 

750 if self.version == 1: 

751 self._readCommunityCards1(hand, street) 

752 else: 

753 self._readCommunityCards2(hand, street) 

754 if street in ('FLOP1', 'TURN1', 'RIVER1', 'FLOP2', 'TURN2', 'RIVER2'): 

755 hand.runItTimes = 2 

756 

757 def _readCommunityCards1(self, hand, street): # street has been matched by markStreets, so exists in this hand 

758 m = self.re_Board.search(hand.streets[street]) 

759 if m: 

760 hand.setCommunityCards(street, [c.replace("10", "T") for c in m.group('CARDS').split(' ')]) 

761 else: 

762 log.error("WinningToFpdb._readCommunityCards1: No community cards found on %s %s" % (street, hand.handid)) 

763 raise FpdbParseError 

764 

765 def _readCommunityCards2(self, hand, street): # street has been matched by markStreets, so exists in this hand 

766 m = self.re_Board.search(hand.streets[street]) 

767 if m: 

768 hand.setCommunityCards(street, m.group('CARDS').split(' ')) 

769 else: 

770 log.error("WinningToFpdb._readCommunityCards2: No community cards found on %s %s" % (street, hand.handid)) 

771 raise FpdbParseError 

772 

773 def readAntes(self, hand): 

774 if self.version == 1: 

775 self._readAntes1(hand) 

776 else: 

777 self._readAntes2(hand) 

778 

779 def _readAntes1(self, hand): 

780 log.debug(("reading antes")) 

781 m = self.re_Antes1.finditer(hand.handText) 

782 for player in m: 

783 #~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))) 

784 hand.addAnte(player.group('PNAME'), player.group('ANTE')) 

785 

786 def _readAntes2(self, hand): 

787 log.debug(("reading antes")) 

788 m = self.re_Antes2.finditer(hand.handText) 

789 for player in m: 

790 #~ logging.debug("hand.addAnte(%s,%s)" %(player.group('PNAME'), player.group('ANTE'))) 

791 hand.addAnte(player.group('PNAME'), player.group('ANTE')) 

792 

793 def readBringIn(self, hand): 

794 if self.version == 1: 

795 self._readBringIn1(hand) 

796 else: 

797 self._readBringIn2(hand) 

798 

799 def _readBringIn1(self, hand): 

800 m = self.re_BringIn1.search(hand.handText,re.DOTALL) 

801 if m: 

802 #~ logging.debug("readBringIn: %s for %s" %(m.group('PNAME'), m.group('BRINGIN'))) 

803 hand.addBringIn(m.group('PNAME'), m.group('BRINGIN')) 

804 

805 def _readBringIn2(self, hand): 

806 m = self.re_BringIn2.search(hand.handText,re.DOTALL) 

807 if m: 

808 #~ logging.debug("readBringIn: %s for %s" %(m.group('PNAME'), m.group('BRINGIN'))) 

809 hand.addBringIn(m.group('PNAME'), m.group('BRINGIN')) 

810 

811 def readBlinds(self, hand): 

812 if self.version == 1: 

813 self._readBlinds1(hand) 

814 else: 

815 self._readBlinds2(hand) 

816 

817 def _readBlinds1(self, hand): 

818 liveBlind = True 

819 for a in self.re_PostSB1.finditer(hand.handText): 

820 if liveBlind: 

821 hand.addBlind(a.group('PNAME'), 'small blind', a.group('SB')) 

822 liveBlind = False 

823 else: 

824 pass 

825 # Post dead blinds as ante 

826 #hand.addBlind(a.group('PNAME'), 'secondsb', a.group('SB')) 

827 for a in self.re_PostBB1.finditer(hand.handText): 

828 hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) 

829 for a in self.re_Posts1.finditer(hand.handText): 

830 if Decimal(self.clearMoneyString(a.group('SBBB'))) == Decimal(hand.bb): 

831 hand.addBlind(a.group('PNAME'), 'big blind', a.group('SBBB')) 

832 else: 

833 hand.addBlind(a.group('PNAME'), 'secondsb', a.group('SBBB')) 

834 

835 def _readBlinds2(self, hand): 

836 liveBlind = True 

837 for a in self.re_PostSB2.finditer(hand.handText): 

838 if liveBlind: 

839 hand.addBlind(a.group('PNAME'), 'small blind', a.group('SB')) 

840 liveBlind = False 

841 else: 

842 pass 

843 # Post dead blinds as ante 

844 #hand.addBlind(a.group('PNAME'), 'secondsb', a.group('SB')) 

845 for a in self.re_PostBB2.finditer(hand.handText): 

846 hand.addBlind(a.group('PNAME'), 'big blind', a.group('BB')) 

847 for a in self.re_PostBoth2.finditer(hand.handText): 

848 hand.addBlind(a.group('PNAME'), 'both', self.clearMoneyString(a.group('SBBB'))) 

849 for a in self.re_Posts2.finditer(hand.handText): 

850 if Decimal(self.clearMoneyString(a.group('SBBB'))) == Decimal(hand.bb): 

851 hand.addBlind(a.group('PNAME'), 'big blind', a.group('SBBB')) 

852 else: 

853 hand.addBlind(a.group('PNAME'), 'secondsb', a.group('SBBB')) 

854 

855 def readHoleCards(self, hand): 

856 if self.version == 1: 

857 self._readHoleCards1(hand) 

858 else: 

859 self._readHoleCards2(hand) 

860 

861 def _readHoleCards1(self, hand): 

862# streets PREFLOP, PREDRAW, and THIRD are special cases beacause 

863# we need to grab hero's cards 

864 for street in ('PREFLOP', 'DEAL'): 

865 if street in hand.streets.keys(): 

866 newcards = [] 

867 m = self.re_HeroCards1.finditer(hand.streets[street]) 

868 for found in m: 

869 hand.hero = found.group('PNAME') 

870 newcards.append(found.group('CARD').replace("10", "T")) 

871 if hand.hero: 

872 hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True) 

873 

874 for street, text in list(hand.streets.items()): 

875 if not text or street in ('PREFLOP', 'DEAL'): continue # already done these 

876 m = self.re_HeroCards1.finditer(hand.streets[street]) 

877 players = {} 

878 for found in m: 

879 player = found.group('PNAME') 

880 if players.get(player) == None: 

881 players[player] = [] 

882 players[player].append(found.group('CARD').replace("10", "T")) 

883 

884 for player, cards in list(players.items()): 

885 if street == 'THIRD': # hero in stud game 

886 hand.dealt.add(player) # need this for stud?? 

887 if len(cards)==3: 

888 hand.hero = player 

889 hand.addHoleCards(street, player, closed=cards[0:2], open=[cards[2]], shown=False, mucked=False, dealt=False) 

890 else: 

891 hand.addHoleCards(street, player, closed=[], open=cards, shown=False, mucked=False, dealt=False) 

892 elif street == 'SEVENTH': 

893 if hand.hero==player: 

894 hand.addHoleCards(street, player, open=cards, closed=[], shown=False, mucked=False, dealt=False) 

895 else: 

896 hand.addHoleCards(street, player, open=[], closed=cards, shown=False, mucked=False, dealt=False) 

897 else: 

898 hand.addHoleCards(street, player, open=cards, closed=[], shown=False, mucked=False, dealt=False) 

899 

900 def _readHoleCards2(self, hand): 

901# streets PREFLOP, PREDRAW, and THIRD are special cases beacause 

902# we need to grab hero's cards 

903 for street in ('PREFLOP', 'DEAL'): 

904 if street in hand.streets.keys(): 

905 newcards = [] 

906 m = self.re_HeroCards2.finditer(hand.streets[street]) 

907 for found in m: 

908 hand.hero = found.group('PNAME') 

909 newcards = found.group('NEWCARDS').split(' ') 

910 if hand.hero: 

911 hand.addHoleCards(street, hand.hero, closed=newcards, shown=False, mucked=False, dealt=True) 

912 

913 for street, text in list(hand.streets.items()): 

914 if not text or street in ('PREFLOP', 'DEAL'): continue # already done these 

915 m = self.re_HeroCards2.finditer(hand.streets[street]) 

916 for found in m: 

917 player = found.group('PNAME') 

918 if found.group('NEWCARDS') is None: 

919 newcards = [] 

920 else: 

921 newcards = found.group('NEWCARDS').split(' ') 

922 if found.group('OLDCARDS') is None: 

923 oldcards = [] 

924 else: 

925 oldcards = found.group('OLDCARDS').split(' ') 

926 

927 if street == 'THIRD' and len(newcards) == 3: # hero in stud game 

928 hand.hero = player 

929 hand.dealt.add(player) # need this for stud?? 

930 hand.addHoleCards(street, player, closed=newcards[0:2], open=[newcards[2]], shown=False, mucked=False, dealt=False) 

931 else: 

932 hand.addHoleCards(street, player, open=newcards, closed=oldcards, shown=False, mucked=False, dealt=False) 

933 

934 def readAction(self, hand, street): 

935 if self.version == 1: 

936 self._readAction1(hand, street) 

937 else: 

938 self._readAction2(hand, street) 

939 

940 def _readAction1(self, hand, street): 

941 m = self.re_Action1.finditer(hand.streets[street]) 

942 for action in m: 

943 acts = action.groupdict() 

944 if action.group('PNAME') == None: 

945 log.error("WinningToFpdb.readAction: Unknown player %s %s" % (action.group('ATYPE'), hand.handid)) 

946 raise FpdbParseError 

947 

948 if action.group('ATYPE') == 'folds': 

949 hand.addFold( street, action.group('PNAME')) 

950 elif action.group('ATYPE') == 'checks': 

951 hand.addCheck( street, action.group('PNAME')) 

952 elif action.group('ATYPE') == 'calls': 

953 hand.addCall( street, action.group('PNAME'), self.clearMoneyString(action.group('BET')) ) 

954 elif action.group('ATYPE') in ('raises', 'straddle', 'caps', 'cap'): 

955 hand.addCallandRaise( street, action.group('PNAME'), self.clearMoneyString(action.group('BET')) ) 

956 elif action.group('ATYPE') == 'bets': 

957 hand.addBet( street, action.group('PNAME'), self.clearMoneyString(action.group('BET')) ) 

958 elif action.group('ATYPE') == 'allin': 

959 player = action.group('PNAME') 

960 # disconnected all in 

961 if action.group('BET') == None: 

962 amount = str(hand.stacks[player]) 

963 else: 

964 amount = self.clearMoneyString(action.group('BET')).replace(u',', u'') #some sites have commas 

965 Ai = Decimal(amount) 

966 Bp = hand.lastBet[street] 

967 Bc = sum(hand.bets[street][player]) 

968 C = Bp - Bc 

969 if Ai <= C: 

970 hand.addCall(street, player, amount) 

971 elif Bp == 0: 

972 hand.addBet(street, player, amount) 

973 else: 

974 hand.addCallandRaise(street, player, amount) 

975 else: 

976 log.debug(("DEBUG:") + " " + ("Unimplemented %s: '%s' '%s'") % ("readAction", action.group('PNAME'), action.group('ATYPE'))) 

977 

978 def _readAction2(self, hand, street): 

979 m = self.re_Action2.finditer(hand.streets[street]) 

980 for action in m: 

981 acts = action.groupdict() 

982 #log.error("DEBUG: %s acts: %s" % (street, acts)) 

983 if action.group('ATYPE') == ' folds': 

984 hand.addFold( street, action.group('PNAME')) 

985 elif action.group('ATYPE') == ' checks': 

986 hand.addCheck( street, action.group('PNAME')) 

987 elif action.group('ATYPE') == ' calls': 

988 hand.addCall( street, action.group('PNAME'), self.clearMoneyString(action.group('BET')) ) 

989 elif action.group('ATYPE') in (' raises', ' straddle', ' caps', ' cap'): 

990 if action.group('BETTO') is not None: 

991 hand.addRaiseTo( street, action.group('PNAME'), self.clearMoneyString(action.group('BETTO')) ) 

992 elif action.group('BET') is not None: 

993 hand.addCallandRaise( street, action.group('PNAME'), self.clearMoneyString(action.group('BET')) ) 

994 elif action.group('ATYPE') == ' bets': 

995 hand.addBet( street, action.group('PNAME'), self.clearMoneyString(action.group('BET')) ) 

996 else: 

997 log.debug(("DEBUG:") + " " + ("Unimplemented %s: '%s' '%s'") % ("readAction", action.group('PNAME'), action.group('ATYPE'))) 

998 

999 def readCollectPot(self,hand): 

1000 if self.version == 1: 

1001 self._readCollectPot1(hand) 

1002 elif hand.runItTimes == 2: 

1003 self._readCollectPot3(hand) 

1004 else: 

1005 self._readCollectPot2(hand) 

1006 

1007 def _readCollectPot1(self,hand): 

1008 for m in self.re_CollectPot1.finditer(hand.handText): 

1009 if Decimal(self.clearMoneyString(m.group('POT'))) > 0: 

1010 hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT')) 

1011 

1012 def _readCollectPot2(self,hand): 

1013 pre, post = hand.handText.split('*** SUMMARY ***') 

1014 acts, bovadaUncalled_v1, bovadaUncalled_v2, blindsantes, adjustment = hand.actions.get('PREFLOP'), False, False, 0, 0 

1015 names = [p[1] for p in hand.players] 

1016 if acts != None and len([a for a in acts if a[1] != 'folds']) == 0: 

1017 m0 = self.re_Uncalled.search(hand.handText) 

1018 if m0 and Decimal(m0.group('BET')) == Decimal(hand.bb): 

1019 bovadaUncalled_v2 = True 

1020 elif m0 == None: 

1021 bovadaUncalled_v1 = True 

1022 has_sb = len([a[2] for a in hand.actions.get('BLINDSANTES') if a[1] == 'small blind']) > 0 

1023 adjustment = (Decimal(hand.bb) - Decimal(hand.sb)) if has_sb else Decimal(hand.bb) 

1024 blindsantes = sum([a[2] for a in hand.actions.get('BLINDSANTES')]) 

1025 else: 

1026 m0 = self.re_Uncalled.search(hand.handText) 

1027 if not m0: 

1028 hand.setUncalledBets(True) 

1029 

1030 for m in self.re_CollectPot2.finditer(post): 

1031 pot = self.clearMoneyString(m.group('POT')) 

1032 if bovadaUncalled_v1 and Decimal(pot) == (blindsantes): 

1033 hand.addCollectPot(player=m.group('PNAME'),pot=str(Decimal(pot) - adjustment)) 

1034 elif bovadaUncalled_v2: 

1035 hand.addCollectPot(player=m.group('PNAME'),pot=str(Decimal(pot)*2)) 

1036 else: 

1037 hand.addCollectPot(player=m.group('PNAME'),pot=pot) 

1038 

1039 def _readCollectPot3(self,hand): 

1040 for m in self.re_CollectPot3.finditer(hand.handText): 

1041 hand.addCollectPot(player=m.group('PNAME'),pot=m.group('POT')) 

1042 

1043 def readShowdownActions(self, hand): 

1044 # TODO: pick up mucks also?? 

1045 pass 

1046 

1047 def readShownCards(self,hand): 

1048 if self.version == 1: 

1049 self._readShownCards1(hand) 

1050 else: 

1051 self._readShownCards2(hand) 

1052 

1053 def _readShownCards1(self,hand): 

1054 for m in self.re_ShownCards1.finditer(hand.handText): 

1055 if m.group('CARDS') is not None: 

1056 cards = m.group('CARDS') 

1057 cards = [c.replace("10", "T") for c in cards.split(' ')] # needs to be a list, not a set--stud needs the order 

1058 string = m.group('STRING') 

1059 if m.group('STRING2'): 

1060 string += '|' + m.group('STRING2') 

1061 

1062 (shown, mucked) = (False, False) 

1063 #if m.group('SHOWED') == "showed": shown = True 

1064 #elif m.group('SHOWED') == "mucked": mucked = True 

1065 

1066 #print "DEBUG: hand.addShownCards(%s, %s, %s, %s)" %(cards, m.group('PNAME'), shown, mucked) 

1067 hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked, string=string) 

1068 

1069 def _readShownCards2(self,hand): 

1070 for m in self.re_ShownCards2.finditer(hand.handText): 

1071 if m.group('CARDS') is not None: 

1072 cards = m.group('CARDS') 

1073 cards = cards.split(' ') # needs to be a list, not a set--stud needs the order 

1074 string = m.group('STRING') 

1075 if m.group('STRING2'): 

1076 string += '|' + m.group('STRING2') 

1077 

1078 (shown, mucked) = (False, False) 

1079 if m.group('SHOWED') == "showed": shown = True 

1080 elif m.group('SHOWED') == "mucked": mucked = True 

1081 

1082 #print "DEBUG: hand.addShownCards(%s, %s, %s, %s)" %(cards, m.group('PNAME'), shown, mucked) 

1083 hand.addShownCards(cards=cards, player=m.group('PNAME'), shown=shown, mucked=mucked, string=string) 

1084 

1085 @staticmethod 

1086 def getTableTitleRe(type, table_name=None, tournament = None, table_number=None): 

1087 "Returns string to search in windows titles" 

1088 regex = re.escape(str(table_name)) 

1089 if type=="tour": 

1090 regex = ", Table " + re.escape(str(table_number)) + "\s\-.*\s\(" + re.escape(str(tournament)) + "\)" 

1091 log.info("Winning.getTableTitleRe: table_name='%s' tournament='%s' table_number='%s'" % (table_name, tournament, table_number)) 

1092 log.info("Winning.getTableTitleRe: returns: '%s'" % (regex)) 

1093 return regex 

1094