Coverage for WinningSummary.py: 0%
116 statements
« prev ^ index » next coverage.py v7.6.3, created at 2024-10-15 19:33 +0000
« 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 -*-
4# Copyright 2016 Chaz Littlejohn
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.
18"""winning poker specific summary parsing code"""
20from __future__ import division
22from past.utils import old_div
23# import L10n
24# _ = L10n.get_translation()
26from HandHistoryConverter import HandHistoryConverter, FpdbParseError, FpdbHandPartial
27import re
28import logging
29import datetime
30from decimal import Decimal
31from TourneySummary import TourneySummary
33# Winning HH Format
34log = logging.getLogger("parser")
37class WinningSummary(TourneySummary):
38 sym = {"USD": "\$", "T$": "", "play": ""}
39 substitutions = {
40 "LEGAL_ISO": "TB|CP", # legal ISO currency codes
41 "LS": "\$|", # legal currency symbols
42 "PLYR": r"(?P<PNAME>.+?)",
43 "NUM": ".,\dK",
44 }
45 games = { # base, category
46 "Hold'em": ("hold", "holdem"),
47 "Omaha": ("hold", "omahahi"),
48 "Omaha HiLow": ("hold", "omahahilo"),
49 "Seven Cards Stud": ("stud", "studhi"),
50 "Seven Cards Stud HiLow": ("stud", "studhilo"),
51 }
53 speeds = {"Turbo": "Turbo", "Hyper Turbo": "Hyper", "Regular": "Normal"}
55 re_Identify = re.compile(r'<link\sid="ctl00_CalendarTheme"')
57 re_HTMLPlayer = re.compile(r"Player\sDetails:\s%(PLYR)s</a>" % substitutions, re.IGNORECASE)
59 re_HTMLTourneyInfo = re.compile(
60 r"<td>(?P<TOURNO>[0-9]+)</td>"
61 r"<td>(?P<GAME>Hold\'em|Omaha|Omaha\sHiLow|Seven\sCards\sStud|Seven\sCards\sStud\sHiLow)</td>"
62 r"<td>(?P<TOURNAME>.*)</td>"
63 r"<td>(?P<CURRENCY>[%(LS)s])(?P<BUYIN>[%(NUM)s]+)</td>"
64 r"<td>[%(NUM)s]+</td>"
65 r"<td>[%(NUM)s]+</td>"
66 r"<td>[%(NUM)s]+</td>"
67 r"<td>[%(LS)s](?P<FEE>[%(NUM)s]+)</td>"
68 r"<td>[%(NUM)s]+</td>"
69 r"<td>[%(NUM)s]+</td>"
70 r"<td>[%(NUM)s]+</td>"
71 r"<td>[%(LS)s](?P<REBUYS>[%(NUM)s]+)</td>"
72 r"<td>[%(NUM)s]+</td>"
73 r"<td>[%(NUM)s]+</td>"
74 r"<td>[%(NUM)s]+</td>"
75 r"<td>[%(LS)s](?P<ADDONS>[%(NUM)s]+)</td>"
76 r"<td>[%(NUM)s]+</td>"
77 r"<td>[%(NUM)s]+</td>"
78 r"<td>[%(NUM)s]+</td>"
79 r"<td>[%(LS)s](?P<WINNINGS>[%(NUM)s]+)</td>"
80 r"<td>[%(NUM)s]+</td>"
81 r"<td>[%(NUM)s]+</td>"
82 r"<td>[%(NUM)s]+</td>"
83 r"<td>.*</td>"
84 r"<td>(?P<TOURNEYSTART>.*)</td>"
85 r"<td>(?P<TOURNEYEND>.*)</td>"
86 r"<td>.*</td>" % substitutions, # duration
87 re.VERBOSE | re.IGNORECASE,
88 )
90 re_HTMLTourneyExtraInfo = re.compile(
91 """
92 ^([%(LS)s]|)?(?P<GUAR>[%(NUM)s]+)\s
93 ((?P<GAMEEXTRA>Holdem|PLO|PLO8|Omaha\sHi/Lo|Omaha|PL\sOmaha|PL\sOmaha\sHi/Lo|PLO\sHi/Lo)\s?)?
94 ((?P<SPECIAL>(GTD|Freeroll|FREEBUY|Freebuy))\s?)?
95 ((?P<SPEED>(Turbo|Hyper\sTurbo|Regular))\s?)?
96 ((?P<MAX>(\d+\-Max|Heads\-up|Heads\-Up))\s?)?
97 (?P<OTHER>.*?)
98 """
99 % substitutions,
100 re.VERBOSE | re.MULTILINE,
101 )
103 re_HTMLDateTime = re.compile(
104 "(?P<M>[0-9]+)\/(?P<D>[0-9]+)\/(?P<Y>[0-9]{4})[\- ]+(?P<H>[0-9]+):(?P<MIN>[0-9]+):(?P<S>[0-9]+) (?P<AMPM>(AM|PM))",
105 re.MULTILINE,
106 )
107 re_HTMLTourNo = re.compile("\s+<td>(?P<TOURNO>[0-9]+)</td>", re.DOTALL)
109 codepage = ["utf8", "cp1252"]
111 @staticmethod
112 def getSplitRe(self, head):
113 return re.compile("</tr><tr")
115 def parseSummary(self):
116 info = {}
117 m1 = self.re_HTMLPlayer.search(self.header)
118 m2 = self.re_HTMLTourneyInfo.search(self.summaryText)
119 if m1 is None or m2 is None:
120 if self.re_HTMLTourNo.search(self.summaryText):
121 tmp1 = self.header[0:200] if m1 is None else "NA"
122 tmp2 = self.summaryText[0:200] if m2 is None else "NA"
123 log.error(("WinningSummary.parseSummaryHtml: '%s' '%s") % (tmp1, tmp2))
124 raise FpdbParseError
125 else:
126 raise FpdbHandPartial
127 # print m2.groupdict()
128 info.update(m1.groupdict())
129 info.update(m2.groupdict())
130 self.parseSummaryArchive(info)
132 def parseSummaryArchive(self, info):
133 # if 'SNG' in info and "Sit & Go" in info['SNG']:
134 # self.isSng = True
136 if "TOURNAME" in info and info["TOURNAME"] is not None:
137 self.tourneyName = info["TOURNAME"]
138 m3 = self.re_HTMLTourneyExtraInfo.search(self.tourneyName)
139 if m3 is not None:
140 info.update(m3.groupdict())
142 if "GAME" in info:
143 self.gametype["category"] = self.games[info["GAME"]][1]
145 if self.gametype["category"] == "holdem":
146 self.gametype["limitType"] = "nl"
147 elif self.gametype["category"] == "omaha":
148 self.gametype["limitType"] = "pl"
149 else:
150 self.gametype["limitType"] = "fl"
152 self.buyinCurrency = "USD"
153 if "SPECIAL" in info and info["SPECIAL"] is not None:
154 if info["SPECIAL"] in ("Freeroll", "FREEBUY", "Freebuy"):
155 self.buyinCurrency = "FREE"
156 self.guaranteeAmt = int(100 * Decimal(self.clearMoneyString(info["GUAR"])))
158 if "TOURNO" in info:
159 self.tourNo = info["TOURNO"]
160 if info["BUYIN"] is not None:
161 self.buyin = int(100 * Decimal(self.clearMoneyString(info["BUYIN"])))
162 if info["FEE"] is not None:
163 self.fee = int(100 * Decimal(self.clearMoneyString(info["FEE"])))
165 if "REBUYS" in info and Decimal(self.clearMoneyString(info["REBUYS"].replace(" ", ""))) > 0:
166 self.isRebuy = True
167 self.rebuyCost = self.buyin
169 if "ADDONS" in info and Decimal(self.clearMoneyString(info["ADDONS"].replace(" ", ""))) > 0:
170 self.isAddOn = True
171 self.addOnCost = self.buyin
173 if "MAX" in info and info["MAX"] is not None:
174 n = info["MAX"].replace("-Max", "")
175 if n in ("Heads-up", "Heads-Up"):
176 self.maxseats = 2
177 else:
178 self.maxseats = int(n)
179 else:
180 self.maxseats = 10
182 if "SPEED" in info and info["SPEED"] is not None:
183 self.speed = self.speeds[info["SPEED"]]
184 self.isSng = True
186 if "On Demand" in self.tourneyName:
187 self.isOnDemand = True
189 if " KO" in self.tourneyName or "Knockout" in self.tourneyName:
190 self.isKO = True
192 if "R/A" in self.tourneyName:
193 self.isRebuy = True
194 self.isAddOn = True
195 self.addOnCost = self.buyin
196 self.rebuyCost = self.buyin
198 if "TOURNEYSTART" in info:
199 m4 = self.re_HTMLDateTime.finditer(info["TOURNEYSTART"])
200 datetimestr = None # default used if time not found
201 for a in m4:
202 datetimestr = "%s/%s/%s %s:%s:%s %s" % (
203 a.group("Y"),
204 a.group("M"),
205 a.group("D"),
206 a.group("H"),
207 a.group("MIN"),
208 a.group("S"),
209 a.group("AMPM"),
210 )
211 self.startTime = datetime.datetime.strptime(
212 datetimestr, "%Y/%m/%d %I:%M:%S %p"
213 ) # also timezone at end, e.g. " ET"
214 self.startTime = HandHistoryConverter.changeTimezone(
215 self.startTime, self.import_parameters["timezone"], "UTC"
216 )
218 if "TOURNEYEND" in info:
219 m5 = self.re_HTMLDateTime.finditer(info["TOURNEYEND"])
220 datetimestr = None # default used if time not found
221 for a in m5:
222 datetimestr = "%s/%s/%s %s:%s:%s %s" % (
223 a.group("Y"),
224 a.group("M"),
225 a.group("D"),
226 a.group("H"),
227 a.group("MIN"),
228 a.group("S"),
229 a.group("AMPM"),
230 )
231 self.endTime = datetime.datetime.strptime(
232 datetimestr, "%Y/%m/%d %I:%M:%S %p"
233 ) # also timezone at end, e.g. " ET"
234 self.endTime = HandHistoryConverter.changeTimezone(self.endTime, self.import_parameters["timezone"], "UTC")
236 self.currency = "USD"
237 winnings = 0
238 rebuyCount = None
239 addOnCount = None
240 koCount = None
241 rank = 9999 # fix with lookups
243 if "WINNINGS" in info and info["WINNINGS"] is not None:
244 winnings = int(100 * Decimal(self.clearMoneyString(info["WINNINGS"])))
246 if self.isRebuy and self.rebuyCost > 0:
247 rebuyAmt = int(100 * Decimal(self.clearMoneyString(info["REBUYS"].replace(" ", ""))))
248 rebuyCount = old_div(rebuyAmt, self.rebuyCost)
250 if self.isAddOn and self.addOnCost > 0:
251 addOnAmt = int(100 * Decimal(self.clearMoneyString(info["ADDONS"].replace(" ", ""))))
252 addOnCount = old_div(addOnAmt, self.addOnCost)
254 self.hero = info["PNAME"]
256 self.addPlayer(rank, info["PNAME"], winnings, self.currency, rebuyCount, addOnCount, koCount)