Coverage for WinamaxSummary.py: 0%

196 statements  

« prev     ^ index     » next       coverage.py v7.6.3, created at 2024-10-15 19:33 +0000

1#!/usr/bin/env python 

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

3 

4# Copyright 2008-2011 Carl Gherardi 

5# This program is free software: you can redistribute it and/or modify 

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

7# the Free Software Foundation, version 3 of the License. 

8# 

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

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

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

12# GNU General Public License for more details. 

13# 

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

15# along with this program. If not, see <http://www.gnu.org/licenses/>. 

16# In the "official" distribution you can find the license in agpl-3.0.txt. 

17 

18 

19# import L10n 

20# _ = L10n.get_translation() 

21 

22from decimal import Decimal 

23import datetime 

24from bs4 import BeautifulSoup 

25 

26from HandHistoryConverter import FpdbParseError 

27 

28import re 

29import logging 

30 

31from TourneySummary import TourneySummary 

32 

33# Winamax HH Format 

34log = logging.getLogger("parser") 

35 

36 

37class WinamaxSummary(TourneySummary): 

38 limits = {"No Limit": "nl", "Pot Limit": "pl", "Limit": "fl", "LIMIT": "fl"} 

39 games = { # base, category 

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

41 "Omaha": ("hold", "omahahi"), 

42 "5 Card Omaha": ("hold", "5_omahahi"), 

43 "Omaha 5": ("hold", "5_omahahi"), 

44 "5 Card Omaha Hi/Lo": ("hold", "5_omahahi"), # incorrect in file 

45 "Omaha Hi/Lo": ("hold", "omahahilo"), 

46 "7-Card Stud": ("stud", "studhi"), 

47 "7-Card Stud Hi/Lo": ("stud", "studhilo"), 

48 "Razz": ("stud", "razz"), 

49 "2-7 Triple Draw": ("draw", "27_3draw"), 

50 } 

51 

52 substitutions = { 

53 "LEGAL_ISO": "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes 

54 "LS": "\$|€|", # legal currency symbols 

55 } 

56 

57 re_Identify = re.compile("Winamax\sPoker\s\-\sTournament\ssummary") 

58 

59 re_SummaryTourneyInfo = re.compile( 

60 """\s:\s 

61 ((?P<LIMIT>No\sLimit|Limit|LIMIT|Pot\sLimit)\s)? 

62 (?P<GAME>.+)? 

63 \((?P<TOURNO>[0-9]+)\)(\s-\sLate\s(r|R)egistration)?\s+ 

64 (Player\s:\s(?P<PNAME>.*)\s+)? 

65 Buy-In\s:\s(?P<BUYIN>(?P<BIAMT>.+?)\s\+\s(?P<BIRAKE>.+?)(\s\+\s(?P<BIBOUNTY>.+))?|Freeroll|Gratuit|Ticket\suniquement|Free|Ticket)\s+ 

66 (Rebuy\scost\s:\s(?P<REBUY>(?P<REBUYAMT>.+)\s\+\s(?P<REBUYRAKE>.+))\s+)? 

67 (Addon\scost\s:\s(?P<ADDON>(?P<ADDONAMT>.+)\s\+\s(?P<ADDONRAKE>.+))\s+)? 

68 (Your\srebuys\s:\s(?P<PREBUYS>\d+)\s+)? 

69 (Your\saddons\s:\s(?P<PADDONS>\d+)\s+)? 

70 Registered\splayers\s:\s(?P<ENTRIES>[0-9]+)\s+ 

71 (Total\srebuys\s:\s\d+\s+)? 

72 (Total\saddons\s:\s\d+\s+)? 

73 (Prizepool\s:\s(?P<PRIZEPOOL1>[.0-9%(LS)s]+)\s+)? 

74 (Mode\s:\s(?P<MODE>.+)?\s+)? 

75 (Type\s:\s(?P<TYPE>.+)?\s+)? 

76 (Speed\s:\s(?P<SPEED>.+)?\s+)? 

77 (Flight\sID\s:\s.+\s+)? 

78 (Levels\s:\s.+\s+)? 

79 (Total\srebuys\s:\s(?P<TREBUYS>\d+)\s+)? 

80 (Total\saddons\s:\s(?P<TADDONS>\d+)\s+)? 

81 (Prizepool\s:\s(?P<PRIZEPOOL2>[.0-9%(LS)s]+)\s+)? 

82 Tournament\sstarted\s(?P<DATETIME>[0-9]{4}\/[0-9]{2}\/[0-9]{2}\s[0-9]{2}:[0-9]{2}:[0-9]{2}\sUTC)\s+ 

83 (?P<BLAH>You\splayed\s.+)\s+ 

84 You\sfinished\sin\s(?P<RANK>[.0-9]+)(st|nd|rd|th)?\splace\s+ 

85 (You\swon\s((?P<WINNINGS>[.0-9%(LS)s]+))?(\s\+\s)?(Ticket\s(?P<TICKET>[.0-9%(LS)s]+))?(\s\+\s)?(Bounty\s(?P<BOUNTY>[.0-9%(LS)s]+))?)? 

86 """ 

87 % substitutions, 

88 re.VERBOSE | re.MULTILINE, 

89 ) 

