Coverage for iPokerSummary.py: 0%
183 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-28 16:41 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-09-28 16:41 +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.
18#import L10n
19#_ = L10n.get_translation()
21from decimal_wrapper import Decimal
22import datetime
24from Exceptions import FpdbParseError
25from HandHistoryConverter import *
26from TourneySummary import *
29class iPokerSummary(TourneySummary):
30 substitutions = {
31 'LS' : u"\$|\xe2\x82\xac|\xe2\u201a\xac|\u20ac|\xc2\xa3|\£|RSD|kr|",
32 'PLYR': r'(?P<PNAME>[^"]+)',
33 'NUM' : r'.,0-9',
34 'NUM2': r'\b((?:\d{1,3}(?:\s\d{3})*)|(?:\d+))\b', # Regex pattern for matching numbers with spaces
35 }
36 currencies = { u'€':'EUR', '$':'USD', '':'T$', u'£':'GBP', 'RSD': 'RSD', 'kr': 'SEK'}
38 months = { 'Jan':1, 'Feb':2, 'Mar':3, 'Apr':4, 'May':5, 'Jun':6, 'Jul':7, 'Aug':8, 'Sep':9, 'Oct':10, 'Nov':11, 'Dec':12}
40 limits = { 'No limit':'nl',
41 'Pot limit':'pl',
42 'Limit':'fl',
43 'NL':'nl',
44 'SL':'nl',
45 u'БЛ':'nl',
46 'PL':'pl',
47 'LP':'pl',
48 'L':'fl',
49 'LZ':'fl',
50 }
51 games = { # base, category
52 '7 Card Stud' : ('stud','studhi'),
53 '7 Card Stud Hi-Lo' : ('stud','studhilo'),
54 '7 Card Stud HiLow': ('stud', 'studhilo'),
55 '5 Card Stud' : ('stud','5_studhi'),
56 'Holdem' : ('hold','holdem'),
57 'Six Plus Holdem' : ('hold','6_holdem'),
58 'Omaha' : ('hold','omahahi'),
59 'Omaha Hi-Lo' : ('hold','omahahilo'),
60 }
62 re_Identify = re.compile(u'<game\sgamecode=')
63 re_client = re.compile(r'<client_version>(?P<CLIENT>.*?)</client_version>')
64 re_GameType = re.compile(r"""
65 <gametype>(?P<GAME>((?P<CATEGORY>(5|7)\sCard\sStud(\sHi\-Lo)?(\sHiLow)?|(Six\sPlus\s)?Holdem|Omaha(\sHi\-Lo)?(\sHiLow)?)?\s?(?P<LIMIT>NL|SL|L|LZ|PL|БЛ|LP|No\slimit|Pot\slimit|Limit))|LH\s(?P<LSB>[%(NUM)s]+)(%(LS)s)?/(?P<LBB>[%(NUM)s]+)(%(LS)s)?.+?)
66 (\s(%(LS)s)?(?P<SB>[%(NUM)s]+)(%(LS)s)?/(%(LS)s)?(?P<BB>[%(NUM)s]+))?(%(LS)s)?(\sAnte\s(%(LS)s)?(?P<ANTE>[%(NUM)s]+)(%(LS)s)?)?</gametype>\s+?
67 <tablename>(?P<TABLE>.+)?</tablename>\s+?
68 (<(tablecurrency|tournamentcurrency)>.*</(tablecurrency|tournamentcurrency)>\s+?)?
69 (<smallblind>.+</smallblind>\s+?)?
70 (<bigblind>.+</bigblind>\s+?)?
71 <duration>.+</duration>\s+?
72 <gamecount>.+</gamecount>\s+?
73 <startdate>(?P<DATETIME>.+)</startdate>\s+?
74 <currency>(?P<CURRENCY>.+)</currency>\s+?
75 <nickname>(?P<HERO>.+)</nickname>
76 """ % substitutions, re.MULTILINE|re.VERBOSE)
78 re_GameInfoTrny = re.compile(r"""
79 (?:(<tour(?:nament)?code>(?P<TOURNO>\d+)</tour(?:nament)?code>))|
80 (?:(<tournamentname>(?P<NAME>[^<]*)</tournamentname>))|
81 (?:(<rewarddrawn>(?P<REWARD>[%(NUM2)s%(LS)s]+)</rewarddrawn>))|
82 (?:(<place>(?P<PLACE>.+?)</place>))|
83 (?:(<buyin>(?P<BIAMT>[%(NUM2)s%(LS)s]+)\s\+\s)?(?P<BIRAKE>[%(NUM2)s%(LS)s]+)\s\+\s(?P<BIRAKE2>[%(NUM2)s%(LS)s]+)</buyin>)|
84 (?:(<totalbuyin>(?P<TOTBUYIN>.*)</totalbuyin>))|
85 (?:(<win>(%(LS)s)?(?P<WIN>[%(NUM2)s%(LS)s]+)</win>))
86 """ % substitutions, re.VERBOSE)
87 re_GameInfoTrny2 = re.compile(r"""
88 (?:(<tour(?:nament)?code>(?P<TOURNO>\d+)</tour(?:nament)?code>))|
89 (?:(<tournamentname>(?P<NAME>[^<]*)</tournamentname>))|
90 (?:(<place>(?P<PLACE>.+?)</place>))|
91 (?:(<buyin>(?P<BIAMT>[%(NUM2)s%(LS)s]+)\s\+\s)?(?P<BIRAKE>[%(NUM2)s%(LS)s]+)</buyin>)|
92 (?:(<totalbuyin>(?P<TOTBUYIN>[%(NUM2)s%(LS)s]+)</totalbuyin>))|
93 (?:(<win>(%(LS)s)?(?P<WIN>.+?|[%(NUM2)s%(LS)s]+)</win>))
94 """ % substitutions, re.VERBOSE)
95 re_Buyin = re.compile(r"""(?P<BUYIN>[%(NUM)s]+)""" % substitutions, re.MULTILINE|re.VERBOSE)
96 re_TourNo = re.compile(r'(?P<TOURNO>\d+)$', re.MULTILINE)
97 re_TotalBuyin = re.compile(r"""(?P<BUYIN>(?P<BIAMT>[%(LS)s%(NUM)s]+)\s\+\s?(?P<BIRAKE>[%(LS)s%(NUM)s]+)?)""" % substitutions, re.MULTILINE|re.VERBOSE)
98 re_DateTime1 = re.compile("""(?P<D>[0-9]{2})\-(?P<M>[a-zA-Z]{3})\-(?P<Y>[0-9]{4})\s+(?P<H>[0-9]+):(?P<MIN>[0-9]+)(:(?P<S>[0-9]+))?""", re.MULTILINE)
99 re_DateTime2 = re.compile("""(?P<D>[0-9]{2})[\/\.](?P<M>[0-9]{2})[\/\.](?P<Y>[0-9]{4})\s+(?P<H>[0-9]+):(?P<MIN>[0-9]+)(:(?P<S>[0-9]+))?""", re.MULTILINE)
100 re_DateTime3 = re.compile("""(?P<Y>[0-9]{4})\/(?P<M>[0-9]{2})\/(?P<D>[0-9]{2})\s+(?P<H>[0-9]+):(?P<MIN>[0-9]+)(:(?P<S>[0-9]+))?""", re.MULTILINE)
101 re_Place = re.compile(r"""(?:(<place>(?P<PLACE>.+?)</place>))""" % substitutions, re.VERBOSE)
102 re_FPP = re.compile(r'Pts\s')
104 codepage = ["utf8", "cp1252"]
106 @staticmethod
107 def getSplitRe(self, head):
108 re_SplitTourneys = re.compile("PokerStars Tournament ")
109 return re_SplitTourneys
112 def parseSummary(self):
113 m = self.re_GameType.search(self.summaryText)
114 if not m:
115 tmp = self.summaryText[0:200]
116 log.error(("iPokerSummary.determineGameType: '%s'") % tmp)
117 raise FpdbParseError
119 mg = m.groupdict()
120 #print "DEBUG: m.groupdict(): %s" % mg
122 if 'SB' in mg and mg['SB'] != None:
123 tmp = self.summaryText[0:200]
124 log.error(("iPokerSummary.parseSummary: Text does not appear to be a tournament '%s'") % tmp)
125 raise FpdbParseError
126 else:
127 tourney = True
128# self.gametype['limitType'] =
129 if 'GAME' in mg:
130 if mg['CATEGORY'] is None:
131 (self.info['base'], self.info['category']) = ('hold', '5_omahahi')
132 else:
133 (self.gametype['base'], self.gametype['category']) = self.games[mg['CATEGORY']]
134 if 'LIMIT' in mg:
135 self.gametype['limitType'] = self.limits[mg['LIMIT']]
137 m2 = self.re_DateTime1.search(mg['DATETIME'])
138 if m2:
139 month = self.months[m2.group('M')]
140 sec = m2.group('S')
141 if m2.group('S') == None:
142 sec = '00'
143 datetimestr = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), month,m2.group('D'),m2.group('H'),m2.group('MIN'),sec)
144 self.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S")
145 else:
146 try:
147 self.startTime = datetime.datetime.strptime(mg['DATETIME'], '%Y-%m-%d %H:%M:%S')
148 except ValueError:
149 date_match = self.re_DateTime2.search(mg['DATETIME'])
150 if date_match != None:
151 datestr = '%d/%m/%Y %H:%M:%S' if '/' in mg['DATETIME'] else '%d.%m.%Y %H:%M:%S'
152 if date_match.group('S') == None:
153 datestr = '%d/%m/%Y %H:%M'
154 else:
155 date_match1 = self.re_DateTime3.search(mg['DATETIME'])
156 datestr = '%Y/%m/%d %H:%M:%S'
157 if date_match1 == None:
158 log.error(("iPokerSummary.parseSummary Could not read datetime"))
159 raise FpdbParseError
160 if date_match1.group('S') == None:
161 datestr = '%Y/%m/%d %H:%M'
162 self.startTime = datetime.datetime.strptime(mg['DATETIME'], datestr)
164 if not mg['CURRENCY'] or mg['CURRENCY']=='fun':
165 self.buyinCurrency = 'play'
166 else:
167 self.buyinCurrency = mg['CURRENCY']
168 self.currency = self.buyinCurrency
170 mt = self.re_TourNo.search(mg['TABLE'])
171 if mt:
172 self.tourNo = mt.group('TOURNO')
173 else:
174 tourNo = mg['TABLE'].split(',')[-1].strip().split(' ')[0]
175 if tourNo.isdigit():
176 self.tourNo = tourNo
178 if tourney:
179 re_client_split = '.'.join(self.re_client.split('.')[:2])
180 if re_client_split == '23.5': #betclic fr
181 matches = list(self.re_GameInfoTrny.finditer(self.summaryText))
182 if len(matches) > 0:
183 mg2 = {'TOURNO': None, 'NAME': None, 'REWARD': None, 'PLACE': None, 'BIAMT': None, 'BIRAKE': None, 'BIRAKE2': None, 'TOTBUYIN': None, 'WIN': None}
184 mg2['TOURNO'] = matches[0].group('TOURNO')
185 mg2['NAME'] = matches[1].group('NAME')
186 mg2['REWARD'] = matches[2].group('REWARD')
187 mg2['PLACE'] = matches[3].group('PLACE')
188 mg2['BIAMT'] = matches[4].group('BIAMT')
189 mg2['BIRAKE'] = matches[4].group('BIRAKE')
190 mg2['BIRAKE2'] = matches[4].group('BIRAKE2')
191 mg2['TOTBUYIN'] = matches[5].group('TOTBUYIN')
192 mg2['WIN'] = matches[6].group('WIN')
194 self.buyin = 0
195 self.fee = 0
196 self.prizepool = None
197 self.entries = None
199 if mg2['TOURNO']:
200 self.tourNo = mg2['TOURNO']
201 #if mg2['CURRENCY']:
202 #self.currency = self.currencies[mg2['CURRENCY']]
203 rank, winnings = None, None
204 if 'PLACE' in mg2 and self.re_Place.search(mg2['PLACE']):
205 rank = int(mg2['PLACE'])
206 winnings = int(100*self.convert_to_decimal(mg2['WIN']))
208 self.tourneyName = mg2['NAME'].replace(" " + self.tourNo, "")
210 if not mg2['BIRAKE'] and mg2['TOTBUYIN']:
211 m3 = self.re_TotalBuyin.search(mg2['TOTBUYIN'])
212 if m3:
213 mg2 = m3.groupdict()
214 elif mg2['BIAMT']: mg2['BIRAKE'] = '0'
215 if mg2['BIAMT'] and mg2['BIRAKE']:
216 self.buyin = int(100*self.convert_to_decimal(mg2['BIAMT']))
217 self.fee = int(100*self.convert_to_decimal(mg2['BIRAKE']))
218 if 'BIRAKE1' in mg2 and mg2['BIRAKE1']:
219 self.buyin += int(100*self.convert_to_decimal(mg2['BIRAKE1']))
220 if self.re_FPP.match(mg2['BIAMT']):
221 self.buyinCurrency = 'FPP'
222 else:
223 self.buyin = 0
224 self.fee = 0
225 if self.buyin == 0:
226 self.buyinCurrency = 'FREE'
227 hero = mg['HERO']
228 self.addPlayer(rank, hero, winnings, self.currency, None, None, None)
229 else:
230 raise FpdbHandPartial(hid=self.tourNo)
231 if self.tourNo is None:
232 log.error(("iPokerSummary.parseSummary: Could Not Parse tourNo"))
233 raise FpdbParseError
235 else:
236 matches = list(self.re_GameInfoTrny2.finditer(self.summaryText))
237 if len(matches) > 0:
238 mg2 = {'TOURNO': None, 'NAME': None, 'PLACE': None, 'BIAMT': None, 'BIRAKE': None, 'TOTBUYIN': None, 'WIN': None}
239 mg2['TOURNO'] = matches[0].group('TOURNO')
240 mg2['NAME'] = matches[1].group('NAME')
241 mg2['PLACE'] = matches[2].group('PLACE')
242 mg2['BIAMT'] = matches[3].group('BIAMT')
243 mg2['BIRAKE'] = matches[3].group('BIRAKE')
244 mg2['TOTBUYIN'] = matches[4].group('TOTBUYIN')
245 mg2['WIN'] = matches[5].group('WIN')
248 self.buyin = 0
249 self.fee = 0
250 self.prizepool = None
251 self.entries = None
253 if mg2['TOURNO']:
254 self.tourNo = mg2['TOURNO']
255 #if mg2['CURRENCY']:
256 #self.currency = self.currencies[mg2['CURRENCY']]
257 rank, winnings = None, None
258 if 'PLACE' in mg2 and mg2['PLACE'] != 'N/A':
259 rank = int(mg2['PLACE'])
260 if mg2['WIN'] and mg2['WIN'] != 'N/A':
261 winnings = int(100*self.convert_to_decimal(mg2['WIN']))
263 self.tourneyName = mg2['NAME'].replace(" " + self.tourNo, "")
265 if not mg2['BIRAKE'] and mg2['TOTBUYIN']:
266 m3 = self.re_TotalBuyin.search(mg2['TOTBUYIN'])
267 if m3:
268 mg2 = m3.groupdict()
269 elif mg2['BIAMT']: mg2['BIRAKE'] = '0'
270 if mg2['BIAMT'] and mg2['BIRAKE']:
271 self.buyin = int(100*self.convert_to_decimal(mg2['BIAMT']))
272 self.fee = int(100*self.convert_to_decimal(mg2['BIRAKE']))
273 if 'BIRAKE1' in mg2 and mg2['BIRAKE1']:
274 self.buyin += int(100*self.convert_to_decimal(mg2['BIRAKE1']))
275 if self.re_FPP.match(mg2['BIAMT']):
276 self.buyinCurrency = 'FPP'
277 else:
278 self.buyin = 0
279 self.fee = 0
280 if self.buyin == 0:
281 self.buyinCurrency = 'FREE'
282 hero = mg['HERO']
283 self.addPlayer(rank, hero, winnings, self.currency, None, None, None)
284 else:
285 raise FpdbHandPartial(hid=self.tourNo)
286 if self.tourNo is None:
287 log.error(("iPokerSummary.parseSummary: Could Not Parse tourNo"))
288 raise FpdbParseError
289 else:
290 tmp = self.summaryText[0:200]
291 log.error(("iPokerSummary.determineGameType: Text does not appear to be a tournament '%s'") % tmp)
292 raise FpdbParseError
295 def convert_to_decimal(self, string):
296 dec = self.clearMoneyString(string)
297 m = self.re_Buyin.search(dec)
298 if m:
299 dec = Decimal(m.group('BUYIN'))
300 else:
301 dec = 0
302 return dec