Coverage for WinamaxSummary.py: 0%
196 statements
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-14 11:07 +0000
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-14 11:07 +0000
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
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.
19# import L10n
20# _ = L10n.get_translation()
22from decimal import Decimal
23import datetime
24from bs4 import BeautifulSoup
26from HandHistoryConverter import FpdbParseError
28import re
29import logging
31from TourneySummary import TourneySummary
33# Winamax HH Format
34log = logging.getLogger("parser")
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 }
52 substitutions = {
53 "LEGAL_ISO": "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
54 "LS": "\$|€|", # legal currency symbols
55 }
57 re_Identify = re.compile("Winamax\sPoker\s\-\sTournament\ssummary")
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 )
91 re_GameType = re.compile("""<h1>((?P<LIMIT>No Limit|Pot Limit) (?P<GAME>Hold\'em|Omaha))</h1>""")
93 re_TourNo = re.compile("ID\=(?P<TOURNO>[0-9]+)")
95 re_Player = re.compile(
96 """(?P<RANK>\d+)<\/td><td width="30%">(?P<PNAME>.+?)<\/td><td width="60%">(?P<WINNINGS>.+?)</td>"""
97 )
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,]+)""")
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.]+)€|Tremplin Winamax Poker Tour|Starting Block Winamax Poker Tour|Finale Freeroll Mobile 2012|SNG Freeroll Mobile 2012)"""
107 )
109 codepage = ("utf8", "cp1252")
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
121 def parseSummary(self):
122 if self.hhtype == "summary":
123 self.parseSummaryFile()
124 elif self.hhtype == "html":
125 self.parseSummaryHtml()
127 def parseSummaryHtml(self):
128 self.currency = "EUR"
129 soup = BeautifulSoup(self.summaryText)
130 tl = soup.findAll("div", {"class": "left_content"})
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("€", "")
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
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(",", ".")
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"
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"])
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)
202 for m in self.re_TourNo.finditer(self.summaryText):
203 mg = m.groupdict()
204 # print mg
205 self.tourNo = mg["TOURNO"]
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
214 mg = m.groupdict()
215 # print "DEBUG: m.groupdict(): %s" % m.groupdict()
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")
238 # FIXME: buyinCurrency and currency not detected
239 self.buyinCurrency = "EUR"
240 self.currency = "EUR"
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"
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")
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))
267 if self.buyin == 0 and self.fee == 0:
268 self.buyinCurrency = "FREE"
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
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"
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
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"])
322 if "TICKET" in mg and mg["TICKET"] is not None:
323 winnings += int(100 * self.convert_to_decimal(mg["TICKET"]))
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"
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)
340 def convert_to_decimal(self, string):
341 dec = self.clearMoneyString(string)
342 dec = Decimal(dec)
343 return dec