90 

91 re_GameType = re.compile("""<h1>((?P<LIMIT>No Limit|Pot Limit) (?P<GAME>Hold\'em|Omaha))</h1>""") 

92 

93 re_TourNo = re.compile("ID\=(?P<TOURNO>[0-9]+)") 

94 

95 re_Player = re.compile( 

96 """(?P<RANK>\d+)<\/td><td width="30%">(?P<PNAME>.+?)<\/td><td width="60%">(?P<WINNINGS>.+?)</td>""" 

97 ) 

98 

99 re_Details = re.compile("""<p class="text">(?P<LABEL>.+?) : (?P<VALUE>.+?)</p>""") 

100 re_Prizepool = re.compile("""<div class="title2">.+: (?P<PRIZEPOOL>[0-9,]+)""") 

101 

102 re_DateTime = re.compile( 

103 "\[(?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]+)" 

104 ) 

105 re_Ticket = re.compile( 

106 """ / (?P<TTYPE>Ticket (?P<VALUE>[0-9.]+)&euro;|Tremplin Winamax Poker Tour|Starting Block Winamax Poker Tour|Finale Freeroll Mobile 2012|SNG Freeroll Mobile 2012)""" 

107 ) 

108 

109 codepage = ("utf8", "cp1252") 

110 

111 @staticmethod 

112 def getSplitRe(self, head): 

113 re_SplitTourneys = re.compile("Winamax\sPoker\s-\sTournament\ssummary") 

114 m = re.search("<!DOCTYPE html PUBLIC", head) 

115 if m is not None: 

116 self.hhtype = "html" 

117 else: 

118 self.hhtype = "summary" 

119 return re_SplitTourneys 

120 

121 def parseSummary(self): 

122 if self.hhtype == "summary": 

123 self.parseSummaryFile() 

124 elif self.hhtype == "html": 

125 self.parseSummaryHtml() 

126 

127 def parseSummaryHtml(self): 

128 self.currency = "EUR" 

129 soup = BeautifulSoup(self.summaryText) 

130 tl = soup.findAll("div", {"class": "left_content"}) 

131 

132 ps = soup.findAll("p", {"class": "text"}) 

133 for p in ps: 

134 for m in self.re_Details.finditer(str(p)): 

135 mg = m.groupdict() 

136 # print mg 

137 if mg["LABEL"] == "Buy-in": 

138 mg["VALUE"] = mg["VALUE"].replace("&euro;", "") 

139 mg["VALUE"] = mg["VALUE"].replace("+", "") 

140 mg["VALUE"] = mg["VALUE"].strip(" $") 

141 bi, fee = mg["VALUE"].split(" ") 

142 self.buyin = int(100 * Decimal(bi)) 

143 self.fee = int(100 * Decimal(fee)) 

144 # print "DEBUG: bi: '%s' fee: '%s" % (self.buyin, self.fee) 

145 if mg["LABEL"] == "Nombre de joueurs inscrits": 

146 self.entries = mg["VALUE"] 

147 if mg["LABEL"] == "D\xc3\xa9but du tournoi": 

148 self.startTime = datetime.datetime.strptime(mg["VALUE"], "%d-%m-%Y %H:%M") 

149 if mg["LABEL"] == "Nombre de joueurs max": 

150 # Max seats i think 

151 pass 

152 

153 div = soup.findAll("div", {"class": "title2"}) 

154 for m in self.re_Prizepool.finditer(str(div)): 

155 mg = m.groupdict() 

156 # print mg 

157 self.prizepool = mg["PRIZEPOOL"].replace(",", ".") 

158 

159 for m in self.re_GameType.finditer(str(tl[0])): 

160 mg = m.groupdict() 

161 # print mg 

162 self.gametype["limitType"] = self.limits[mg["LIMIT"]] 

163 self.gametype["category"] = self.games[mg["GAME"]][1] 

164 else: 

165 # FIXME: No gametype 

