Coverage for PokerStarsSummary.py: 0%
383 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 2008-2012 Steffen Schaumburg, 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.
18"""pokerstars-specific summary parsing code"""
20# import L10n
21# _ = L10n.get_translation()
23import datetime
24import re
25from HandHistoryConverter import HandHistoryConverter, FpdbParseError, FpdbHandPartial
26import PokerStarsStructures
27from TourneySummary import TourneySummary
29import logging
31try:
32 import xlrd
33except ImportError:
34 xlrd = None
36# PPokerstatars HH Format
37log = logging.getLogger("parser")
40class PokerStarsSummary(TourneySummary):
41 hhtype = "summary"
42 limits = {
43 "No Limit": "nl",
44 "NO LIMIT": "nl",
45 "NL": "nl",
46 "Pot Limit": "pl",
47 "POT LIMIT": "pl",
48 "PL": "pl",
49 "Limit": "fl",
50 "LIMIT": "fl",
51 "Pot Limit Pre-Flop, No Limit Post-Flop": "pn",
52 "PNL": "pn",
53 }
54 games = { # base, category
55 "Hold'em": ("hold", "holdem"),
56 "Hold 'Em": ("hold", "holdem"),
57 "6+ Hold'em": ("hold", "6_holdem"),
58 "Omaha": ("hold", "omahahi"),
59 "Omaha Hi/Lo": ("hold", "omahahilo"),
60 "Omaha H/L": ("hold", "omahahilo"),
61 "5 Card Omaha": ("hold", "5_omahahi"),
62 "5 Card Omaha Hi/Lo": ("hold", "5_omaha8"),
63 "5 Card Omaha H/L": ("hold", "5_omaha8"),
64 "6 Card Omaha": ("hold", "6_omahahi"),
65 "6 Card Omaha Hi/Lo": ("hold", "6_omaha8"),
66 "Courchevel": ("hold", "cour_hi"),
67 "Courchevel Hi/Lo": ("hold", "cour_hilo"),
68 "Courchevel H/L": ("hold", "cour_hilo"),
69 "Razz": ("stud", "razz"),
70 "RAZZ": ("stud", "razz"),
71 "7 Card Stud": ("stud", "studhi"),
72 "7 Card Stud Hi/Lo": ("stud", "studhilo"),
73 "7 Card Stud H/L": ("stud", "studhilo"),
74 "Badugi": ("draw", "badugi"),
75 "Triple Draw 2-7 Lowball": ("draw", "27_3draw"),
76 "Single Draw 2-7 Lowball": ("draw", "27_1draw"),
77 "Triple Draw 2-7": ("draw", "27_3draw"),
78 "Single Draw 2-7": ("draw", "27_1draw"),
79 "5 Card Draw": ("draw", "fivedraw"),
80 "HORSE": ("mixed", "horse"),
81 "HOSE": ("mixed", "hose"),
82 "Horse": ("mixed", "horse"),
83 "Hose": ("mixed", "hose"),
84 "Triple Stud": ("mixed", "3stud"),
85 "8-Game": ("mixed", "8game"),
86 "Mixed PLH/PLO": ("mixed", "plh_plo"),
87 "Mixed NLH/PLO": ("mixed", "nlh_plo"),
88 "Mixed NLH/NLO": ("mixed", "nlh_nlo"),
89 "Mixed Omaha H/L": ("mixed", "plo_lo"),
90 "Mixed Hold'em": ("mixed", "mholdem"),
91 "PLH/PLO Mixed": ("mixed", "plh_plo"),
92 "NLH/PLO Mixed": ("mixed", "nlh_plo"),
93 "NLH/NLO Mixed": ("mixed", "nlh_nlo"),
94 "Omaha H/L Mixed": ("mixed", "plo_lo"),
95 "Hold'em Mixed": ("mixed", "mholdem"),
96 "Mixed Omaha": ("mixed", "momaha"),
97 }
99 substitutions = {
100 "LEGAL_ISO": "USD|EUR|GBP|CAD|FPP|SC|INR|CNY", # legal ISO currency codes
101 "LS": "\$|\xe2\x82\xac|\u20ac||\£|\u20b9|\¥|Rs\.\s|", # legal currency symbols - Euro(cp1252, utf-8)
102 }
104 re_Identify = re.compile(
105 "((?P<SITE>PokerStars|Full\sTilt|Run\sIt\sOnce\sPoker)\sTournament\s\#\d+|<title>TOURNEYS:)"
106 )
108 re_TourNo = re.compile("\#(?P<TOURNO>[0-9]+),")
109 re_Header = re.compile("History\sRequest\s\-\s")
110 re_emailHeader = re.compile("Delivered\-To\:\s")
112 re_TourneyInfo = re.compile(
113 """
114 \#(?P<TOURNO>[0-9]+),\s
115 (?P<DESC1>.+?\sSNG\s)?
116 ((?P<LIMIT>No\sLimit|NO\sLIMIT|Limit|LIMIT|Pot\sLimit|POT\sLIMIT|Pot\sLimit\sPre\-Flop,\sNo\sLimit\sPost\-Flop)\s)?
117 (?P<SPLIT>Split)?\s?
118 (?P<GAME>Hold\'em|6\+\sHold\'em|Hold\s\'Em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sHi/Lo|Omaha|Omaha\sHi/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|Single\sDraw\s2\-7\sLowball|5\sCard\sDraw|(5|6)\sCard\sOmaha(\sHi/Lo)?|Courchevel(\sHi/Lo)?|HORSE|8\-Game|HOSE|Mixed\sOmaha\sH/L|Mixed\sHold\'em|Mixed\sPLH/PLO|Mixed\sNLH/PLO||Mixed\sOmaha|Triple\sStud)\s+
119 (?P<DESC>[ a-zA-Z]+\s+)?
120 (Buy-In:\s(?P<CURRENCY>[%(LS)s]?)(?P<BUYIN>[,.0-9]+)(\s(?P<CURRENCY1>(FPP|SC)))?(\/[%(LS)s]?(?P<FEE>[,.0-9]+))?(\/[%(LS)s]?(?P<BOUNTY>[,.0-9]+))?(?P<CUR>\s(%(LEGAL_ISO)s))?\s+)?
121 (?P<ENTRIES>[0-9]+)\splayers\s+
122 ([%(LS)s]?(?P<ADDED>[,.\d]+)(\s(%(LEGAL_ISO)s))?\sadded\sto\sthe\sprize\spool\sby\s(PokerStars|Full\sTilt)(\.com)?\s+)?
123 (Total\sPrize\sPool:\s[%(LS)s]?(?P<PRIZEPOOL>[,.0-9]+|Sunday\sMillion\s(ticket|biļete))(\s(%(LEGAL_ISO)s))?\s+)?
124 (?P<SATELLITE>Target\sTournament\s\#(?P<TARGTOURNO>[0-9]+)\s+
125 (Buy-In:\s(?P<TARGCURRENCY>[%(LS)s]?)(?P<TARGBUYIN>[,.0-9]+)(\/[%(LS)s]?(?P<TARGFEE>[,.0-9]+))?(\/[%(LS)s]?(?P<TARGBOUNTY>[,.0-9]+))?(?P<TARGCUR>\s(%(LEGAL_ISO)s))?\s+)?)?
126 ([0-9]+\stickets?\sto\sthe\starget\stournament\s+)?
127 Tournament\sstarted\s+(-\s)?
128 (?P<DATETIME>.*$)
129 """
130 % substitutions,
131 re.VERBOSE | re.MULTILINE,
132 )
133 # re_TourneyInfo = re.compile(u"""(?P<TOURNO>[0-9]+),\s(?P<DESC1>.+?\sSNG\s)?((?P<LIMIT>No\sLimit|NO\sLIMIT|Limit|LIMIT|Pot\sLimit|POT\sLIMIT|Pot\sLimit\sPre\-Flop,\sNo\sLimit\sPost\-Flop)\s)?(?P<SPLIT>Split)?\s?(?P<GAME>Hold\'em|6\+\sHold\'em|Hold\s\'Em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sHi\/Lo|Omaha|Omaha\sHi\/Lo|Badugi|Triple\sDraw\s2\-7\sLowball|Single\sDraw\s2\-7\sLowball|5\sCard\sDraw|(5|6)\sCard\sOmaha(\sHi\/Lo)?|Courchevel(\sHi\/Lo)?|HORSE|8\-Game|HOSE|Mixed\sOmaha\sH\/L|Mixed\sHold\'em|Mixed\sPLH\/PLO|Mixed\sNLH\/PLO||Mixed\sOmaha|Triple\sStud)\s+Buy-In:\s(?P<CURRENCY>\[%(LS)s\]?)((?P<BUYIN>[,.0-9]+)/\[%(LS)s\]?(?P<FEE>[,.0-9]+)|(?P<BUYIN2>[,.0-9]+))\s+""" % substitutions ,re.VERBOSE|re.MULTILINE)
134 # re_TourneyInfo2 = re.compile(u"""(?P<ENTRIES>[0-9]+)\splayers\s+""" % substitutions ,re.VERBOSE|re.MULTILINE)
135 # re_TourneyInfo3 = re.compile(u"""Total\sPrize\sPool:\s\[%(LS)s\]?(?P<PRIZEPOOL>[,.0-9]+)\s+""" % substitutions ,re.VERBOSE|re.MULTILINE)
136 # re_TourneyInfo4 = re.compile(u"""Tournament\sstarted\s+(-\s)?(?P<DATETIME>.*$)""" % substitutions ,re.VERBOSE|re.MULTILINE)
137 # You made 5 rebuys and 1 addons for a total of USD 3,180.00.
138 re_rebuyAddOn = re.compile(
139 """
140 You\smade\s(?P<REBUYCOUNT>\d+)\srebuys\sand\s(?P<ADDONCOUNT>\d+)\saddons\sfor\sa\stotal\sof\s(%(LEGAL_ISO)s)\s(?P<REBUYADDON>[,.0-9]+)
141 """
142 % substitutions,
143 re.VERBOSE | re.MULTILINE,
144 )
145 # You collected 5 bounties for a total of USD 875.00.
146 re_KOBounties = re.compile(
147 """
148 You\scollected\s(?P<KOCOUNT>\d+)\sbounties\sfor\sa\stotal\sof\s(%(LEGAL_ISO)s)\s(?P<KOBOUNTY>[,.0-9]+)
149 """
150 % substitutions,
151 re.VERBOSE | re.MULTILINE,
152 )
154 re_HTMLTourneyInfo = re.compile(
155 r'<td align="right">(?P<DATETIME>.*)</td>'
156 r'<td align="center">(?P<TOURNO>[0-9]+)</td>'
157 r"(<td>(?P<TOURNAME>.*)</td>)?"
158 r'<td align="right">'
159 r"(?P<LIMIT>[ a-zA-Z\-]+)\s"
160 r"(?P<SPLIT>Split)?\s?"
161 r"(?P<GAME>Hold\'em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sH/L|Omaha|Omaha\sH/L|Badugi|Triple\sDraw\s2\-7(\sLowball)?|Single\sDraw\s2\-7(\sLowball)?|5\sCard\sDraw|(5|6)\sCard\sOmaha(\sH/L)?|Courchevel(\sH/L)?|HORSE|Horse|8\-Game|HOSE|Hose|Omaha\sH/L\sMixed|Hold\'em\sMixed|PLH/PLO\sMixed|NLH/PLO\sMixed|Triple\sStud|NLH/NLO\sMixed|Mixed\sNLH/NLO|Mixed\sOmaha\sH/L|Mixed\sHold\'em|Mixed\sPLH/PLO|Mixed\sNLH/PLO)</td>"
162 r"<td.*?>(?P<CURRENCY>(%(LEGAL_ISO)s)?)( )?</td>"
163 r"<td.*?>(?P<BUYIN>([,.0-9 ]+|Freeroll))(?P<FPPBUYIN>(\s| )(FPP|SC|StarsCoin))?</td>"
164 r"<td.*?>(?P<REBUYADDON>[,.0-9 ]+)</td>"
165 r"<td.*?>(?P<FEE>[,.0-9 ]+)</td>"
166 r'<td align="?right"?>(?P<RANK>[,.0-9]+)</td>'
167 r'<td align="right">(?P<ENTRIES>[,.0-9]+)</td>'
168 r"(<td.*?>[,.0-9]+</td>)?"
169 r"<td.*?>(?P<WINNINGS>[,.0-9]+)(?P<FPPWINNINGS>\s\+\s[,.0-9]+(\s| )(FPP|SC|StarsCoin))?</td>"
170 r"<td.*?>(?P<KOS>[,.0-9]+)</td>"
171 r"<td.*?>((?P<TARGET>[,.0-9]+)|( ))</td>"
172 r"<td.*?>((?P<WONTICKET>\*\\\/\*)|( ))</td>" % substitutions,
173 re.IGNORECASE,
174 )
176 re_XLSTourneyInfo = {}
177 re_XLSTourneyInfo["Date/Time"] = re.compile(r"(?P<DATETIME>.*)")
178 re_XLSTourneyInfo["Tourney"] = re.compile(r"(?P<TOURNO>[0-9]+)")
179 re_XLSTourneyInfo["Name"] = re.compile(r"(?P<TOURNAME>.*)")
180 re_XLSTourneyInfo["Game"] = re.compile(
181 r"(?P<LIMIT>[ a-zA-Z\-]+)\s"
182 r"(?P<SPLIT>Split)?\s?"
183 r"(?P<GAME>Hold\'em|Razz|RAZZ|7\sCard\sStud|7\sCard\sStud\sH/L|Omaha|Omaha\sH/L|Badugi|Triple\sDraw\s2\-7(\sLowball)?|Single\sDraw\s2\-7(\sLowball)?|5\sCard\sDraw|(5|6)\sCard\sOmaha(\sH/L)?|Courchevel(\sH/L)?|HORSE|Horse|8\-Game|HOSE|Hose|Omaha\sH/L\sMixed|Hold\'em\sMixed|PLH/PLO\sMixed|NLH/PLO\sMixed|Triple\sStud|NLH/NLO\sMixed|Mixed\sNLH/NLO|Mixed\sOmaha\sH/L|Mixed\sHold\'em|Mixed\sPLH/PLO|Mixed\sNLH/PLO)"
184 )
185 re_XLSTourneyInfo["Currency"] = re.compile(r"(?P<CURRENCY>(%(LEGAL_ISO)s)?)" % substitutions)
186 re_XLSTourneyInfo["Buy-In"] = re.compile(r"(?P<BUYIN>([,.0-9]+|Freeroll))(?P<FPPBUYIN>\s(FPP|SC|StarsCoin))?")
187 re_XLSTourneyInfo["ReBuys"] = re.compile(r"(?P<REBUYADDON>[,.0-9]+)")
188 re_XLSTourneyInfo["Rake"] = re.compile(r"(?P<FEE>[,.0-9]+)")
189 re_XLSTourneyInfo["Place"] = re.compile(r"(?P<RANK>[,.0-9]+)")
190 re_XLSTourneyInfo["Entries"] = re.compile(r"(?P<ENTRIES>[,.0-9]+)")
191 re_XLSTourneyInfo["Prize"] = re.compile(
192 r"(?P<WINNINGS>[,.0-9]+)(?P<FPPWINNINGS>\s\+\s[,.0-9]+\s(FPP|SC|StarsCoin))?"
193 )
194 re_XLSTourneyInfo["Bounty Awarded"] = re.compile(r"(?P<KOS>[,.0-9]+)")
195 re_XLSTourneyInfo["Target ID"] = re.compile(r"(?P<TARGET>[0-9]+)?")
196 re_XLSTourneyInfo["Qualified"] = re.compile(r"(?P<WONTICKET>\*\\\/\*)?")
198 re_PlayerStars = re.compile(
199 """(?P<RANK>[,.0-9]+):\s(?P<NAME>.+?)(\s\[(?P<ENTRYID>\d+)\])?\s\(.+?\),(\s)?((?P<CUR>\[%(LS)s]?)(?P<WINNINGS>[,.0-9]+)(\s(?P<CUR1>(FPP|SC)))?)?(?P<STILLPLAYING>still\splaying)?((?P<TICKET>Tournament\sTicket)\s\(WSOP\sStep\s(?P<LEVEL>\d)\))?(?P<QUALIFIED>\s\(qualified\sfor\sthe\starget\stournament\)|Sunday\sMillion\s(ticket|biļete))?(\s+)?"""
200 % substitutions
201 )
202 re_PlayerRIO = re.compile(
203 """(?P<RANK>[,.0-9]+):\s(?P<NAME>[^,]+?)(,\s(?P<CUR>\[%(LS)s])(?P<WINNINGS>[,.0-9]+))?(\s+)?$"""
204 % substitutions,
205 re.MULTILINE,
206 )
207 re_HTMLPlayer1 = re.compile(
208 r"<h2>All\s+(?P<SNG>(Regular|Sit & Go))\s?Tournaments\splayed\sby\s'(<b>)?(?P<NAME>.+?)':?</h2>", re.IGNORECASE
209 )
210 re_HTMLPlayer2 = re.compile(r"<title>TOURNEYS:\s<(?P<NAME>.+?)></title>", re.IGNORECASE)
211 re_XLSPlayer = re.compile(
212 r"All\s(?P<SNG>(Regular|(Heads\sup\s)?Sit\s&\sGo))\sTournaments\splayed\sby\s\'(?P<NAME>.+?)\'"
213 )
215 re_DateTime = re.compile(
216 """(?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]+)""",
217 re.MULTILINE,
218 )
219 re_HTMLDateTime = re.compile(
220 """(?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))""",
221 re.MULTILINE,
222 )
223 re_HTMLTourneyExtraInfo = re.compile(
224 "\[(Deep\s)?((?P<MAX>\d+)-Max,\s?)?((\dx\-)?(?P<SPEED>Turbo|Hyper\-Turbo))?(, )?(?P<REBUYADDON1>\dR\dA)?"
225 )
226 re_XLSDateTime = re.compile("^[.0-9]+$")
227 re_Rank = re.compile("^You\sfinished\sin\s(?P<RANK>[0-9]+)(st|nd|rd|th)\splace\.", re.MULTILINE)
228 # re_WinningRankOne = re.compile(u"^%(PLYR)s wins the tournament and receives %(CUR)s(?P<AMT>[\.0-9]+) - congratulations!$" % substitutions, re.MULTILINE)
229 # re_WinningRankOther = re.compile(u"^%(PLYR)s finished the tournament in (?P<RANK>[0-9]+)(st|nd|rd|th) place and received %(CUR)s(?P<AMT>[.0-9]+)\.$" % substitutions, re.MULTILINE)
230 # re_RankOther = re.compile(u"^%(PLYR)s finished the tournament in (?P<RANK>[0-9]+)(st|nd|rd|th) place$" % substitutions, re.MULTILINE)
232 codepage = ["utf8", "cp1252"]
234 @staticmethod
235 def getSplitRe(self, head):
236 re_SplitTourneys = re.compile("(?:PokerStars|Full\sTilt|Run\sIt\sOnce\sPoker) Tournament ")
237 re_HTMLSplitTourneys = re.compile('tr id="row_\d+')
238 m = re.search("<title>TOURNEYS:", head)
239 if m is not None:
240 self.hhtype = "html"
241 return re_HTMLSplitTourneys
242 self.hhtype = "summary"
243 return re_SplitTourneys
245 def parseSummary(self):
246 if self.hhtype == "summary":
247 self.parseSummaryFile()
248 elif self.hhtype == "html":
249 self.parseSummaryHtml()
250 elif self.hhtype == "xls":
251 self.parseSummaryXLS()
252 elif self.hhtype == "hh":
253 self.parseSummaryFromHH()
254 else:
255 raise FpdbParseError(("parseSummary FAIL"))
257 def parseSummaryFromHH(self):
258 raise FpdbParseError(("PokerStarsSummary.parseSummaryHtml: This file format is not yet supported"))
259 # self.entries = Unavailable from HH
260 # self.prizepool = Unavailable from HH
261 # self.startTime = Unreliable from HH (late reg)
262 # obj = getattr(PokerStarsToFpdb, "PokerStars", None)
263 # hhc = obj(self.config, in_path = self.in_path, sitename = None, autostart = False)
265 # self.buyin = int(100*hhc.SnG_Structures[tourneyNameFull]['buyIn'])
266 # self.fee = int(100*hhc.SnG_Structures[tourneyNameFull]['fee'])
268 # self.tourNo =
269 # self.buyin =
270 # self.fee =
271 # self.buyinCurrency =
272 # self.currency =
273 # self.maxseats =
274 # self.isSng =
275 # self.addPlayer(rank, name, winnings, self.currency, rebuyCount, addOnCount, koCount)
277 def parseSummaryXLS(self):
278 info = self.summaryText[0]
279 m = self.re_XLSPlayer.search(info["header"])
280 if m is None:
281 tmp1 = info["header"]
282 tmp2 = str(info)[0:200]
283 log.error(("PokerStarsSummary.parseSummaryXLS: '%s' '%s") % (tmp1, tmp2))
284 raise FpdbParseError
285 info.update(m.groupdict())
286 mg = {}
287 for k, j in info.iteritems():
288 if self.re_XLSTourneyInfo.get(k) is not None:
289 m1 = self.re_XLSTourneyInfo[k].search(j)
290 if m1:
291 mg.update(m1.groupdict())
292 elif k == "Game":
293 log.error(("PokerStarsSummary.parseSummaryXLS Game '%s' not found") % j)
294 raise FpdbParseError
295 info.update(mg)
296 self.parseSummaryArchive(info)
298 def parseSummaryHtml(self):
299 info = {}
300 m1 = self.re_HTMLPlayer1.search(self.header)
301 if m1 is None:
302 m1 = self.re_HTMLPlayer2.search(self.header)
303 m2 = self.re_HTMLTourneyInfo.search(self.summaryText)
304 if m1 is None or m2 is None:
305 if self.re_HTMLPlayer1.search(self.summaryText) or self.re_HTMLPlayer2.search(self.summaryText):
306 raise FpdbHandPartial
307 tmp1 = self.header[0:200] if m1 is None else "NA"
308 tmp2 = self.summaryText if m2 is None else "NA"
309 log.error(("PokerStarsSummary.parseSummaryHtml: '%s' '%s") % (tmp1, tmp2))
310 raise FpdbParseError
311 info.update(m1.groupdict())
312 info.update(m2.groupdict())
313 self.parseSummaryArchive(info)
315 def parseSummaryArchive(self, info):
316 if "SNG" in info and "Sit & Go" in info["SNG"]:
317 self.isSng = True
319 if "TOURNAME" in info and info["TOURNAME"] is not None:
320 self.tourneyName = re.sub("</?(b|font).*?>", "", info["TOURNAME"])
321 m3 = self.re_HTMLTourneyExtraInfo.search(self.tourneyName)
322 if m3 is not None:
323 info.update(m3.groupdict())
325 if "TOURNO" in info:
326 self.tourNo = info["TOURNO"]
327 if "LIMIT" in info and info["LIMIT"] is not None:
328 self.gametype["limitType"] = self.limits[info["LIMIT"]]
329 if "GAME" in info:
330 self.gametype["category"] = self.games[info["GAME"]][1]
331 if "SPLIT" in info and info["SPLIT"] == "Split":
332 self.isSplit = True
333 if info["BUYIN"] is not None:
334 if info["BUYIN"] == "Freeroll":
335 self.buyin = 0
336 else:
337 self.buyin = int(100 * float(self.clearMoneyString(info["BUYIN"].replace(" ", ""))))
338 if info["FEE"] is not None:
339 self.fee = int(100 * float(self.clearMoneyString(info["FEE"].replace(" ", ""))))
340 if "REBUYADDON" in info and float(self.clearMoneyString(info["REBUYADDON"].replace(" ", ""))) > 0:
341 self.isRebuy = True
342 self.isAddOn = True
343 rebuyAddOnAmt = int(100 * float(self.clearMoneyString(info["REBUYADDON"].replace(" ", ""))))
344 if self.buyin != 0:
345 rebuys = int(rebuyAddOnAmt / self.buyin)
346 if rebuys != 0:
347 self.fee = self.fee / (rebuys + 1)
348 self.rebuyCost = self.buyin + self.fee
349 self.addOnCost = self.buyin + self.fee
350 if "REBUYADDON1" in info and info["REBUYADDON1"] is not None:
351 self.isRebuy = True
352 self.isAddOn = True
353 self.rebuyCost = self.buyin + self.fee
354 self.addOnCost = self.buyin + self.fee
355 if "ENTRIES" in info:
356 self.entries = int(self.clearMoneyString(info["ENTRIES"]))
357 if "MAX" in info and info["MAX"] is not None:
358 self.maxseats = int(info["MAX"])
359 if not self.isSng and "SPEED" in info and info["SPEED"] is not None:
360 if info["SPEED"] == "Turbo":
361 self.speed = "Turbo"
362 elif info["SPEED"] == "Hyper-Turbo":
363 self.speed = "Hyper"
364 if "TARGET" in info and info["TARGET"] is not None:
365 self.isSatellite = True
366 if "WONTICKET" in info and info["WONTICKET"] is not None:
367 self.comment = info["TARGET"]
369 if "DATETIME" in info:
370 m4 = self.re_HTMLDateTime.finditer(info["DATETIME"])
371 datetimestr = None # default used if time not found
372 for a in m4:
373 datetimestr = "%s/%s/%s %s:%s:%s %s" % (
374 a.group("Y"),
375 a.group("M"),
376 a.group("D"),
377 a.group("H"),
378 a.group("MIN"),
379 a.group("S"),
380 a.group("AMPM"),
381 )
382 self.endTime = datetime.datetime.strptime(
383 datetimestr, "%Y/%m/%d %I:%M:%S %p"
384 ) # also timezone at end, e.g. " ET"
385 self.endTime = HandHistoryConverter.changeTimezone(self.endTime, "ET", "UTC")
386 if datetimestr is None:
387 if xlrd and self.re_XLSDateTime.match(info["DATETIME"]):
388 datetup = xlrd.xldate_as_tuple(float(info["DATETIME"]), 0)
389 datetimestr = "%d/%d/%d %d:%d:%d" % (
390 datetup[0],
391 datetup[1],
392 datetup[2],
393 datetup[3],
394 datetup[4],
395 datetup[5],
396 )
397 else:
398 datetimestr = "2000/01/01 12:00:00"
399 self.endTime = datetime.datetime.strptime(
400 datetimestr, "%Y/%m/%d %H:%M:%S"
401 ) # also timezone at end, e.g. " ET"
402 self.endTime = HandHistoryConverter.changeTimezone(self.endTime, "ET", "UTC")
404 if "CURRENCY" in info and info["CURRENCY"] is not None:
405 self.currency = info["CURRENCY"]
406 if info["BUYIN"] == "Freeroll":
407 self.buyinCurrency = "FREE"
408 self.currency = "USD"
409 elif info["FPPBUYIN"] is not None:
410 self.buyinCurrency = "PSFP"
411 elif self.currency is not None:
412 self.buyinCurrency = self.currency
413 else:
414 self.buyinCurrency = "play"
415 self.currency = "play"
417 if self.buyinCurrency not in ("FREE", "PSFP"):
418 self.prizepool = int(float(self.entries)) * self.buyin
420 if self.isSng:
421 self.lookupStructures(self.endTime)
423 if info.get("NAME") is not None and info.get("RANK") is not None:
424 name = info["NAME"]
425 rank = int(self.clearMoneyString(info["RANK"]))
426 winnings = 0
427 rebuyCount = None
428 addOnCount = None
429 koCount = None
430 entryId = 1
432 if "WINNINGS" in info and info["WINNINGS"] is not None:
433 winnings = int(100 * float(self.clearMoneyString(info["WINNINGS"])))
435 if "REBUYADDON" in info and float(self.clearMoneyString(info["REBUYADDON"].replace(" ", ""))) > 0:
436 rebuyAddOnAmt = int(100 * float(self.clearMoneyString(info["REBUYADDON"].replace(" ", ""))))
437 rebuyCount = rebuyAddOnAmt / self.buyin
439 # KOs should be exclusively handled in the PokerStars hand history files
440 if "KOS" in info and info["KOS"] is not None and info["KOS"] != "0.00":
441 self.isKO = True
443 re_HTMLEntries = re.compile(
444 r'<td align="center">%s</td>.+?<td align="?right"?>(?P<RANK>[,.0-9]+)</td>' % self.tourNo, re.IGNORECASE
445 )
446 m = re_HTMLEntries.finditer(self.header)
447 entries = []
448 for a in m:
449 entries.append(int(self.clearMoneyString(a.group("RANK"))))
450 entries.sort(reverse=True)
452 if len(entries) > 1:
453 entryId = entries.index(rank) + 1
454 self.isReEntry = True
456 self.addPlayer(rank, name, winnings, self.currency, rebuyCount, addOnCount, koCount, entryId)
458 def parseSummaryFile(self):
459 m = self.re_TourneyInfo.search(self.summaryText)
460 if m is None:
461 if self.re_Header.match(self.summaryText):
462 raise FpdbHandPartial
463 if self.re_emailHeader.match(self.summaryText):
464 raise FpdbHandPartial
465 # tmp = self.summaryText[0:200]
466 log.error(("PokerStarsSummary.parseSummaryFile: '%s'") % self.summaryText)
467 raise FpdbParseError
468 # m4 = self.re_TourneyInfo4.search(self.summaryText)
469 # print "DEBUG: m.groupdict(): %s" % m.groupdict()
470 mg = m.groupdict()
471 # mg4 = m4.groupdict()
472 if "DATETIME" in mg:
473 m1 = self.re_DateTime.finditer(mg["DATETIME"])
474 datetimestr = "2000/01/01 00:00:00" # default used if time not found
475 for a in m1:
476 datetimestr = "%s/%s/%s %s:%s:%s" % (
477 a.group("Y"),
478 a.group("M"),
479 a.group("D"),
480 a.group("H"),
481 a.group("MIN"),
482 a.group("S"),
483 )
485 self.startTime = datetime.datetime.strptime(
486 datetimestr, "%Y/%m/%d %H:%M:%S"
487 ) # also timezone at end, e.g. " ET"
488 self.startTime = HandHistoryConverter.changeTimezone(self.startTime, "ET", "UTC")
490 if mg["DESC1"] is not None:
491 self.siteName = "Run It Once Poker"
492 self.siteId = 26
493 re_Player = self.re_PlayerRIO
494 else:
495 re_Player = self.re_PlayerStars
497 if "TOURNO" in mg:
498 self.tourNo = mg["TOURNO"]
499 if "LIMIT" in mg and mg["LIMIT"] is not None:
500 self.gametype["limitType"] = self.limits[mg["LIMIT"]]
501 else:
502 self.gametype["limitType"] = "fl"
503 if "GAME" in mg:
504 self.gametype["category"] = self.games[mg["GAME"]][1]
505 if "SPLIT" in mg and mg["SPLIT"] == "Split":
506 self.isSplit = True
507 if mg["BOUNTY"] is not None and mg["FEE"] is not None:
508 self.koBounty = int(100 * float(self.clearMoneyString(mg["FEE"])))
509 self.isKO = True
510 mg["FEE"] = mg["BOUNTY"]
511 if mg["BUYIN"] is not None:
512 self.buyin = int(100 * float(self.clearMoneyString(mg["BUYIN"]))) + self.koBounty
513 if mg["FEE"] is not None:
514 self.fee = int(100 * float(self.clearMoneyString(mg["FEE"])))
516 m2 = self.re_rebuyAddOn.search(self.summaryText)
517 if m2 and m2.group("REBUYCOUNT") is not None:
518 self.isRebuy = True
519 self.isAddOn = True
520 # You made 5 rebuys and 1 addons for a total of USD 3,180.00.
521 rebuyCountHero = int(m2.group("REBUYCOUNT")) + int(
522 m2.group("ADDONCOUNT")
523 ) # combine b/c html summary does not split out
524 self.rebuyCost = self.buyin + self.fee
525 self.addOnCost = self.buyin + self.fee
526 else:
527 rebuyCountHero = None
529 if "PRIZEPOOL" in mg and mg["PRIZEPOOL"] is not None:
530 if "Sunday Million" in mg["PRIZEPOOL"]:
531 self.isSatellite = True
532 newBuyinDate = HandHistoryConverter.changeTimezone(
533 datetime.datetime.strptime("2019/01/27 00:00:00", "%Y/%m/%d %H:%M:%S"), "ET", "UTC"
534 )
535 if self.startTime > newBuyinDate:
536 targetBuyin, targetCurrency = 10900, "USD"
537 else:
538 targetBuyin, targetCurrency = 21500, "USD"
539 else:
540 self.prizepool = int(float(self.clearMoneyString(mg["PRIZEPOOL"])))
541 if "ENTRIES" in mg:
542 self.entries = int(mg["ENTRIES"])
543 if "SATELLITE" in mg and mg["SATELLITE"] is not None:
544 self.isSatellite = True
545 targetBuyin, targetCurrency = 0, "USD"
546 if mg["TARGBUYIN"] is not None:
547 targetBuyin += int(100 * float(self.clearMoneyString(mg["TARGBUYIN"])))
548 if mg["TARGFEE"] is not None:
549 targetBuyin += int(100 * float(self.clearMoneyString(mg["TARGFEE"])))
550 if mg["TARGBOUNTY"] is not None:
551 targetBuyin += int(100 * float(self.clearMoneyString(mg["TARGBOUNTY"])))
552 if mg["TARGCUR"] is not None:
553 if mg["CUR"] == "$":
554 targetCurrency = "USD"
555 elif mg["CUR"] == "€":
556 targetCurrency = "EUR"
557 elif mg["CUR"] == "£":
558 targetCurrency = "GBP"
559 elif mg["CUR"] == "₹":
560 targetCurrency = "INR"
561 elif mg["CUR"] == "Rs. ":
562 targetCurrency = "INR"
563 elif mg["CUR"] == "¥":
564 targetCurrency = "CNY"
565 elif mg["CUR"] == "FPP":
566 targetCurrency = "PSFP"
567 elif mg["CUR"] == "SC":
568 targetCurrency = "PSFP"
570 if mg["CURRENCY"] == "$":
571 self.buyinCurrency = "USD"
572 elif mg["CURRENCY"] == "€":
573 self.buyinCurrency = "EUR"
574 elif mg["CURRENCY"] == "£":
575 self.buyinCurrency = "GBP"
576 elif mg["CURRENCY"] == "₹":
577 self.buyinCurrency = "INR"
578 elif mg["CURRENCY"] == "Rs. ":
579 self.buyinCurrency = "INR"
580 elif mg["CURRENCY"] == "¥":
581 self.buyinCurrency = "CNY"
582 elif mg["CURRENCY1"] == "FPP":
583 self.buyinCurrency = "PSFP"
584 elif mg["CURRENCY1"] == "SC":
585 self.buyinCurrency = "PSFP"
586 elif not mg["CURRENCY"]:
587 self.buyinCurrency = "play"
588 if self.buyin == 0:
589 self.buyinCurrency = "FREE"
590 self.currency = self.buyinCurrency
592 if "Zoom" in self.in_path or "Rush" in self.in_path:
593 self.isFast = True
595 self.lookupStructures(self.startTime)
597 m3 = self.re_Rank.search(self.summaryText)
598 if m3:
599 heroRank = int(m3.group("RANK"))
600 else:
601 heroRank = 0
603 m = re_Player.finditer(self.summaryText)
604 for a in m:
605 mg = a.groupdict()
606 # print "DEBUG: a.groupdict(): %s" % mg
607 name = mg["NAME"]
608 rank = int(mg["RANK"])
609 winnings = 0
610 rebuyCount = None
611 addOnCount = None
612 koCount = None
613 entryId = 1
615 if "WINNINGS" in mg and mg["WINNINGS"] is not None:
616 winnings = int(100 * float(self.clearMoneyString(mg["WINNINGS"])))
618 if "CUR" in mg and mg["CUR"] is not None:
619 if mg["CUR"] == "$":
620 self.currency = "USD"
621 elif mg["CUR"] == "€":
622 self.currency = "EUR"
623 elif mg["CUR"] == "£":
624 self.currency = "GBP"
625 elif mg["CUR"] == "₹":
626 self.currency = "INR"
627 elif mg["CUR"] == "Rs. ":
628 self.currency = "INR"
629 elif mg["CUR"] == "¥":
630 self.currency = "CNY"
631 elif mg["CUR1"] == "FPP":
632 self.currency = "PSFP"
633 elif mg["CUR1"] == "SC":
634 self.currency = "PSFP"
636 if "STILLPLAYING" in mg and mg["STILLPLAYING"] is not None:
637 # print "stillplaying"
638 rank = None
639 winnings = None
641 if "TICKET" in mg and mg["TICKET"] is not None:
642 # print "Tournament Ticket Level %s" % mg['LEVEL']
643 step_values = {
644 "1": "750", # Step 1 - $7.50 USD
645 "2": "2750", # Step 2 - $27.00 USD
646 "3": "8200", # Step 3 - $82.00 USD
647 "4": "21500", # Step 4 - $215.00 USD
648 "5": "70000", # Step 5 - $700.00 USD
649 "6": "210000", # Step 6 - $2100.00 USD
650 }
651 winnings = int(step_values[mg["LEVEL"]])
653 if "QUALIFIED" in mg and mg["QUALIFIED"] is not None and self.isSatellite:
654 winnings = targetBuyin
655 self.currency = targetCurrency
657 if "ENTRYID" in mg and mg["ENTRYID"] is not None:
658 entryId = int(mg["ENTRYID"])
659 self.isReEntry = True
661 if heroRank == rank and entryId == 1:
662 rebuyCount = rebuyCountHero
663 addOnCount = None
664 koCount = None
666 # print "DEBUG: addPlayer(%s, %s, %s, %s, None, None, None)" %(rank, name, winnings, self.currency)
667 # print "DEBUG: self.buyin: %s self.fee %s" %(self.buyin, self.fee)
668 self.addPlayer(rank, name, winnings, self.currency, rebuyCount, addOnCount, koCount, entryId)
670 # print self
672 def lookupStructures(self, date):
673 Structures = PokerStarsStructures.PokerStarsStructures()
674 if self.entries % 9 == 0 and self.entries < 45:
675 entries = 9
676 elif self.entries % 6 == 0 and self.entries < 30:
677 entries = 6
678 elif self.entries > 6 and self.entries < 9:
679 entries = 9
680 else:
681 entries = self.entries
683 speed = Structures.lookupSnG((self.buyin, self.fee, entries), date)
684 if speed is not None:
685 self.speed = speed
686 if entries == 10:
687 self.isDoubleOrNothing = True
690# end class PokerStarsSummary