def fromFileName(klass, fileName): # stars seems to have switched to utf-8 at some time. more or less a guess # that it used to be iso-8859-1 before. data = None fp = codecs.open(fileName, encoding='utf-8') try: data = fp.read() except UnicodeDecodeError: pass else: #NOTE: remove BOM(s) if present. seen unicode BOM_BE trailing game headers # even within HHs (no idea why), so for now we remove all BOMs unconditionally data = data.replace(unicode(codecs.BOM_UTF8, 'utf-8'), '') #NOTE: found that some files start with \x10 (TourneySumaries) if data.startswith('\x10'): data = data[1:] finally: fp.close() if data is None: fp = codecs.open(fileName, encoding='iso-8859-1') try: data = fp.read() finally: fp.close() lines = HcConfig.linesFromString(data) return klass(lines, fileName=fileName)
def parseGameHeader(self, lines, eventHandler, events, state): if len(lines) < 2: return False m = self.PatternGameHeader.match(lines[0][1]) if m is None: return False d = m.groupdict() m = self.PatternTableHeader.match(lines[1][1]) if m is None: lines.pop(0) return False d.update(m.groupdict()) d['seatNoButton'] = int(d['seatNoButton']) d['site'] = self.ID['site'] d['gameScope'] = self.ID['gameScope'] d['gameContext'] = self.ID['gameContext'] d['game'] = GameMapping[d['game']] d['gameLimit'] = GameLimitMapping[d['gameLimit'].lower()] #NOTE: stars added currency to header at some point, but this is pretty useless # for parsing old hand histories, so we parse currency symbols directly line = lines[0][1] currency = CurrencyMapping[''] for symbol in CurrencySymbols: if symbol in line: currency = CurrencyMapping[symbol] break d['currency'] = currency d['bigBlind'] = self.stringToFloat(d['bigBlind']) d['smallBlind'] = self.stringToFloat(d['smallBlind']) d['maxPlayers'] = int(d['maxPlayers']) d['time'] = HcConfig.timeToUTC( (int(d.pop('year')), int(d.pop('month')), int(d.pop('day')), int(d.pop('hour')), int(d.pop('minute')), int(d.pop('second'))), timeZone=HcConfig.TimeZoneET, ) lines.pop(0) lines.pop(0) #NOTE: we have to parse ante here because PS does not report it in header # we can either guess here (highest amount posted) or look it up somewhere # if we are positive that ante is charged. maxAnte = self.parsePlayerPostAnte(lines, eventHandler, events, state) d['ante'] = maxAnte events[0] = (eventHandler.handleHandStart, d) return True
def fromString(klass, string): lines = HcConfig.linesFromString(string) return klass(lines, fileName='')