166 # Quitte or Double, Starting Block Winamax Poker Tour 

167 # Do not contain enough the gametype. 

168 # Lookup the tid from the db, if it exists get the gametype info from there, otherwise ParseError 

169 log.warning(("WinamaxSummary.parseSummary: Gametype unknown defaulting to NLHE")) 

170 self.gametype["limitType"] = "nl" 

171 self.gametype["category"] = "holdem" 

172 

173 for m in self.re_Player.finditer(str(tl[0])): 

174 winnings = 0 

175 mg = m.groupdict() 

176 rank = mg["RANK"] 

177 name = mg["PNAME"] 

178 if rank != "...": 

179 rank = int(mg["RANK"]) 

180 # print "DEUBG: mg: '%s'" % mg 

181 is_satellite = self.re_Ticket.search(mg["WINNINGS"]) 

182 if is_satellite: 

183 # Ticket 

184 if is_satellite.group("VALUE"): 

185 winnings = self.convert_to_decimal(is_satellite.group("VALUE")) 

186 else: # Value not specified 

187 rank = 1 

188 # FIXME: Do lookup here 

189 # Tremplin Winamax Poker Tour 

190 # Starting Block Winamax Poker Tour 

191 pass 

192 # For stallites, any ticket means 1st 

193 if winnings > 0: 

194 rank = 1 

195 else: 

196 winnings = self.convert_to_decimal(mg["WINNINGS"]) 

197 

198 winnings = int(100 * Decimal(winnings)) 

199 # print "DEBUG: %s) %s: %s" %(rank, name, winnings) 

200 self.addPlayer(rank, name, winnings, self.currency, None, None, None) 

201 

202 for m in self.re_TourNo.finditer(self.summaryText): 

203 mg = m.groupdict() 

204 # print mg 

205 self.tourNo = mg["TOURNO"] 

206 

207 def parseSummaryFile(self): 

208 m = self.re_SummaryTourneyInfo.search(self.summaryText) 

209 if m is None: 

210 tmp = self.summaryText[0:200] 

211 log.error(("WinamaxSummary.parseSummaryFromFile: '%s'") % tmp) 

212 raise FpdbParseError 

213 

214 mg = m.groupdict() 

215 # print "DEBUG: m.groupdict(): %s" % m.groupdict() 

216 

217 if "LIMIT" in mg and mg["LIMIT"] is not None: 

218 self.gametype["limitType"] = self.limits[mg["LIMIT"]] 

219 self.gametype["category"] = self.games[mg["GAME"]][1] 

220 else: 

221 # FIXME: No gametype 

222 # Quitte or Double, Starting Block Winamax Poker Tour 

223 # Do not contain enough the gametype. 

224 # Lookup the tid from the db, if it exists get the gametype info from there, otherwise ParseError 

225 log.warning(("WinamaxSummary.parseSummary: Gametype unknown defaulting to NLHE")) 

226 self.gametype["limitType"] = "nl" 

227 self.gametype["category"] = "holdem" 

228 self.tourneyName = mg["GAME"] 

229 if "ENTRIES" in mg: 

230 self.entries = mg["ENTRIES"] 

231 if "PRIZEPOOL1" in mg and mg["PRIZEPOOL1"] is not None: 

232 self.prizepool = int(100 * self.convert_to_decimal(mg["PRIZEPOOL1"])) 

233 if "PRIZEPOOL2" in mg and mg["PRIZEPOOL2"] is not None: 

234 self.prizepool = int(100 * self.convert_to_decimal(mg["PRIZEPOOL2"])) 

235 if "DATETIME" in mg: 

236 self.startTime = datetime.datetime.strptime(mg["DATETIME"], "%Y/%m/%d %H:%M:%S UTC") 

237 

238 # FIXME: buyinCurrency and currency not detected 

239 self.buyinCurrency = "EUR" 

240 self.currency = "EUR" 

241 

242 if "BUYIN" in mg: 

243 # print "DEBUG: BUYIN '%s'" % mg['BUYIN'] 

244 if mg["BUYIN"] in ("Gratuit", "Freeroll", "Ticket uniquement", "Ticket"): 

245 self.buyin = 0 

246 self.fee = 0 

247 self.buyinCurrency = "FREE" 

248 else: 

249 if mg["BUYIN"].find("€") != -1: 

250 self.buyinCurrency = "EUR" 

251 elif mg["BUYIN"].find("FPP") != -1: 

252 self.buyinCurrency = "WIFP" 

253 elif mg["BUYIN"].find("Free") != -1: 

254 self.buyinCurrency = "WIFP" 

