Use debian 2.7 only
[fpbd-bostik.git] / pyfpdb / MergeSummary.py
blob786294743f621fbc0e2783d1d6dc8ba12de17613
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.
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.
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()
21 from decimal_wrapper import Decimal
22 import datetime
23 from BeautifulSoup import BeautifulSoup
25 from Exceptions import FpdbParseError
26 from HandHistoryConverter import *
27 import MergeToFpdb
28 from TourneySummary import *
31 class MergeSummary(TourneySummary):
32 limits = { 'No Limit':'nl', 'No Limit ':'nl', 'Fixed Limit':'fl', 'Limit':'fl', 'Pot Limit':'pl', 'Pot Limit ':'pl', 'Half Pot Limit':'hp'}
33 games = { # base, category
34 'Holdem' : ('hold','holdem'),
35 'Holdem Tournament' : ('hold','holdem'),
36 'Omaha' : ('hold','omahahi'),
37 'Omaha Tournament' : ('hold','omahahi'),
38 'Omaha H/L8' : ('hold','omahahilo'),
39 '2-7 Lowball' : ('draw','27_3draw'),
40 'A-5 Lowball' : ('draw','a5_3draw'),
41 'Badugi' : ('draw','badugi'),
42 '5-Draw w/Joker' : ('draw','fivedraw'),
43 '5-Draw' : ('draw','fivedraw'),
44 '7-Stud' : ('stud','studhi'),
45 '7-Stud H/L8' : ('stud','studhilo'),
46 '5-Stud' : ('stud','5studhi'),
47 'Razz' : ('stud','razz')
49 games_html = {
50 'Texas Holdem' : ('hold','holdem'),
51 'Omaha' : ('hold','omahahi'),
52 'Omaha HiLo' : ('hold','omahahilo'),
53 '2-7 Low Triple Draw' : ('draw','27_3draw'),
54 'Badugi' : ('draw','badugi'),
55 'Seven Card Stud' : ('stud','studhi'),
56 'Seven Card Stud HiLo' : ('stud','studhilo'),
57 'Five Card Stud' : ('stud','studhilo'),
58 'Razz' : ('stud','razz')
61 months = { 'January':1, 'Jan':1, 'February':2, 'Feb':2, 'March':3, 'Mar':3,
62 'April':4, 'Apr':4, 'May':5, 'May':5, 'June':6, 'Jun':6,
63 'July':7, 'Jul':7, 'August':8, 'Aug':8, 'September':9, 'Sep':9,
64 'October':10, 'Oct':10, 'November':11, 'Nov':11, 'December':12, 'Dec':12}
67 substitutions = {
68 'LEGAL_ISO' : "USD|EUR|GBP|CAD|FPP", # legal ISO currency codes
69 'LS' : u"\$|\xe2\x82\xac|\u20ac|" # legal currency symbols
71 re_GameTypeHH = re.compile(r'<description type="(?P<GAME>Holdem|Omaha|Omaha|Omaha\sH/L8|2\-7\sLowball|A\-5\sLowball|Badugi|5\-Draw\sw/Joker|5\-Draw|7\-Stud|7\-Stud\sH/L8|5\-Stud|Razz|HORSE)(?P<TYPE>\sTournament)?" stakes="(?P<LIMIT>[a-zA-Z ]+)(\s\(?\$?(?P<SB>[.0-9]+)?/?\$?(?P<BB>[.0-9]+)?(?P<blah>.*)\)?)?"/>', re.MULTILINE)
72 re_HandInfoHH = re.compile(r'<game id="(?P<HID1>[0-9]+)-(?P<HID2>[0-9]+)" starttime="(?P<DATETIME>[0-9]+)" numholecards="[0-9]+" gametype="[0-9]+" (multigametype="(?P<MULTIGAMETYPE>\d+)" )?(seats="(?P<SEATS>[0-9]+)" )?realmoney="(?P<REALMONEY>(true|false))" data="[0-9]+\|(?P<TABLENAME>[^|]+)\|(?P<TDATA>[^|]+)\|?.*>', re.MULTILINE)
74 re_HTMLName = re.compile("Name</th><td>(?P<NAME>.+?)</td>")
75 re_HTMLGameType = re.compile("""Game Type</th><td>(?P<LIMIT>Fixed Limit|No Limit|Pot Limit) (?P<GAME>Texas\sHoldem|Omaha|Omaha\sHiLo|2\-7\sLow\sTriple\sDraw|Badugi|Seven\sCard\sStud|Seven\sCard\sStud\sHiLo|Five\sCard\sStud|Razz|HORSE|HA|HO)</td>""")
76 re_HTMLBuyIn = re.compile("Buy In</th><td>(?P<BUYIN>[0-9,.]+)</td>")
77 re_HTMLFee = re.compile("Entry Fee</th><td>(?P<FEE>[0-9,.]+)</td>")
78 re_HTMLBounty = re.compile("Bounty</th><td>(?P<KOBOUNTY>.+?)</td>")
79 re_HTMLAddons = re.compile("Addons</th><td>(?P<ADDON>.+?)</td>")
80 re_HTMLRebuy = re.compile("Rebuys</th><td>(?P<REBUY>.+?)</td>")
81 re_HTMLTourNo = re.compile("Game ID</th><td>(?P<TOURNO>[0-9]+)-1</td>")
82 re_HTMLPlayer = re.compile(u"""<tr><td align="center">(?P<RANK>\d+)</td><td>(?P<PNAME>.+?)</td><td>(?P<WINNINGS>.+?)</td></tr>""")
83 re_HTMLDetails = re.compile(u"""<p class="text">(?P<LABEL>.+?) : (?P<VALUE>.+?)</p>""")
84 re_HTMLPrizepool = re.compile(u"""Total Prizepool</th><td>(?P<PRIZEPOOL>[0-9,.]+)</td>""")
85 re_HTMLStartTime = re.compile("Start Time</th><td>(?P<STARTTIME>.+?)</td>")
86 re_HTMLDateTime = re.compile("\w+?\s+?(?P<D>\d+)\w+?\s+(?P<M>\w+)\s+(?P<Y>\d+),?\s+(?P<H>\d+):(?P<MIN>\d+):(?P<S>\d+)")
88 re_Ticket = re.compile(u""" / Ticket (?P<VALUE>[0-9.]+)&euro;""")
90 codepage = ["utf-8"]
92 @staticmethod
93 def getSplitRe(self, head):
94 re_SplitTourneys = re.compile("PokerStars Tournament ")
95 return re_SplitTourneys
97 def parseSummary(self):
98 # id type of file and call correct function
99 m = self.re_GameTypeHH.search(self.summaryText)
100 if m:
101 mg = m.groupdict()
102 if ' Tournament' == mg['TYPE']:
103 self.parseSummaryFromHH(mg)
104 else:
105 self.parseSummaryFile()
107 def parseSummaryFromHH(self, mg):
108 if 'LIMIT' in mg:
109 self.gametype['limitType'] = self.limits[mg['LIMIT']]
110 if 'GAME' in mg:
111 if mg['GAME'] == "HORSE":
112 log.error(_("MergeSummary.determineGameType: HORSE found, unsupported"))
113 raise FpdbParseError
114 #(self.info['base'], self.info['category']) = self.Multigametypes[m2.group('MULTIGAMETYPE')]
115 else:
116 self.gametype['category'] = self.games[mg['GAME']][1]
117 m = self.re_HandInfoHH.search(self.summaryText)
118 if m is None:
119 tmp = self.summaryText[0:200]
120 log.error(_("MergeSummary.readHandInfo: '%s'") % tmp)
121 raise FpdbParseError
123 tourneyNameFull = m.group('TABLENAME')
124 self.tourneyName = m.group('TABLENAME')[:40]
125 self.tourNo = re.split('-', m.group('TDATA'))[0]
126 self.startTime = datetime.datetime.strptime(m.group('DATETIME')[:12],'%Y%m%d%H%M')
127 self.startTime = HandHistoryConverter.changeTimezone(self.startTime, "ET", "UTC")
128 obj = getattr(MergeToFpdb, "Merge", None)
129 hhc = obj(self.config, in_path = self.in_path, sitename = None, autostart = False)
131 if tourneyNameFull not in hhc.SnG_Structures:
132 log.error(_("MergeSummary.determineGameType: No match in SnG_Structures"))
133 raise FpdbParseError
135 self.buyin = int(100*hhc.SnG_Structures[tourneyNameFull]['buyIn'])
136 self.fee = int(100*hhc.SnG_Structures[tourneyNameFull]['fee'])
137 self.entries = hhc.SnG_Structures[tourneyNameFull]['seats']
138 self.buyinCurrency = hhc.SnG_Structures[tourneyNameFull]['currency']
139 self.currency = hhc.SnG_Structures[tourneyNameFull]['payoutCurrency']
140 self.maxseats = hhc.SnG_Structures[tourneyNameFull]['seats']
141 self.prizepool = sum(hhc.SnG_Structures[tourneyNameFull]['payouts'])
142 payouts = len(hhc.SnG_Structures[tourneyNameFull]['payouts'])
143 self.isSng = True
145 if hhc.SnG_Structures[tourneyNameFull]['multi']:
146 log.error(_("MergeSummary.determineGameType: Muli-table SnG found, unsupported"))
147 raise FpdbParseError
149 handsList = hhc.allHandsAsList()
150 for handText in handsList:
151 players, out, won = {}, [], []
152 for m in hhc.re_PlayerOut.finditer(handText):
153 out.append(m.group('PSEAT'))
154 if out:
155 for m in hhc.re_PlayerInfo.finditer(handText):
156 players[m.group('SEAT')] = m.group('PNAME')
157 if not players: continue
158 for m in hhc.re_CollectPot.finditer(handText):
159 won.append(m.group('PSEAT'))
160 i = 0
161 for n in out:
162 winnings = 0
163 if n in won:
164 rank = 1
165 winnings = int(100*hhc.SnG_Structures[tourneyNameFull]['payouts'][0])
166 else:
167 rank = len(players) - i
168 if rank <= payouts:
169 winnings = int(100*hhc.SnG_Structures[tourneyNameFull]['payouts'][rank-1])
170 i += 1
171 self.addPlayer(rank, players[n], winnings, self.currency, 0, 0, 0)
173 def parseSummaryFile(self):
174 self.buyinCurrency = "USD"
175 soup = BeautifulSoup(self.summaryText)
176 tables = soup.findAll('table')
177 table1 = BeautifulSoup(str(tables[0])).findAll('tr')
178 table2 = BeautifulSoup(str(tables[1])).findAll('tr')
179 # FIXME: Searching every line for all regexes is pretty horrible
180 # FIXME: Need to search for 'Status: Finished'
181 #print self.in_path
182 for p in table1:
183 m = self.re_HTMLGameType.search(str(p))
184 if m:
185 #print "DEBUG: re_HTMLGameType: '%s' '%s'" %(m.group('LIMIT'), m.group('GAME'))
186 if m.group('GAME') in ("HORSE", "HA", "HO"):
187 log.error(_("MergeSummary.parseSummaryFile: %s found, unsupported") % m.group('GAME'))
188 raise FpdbParseError
189 self.gametype['limitType'] = self.limits[m.group('LIMIT')]
190 self.gametype['category'] = self.games_html[m.group('GAME')][1]
191 m = self.re_HTMLTourNo.search(str(p))
192 if m:
193 #print "DEBUG: re_HTMLTourNo: '%s'" % m.group('TOURNO')
194 self.tourNo = m.group('TOURNO')
195 m = self.re_HTMLName.search(str(p))
196 if m:
197 #print "DEBUG: re_HTMLName: '%s'" % m.group('NAME')
198 self.tourneyName = m.group('NAME')[:40]
199 if m.group('NAME').find("$")!=-1:
200 self.buyinCurrency="USD"
201 elif m.group('NAME').find(u"€")!=-1:
202 self.buyinCurrency="EUR"
203 m = self.re_HTMLPrizepool.search(str(p))
204 if m:
205 #print "DEBUG: re_HTMLPrizepool: '%s'" % m.group('PRIZEPOOL')
206 self.prizepool = int(convert_to_decimal(m.group('PRIZEPOOL')))
207 m = self.re_HTMLBuyIn.search(str(p))
208 if m:
209 #print "DEBUG: re_HTMLBuyIn: '%s'" % m.group('BUYIN')
210 self.buyin = int(100*convert_to_decimal(m.group('BUYIN')))
211 if self.buyin==0:
212 self.buyinCurrency="FREE"
213 m = self.re_HTMLFee.search(str(p))
214 if m:
215 #print "DEBUG: re_HTMLFee: '%s'" % m.group('FEE')
216 self.fee = int(100*convert_to_decimal(m.group('FEE')))
217 m = self.re_HTMLBounty.search(str(p))
218 if m:
219 #print "DEBUG: re_HTMLBounty: '%s'" % m.group('KOBOUNTY')
220 if m.group('KOBOUNTY') != '0.00':
221 self.isKO = True
222 self.koBounty = int(100*convert_to_decimal(m.group('KOBOUNTY')))
223 m = self.re_HTMLAddons.search(str(p))
224 if m:
225 #print "DEBUG: re_HTMLAddons: '%s'" % m.group('ADDON')
226 if m.group('ADDON') != '0':
227 self.isAddOn = True
228 self.addOnCost = self.buyin
229 m = self.re_HTMLRebuy.search(str(p))
230 if m:
231 #print "DEBUG: re_HTMLRebuy: '%s'" % m.group('REBUY')
232 if m.group('REBUY') != '0':
233 self.isRebuy = True
234 self.rebuyCost = self.buyin
235 m = self.re_HTMLStartTime.search(str(p))
236 if m:
237 m2 = self.re_HTMLDateTime.search(m.group('STARTTIME'))
238 if m2:
239 month = self.months[m2.group('M')]
240 datetimestr = "%s/%s/%s %s:%s:%s" % (m2.group('Y'), month,m2.group('D'),m2.group('H'),m2.group('MIN'),m2.group('S'))
241 self.startTime = datetime.datetime.strptime(datetimestr, "%Y/%m/%d %H:%M:%S")
242 self.startTime = HandHistoryConverter.changeTimezone(self.startTime, "ET", "UTC")
244 self.currency = self.buyinCurrency
245 for p in table2:
246 m = self.re_HTMLPlayer.search(str(p))
247 if m:
248 self.entries += 1
249 #print "DEBUG: rank: %s pname: %s won: %s" %(m.group('RANK'), m.group('PNAME'), m.group('WINNINGS'))
250 winnings = 0
251 rebuyCount = 0
252 addOnCount = 0
253 koCount = 0
255 rank = int(m.group('RANK'))
256 name = m.group('PNAME')
257 if m.group('WINNINGS') != None:
258 if m.group('WINNINGS').find("$")!=-1:
259 self.currency="USD"
260 elif m.group('WINNINGS').find(u"€")!=-1:
261 self.currency="EUR"
262 winnings = int(100*convert_to_decimal(m.group('WINNINGS')))
263 self.addPlayer(rank, name, winnings, self.currency, rebuyCount, addOnCount, koCount)
265 def convert_to_decimal(string):
266 dec = string.strip(u'€&euro;\u20ac$')
267 dec = dec.replace(u',','.')
268 dec = dec.replace(u' ','')
269 dec = Decimal(dec)
270 return dec