255 else: 

256 self.buyinCurrency = "play" 

257 

258 if mg["BIBOUNTY"] is not None and mg["BIRAKE"] is not None: 

259 self.koBounty = int(100 * Decimal(self.convert_to_decimal(mg["BIRAKE"].strip("\r")))) 

260 self.isKO = True 

261 mg["BIRAKE"] = mg["BIBOUNTY"].strip("\r") 

262 

263 rake = mg["BIRAKE"].strip("\r") 

264 self.buyin = int(100 * self.convert_to_decimal(mg["BIAMT"])) 

265 self.fee = int(100 * self.convert_to_decimal(rake)) 

266 

267 if self.buyin == 0 and self.fee == 0: 

268 self.buyinCurrency = "FREE" 

269 

270 if "REBUY" in mg and mg["REBUY"] is not None: 

271 self.isRebuy = True 

272 rebuyrake = mg["REBUYRAKE"].strip("\r") 

273 rebuyamt = int(100 * self.convert_to_decimal(mg["REBUYAMT"])) 

274 rebuyfee = int(100 * self.convert_to_decimal(rebuyrake)) 

275 self.rebuyCost = rebuyamt + rebuyfee 

276 if "ADDON" in mg and mg["ADDON"] is not None: 

277 self.isAddOn = True 

278 addonrake = mg["ADDONRAKE"].strip("\r") 

279 addonamt = int(100 * self.convert_to_decimal(mg["ADDONAMT"])) 

280 addonfee = int(100 * self.convert_to_decimal(addonrake)) 

281 self.addOnCost = addonamt + addonfee 

282 

283 if "TOURNO" in mg: 

284 self.tourNo = mg["TOURNO"] 

285 # self.maxseats = 

286 if int(self.entries) <= 10: # FIXME: obv not a great metric 

287 self.isSng = True 

288 if "MODE" in mg and mg["MODE"] is not None: 

289 if "sng" in mg["MODE"]: 

290 self.isSng = True 

291 if "SPEED" in mg and mg["SPEED"] is not None: 

292 if mg["SPEED"] == "turbo": 

293 self.speed = "Hyper" 

294 elif mg["SPEED"] == "semiturbo": 

295 self.speed = "Turbo" 

296 

297 if "PNAME" in mg and mg["PNAME"] is not None: 

298 name = mg["PNAME"].strip("\r") 

299 rank = mg["RANK"] 

300 if rank != "...": 

301 rank = int(mg["RANK"]) 

302 winnings = 0 

303 rebuyCount = None 

304 addOnCount = None 

305 koCount = None 

306 

307 if "WINNINGS" in mg and mg["WINNINGS"] is not None: 

308 if mg["WINNINGS"].find("€") != -1: 

309 self.currency = "EUR" 

310 elif mg["WINNINGS"].find("FPP") != -1: 

311 self.currency = "WIFP" 

312 elif mg["WINNINGS"].find("Free") != -1: 

313 self.currency = "WIFP" 

314 else: 

315 self.currency = "play" 

316 winnings = int(100 * self.convert_to_decimal(mg["WINNINGS"])) 

317 if "PREBUYS" in mg and mg["PREBUYS"] is not None: 

318 rebuyCount = int(mg["PREBUYS"]) 

319 if "PADDONS" in mg and mg["PADDONS"] is not None: 

320 addOnCount = int(mg["PADDONS"]) 

321 

322 if "TICKET" in mg and mg["TICKET"] is not None: 

323 winnings += int(100 * self.convert_to_decimal(mg["TICKET"])) 

324 

325 if "BOUNTY" in mg and mg["BOUNTY"] is not None: 

326 koCount = 100 * self.convert_to_decimal(mg["BOUNTY"]) / Decimal(self.koBounty) 

327 if winnings == 0: 

328 if mg["BOUNTY"].find("€") != -1: 

329 self.currency = "EUR" 

330 elif mg["BOUNTY"].find("FPP") != -1: 

331 self.currency = "WIFP" 

332 elif mg["BOUNTY"].find("Free") != -1: 

333 self.currency = "WIFP" 

334 else: 

335 self.currency = "play" 

336 

337 # print "DEBUG: addPlayer(%s, %s, %s, %s, %s, %s, %s)" %(rank, name, winnings, self.currency, rebuyCount, addOnCount, koCount) 

338 self.addPlayer(rank, name, winnings, self.currency, rebuyCount, addOnCount, koCount) 

339 

340 def convert_to_decimal(self, string): 

341 dec = self.clearMoneyString(string) 

342 dec = Decimal(dec) 

343 return dec