def disagree(about): """do not bother to translate this, it should normally not happen""" self.game.close() msg = u'The data bases for game %s have different %s' % ( self.game.seed, about) logWarning(msg) raise pb.Error(msg)
def _loginReallyFailed(self, failure): """login failed, not fixable by adding missing user""" msg = None if not isAlive(Internal.mainWindow): raise CancelledError if failure.check(CancelledError): pass elif failure.check(twisted.internet.error.TimeoutError): msg = i18n('Server %1 did not answer', self.url) elif failure.check(twisted.internet.error.ConnectionRefusedError): msg = i18n('Server %1 refused connection', self.url) elif failure.check(twisted.internet.error.ConnectionLost): msg = i18n('Server %1 does not run a kajongg server', self.url) elif failure.check(twisted.internet.error.DNSLookupError): msg = i18n('Address for server %1 cannot be found', self.url) elif failure.check(twisted.internet.error.ConnectError): msg = i18n( 'Login to server %1 failed: You have no network connection', self.url) else: msg = 'Login to server {} failed: {}/{} Callstack:{}'.format( self.url, failure.value.__class__.__name__, failure.getErrorMessage(), failure.getTraceback()) # Maybe the server is running but something is wrong with it if self.url and self.url.useSocket: if removeIfExists(socketName()): logInfo( i18n('removed stale socket <filename>%1</filename>', socketName())) msg += '\n\n\n' + i18n('Please try again') self.dlg = None if msg: logWarning(msg) raise CancelledError
def __versionError(err): """log the twisted error""" logWarning(err.getErrorMessage()) if Internal.game: Internal.game.close() Internal.game = None return err
def remote_tableRemoved(self, tableid, message, *args): """update table list""" Client.remote_tableRemoved(self, tableid, message, *args) self.__updateTableList() if message: if self.name not in args or not message.endswith('has logged out'): logWarning(i18n(message, *args))
def kajonggServer(): """start the server""" # pylint: disable=too-many-branches options = parseArgs() if not initDb(): sys.exit(1) realm = MJRealm() realm.server = MJServer() kajonggPortal = portal.Portal(realm, [DBPasswordChecker()]) import predefined predefined.load() try: if Options.socket: # we do not want tracebacks to go from server to client, # please check on the server side instead factory = pb.PBServerFactory(kajonggPortal, unsafeTracebacks=False) if os.name == 'nt': if Debug.connections: logDebug('local server listening on 127.0.0.1 port %d' % options.port) reactor.listenTCP(options.port, factory, interface='127.0.0.1') else: if Debug.connections: logDebug('local server listening on UNIX socket %s' % Options.socket) reactor.listenUNIX(Options.socket, factory) else: if Debug.connections: logDebug('server listening on port %d' % options.port) reactor.listenTCP(options.port, pb.PBServerFactory(kajonggPortal)) except error.CannotListenError as errObj: logWarning(errObj) sys.exit(1) else: reactor.run()
def downloadGoogleTrendsData(geoIdArray): pytrend = TrendReq() maxLength = len(geoIdArray) progress = 0 tooManyRequestGeoIdArray = [] for geoId in geoIdArray: printProgressBar(progress, maxLength, "Downloading Google Trends data for " + geoId) geoIdForGoolge = geoId #special cases if geoId == "GB": geoIdForGoolge = "GB-ENG" if(geoIdForGoolge != "" and geoIdForGoolge != None and geoIdForGoolge != "N/A"): try: pytrend.build_payload(kw_list=['/m/01cpyy'], timeframe='2019-11-01 ' + datetime.datetime.now().strftime("%Y-%m-%d"), geo=geoIdForGoolge) interest_over_time_df = pytrend.interest_over_time() interest_over_time_df.to_csv("../dat/temp/googleTrends/" + geoId + ".csv") except pytrends.exceptions.ResponseError as error: if error.response.status_code == 429: log.logInfo("Google is mad at us that we make so much requests so were waiting for a minute before continuing (geoId will be redownloaded at the end)") tooManyRequestGeoIdArray.append(geoId) time.sleep(60) else: log.logError("Downloading googletrends for geoId " + geoId + " failed - Errormessage was: " + str(error)) except Exception as error: log.logWarning("Downloading googletrends for geoId " + geoId + " failed - Errormessage was: " + str(error)) progress += 1 if len(tooManyRequestGeoIdArray) > 0: downloadGoogleTrendsData(tooManyRequestGeoIdArray)
def disagree(about): """do not bother to translate this, it should normally not happen""" self.game.close() msg = 'The data bases for game %s have different %s' % ( self.game.seed, about) logWarning(msg) raise pb.Error(msg)
def remote_tableRemoved(self, tableid, message, *args): """update table list""" Client.remote_tableRemoved(self, tableid, message, *args) self.__updateTableList() if message: if self.name not in args or not message.endswith('has logged out'): logWarning(m18n(message, *args))
def __checkExistingConnections(self, dummy=None): """do we already have a connection to the wanted URL?""" for client in self.client.humanClients: if client.connection and client.connection.url == self.url: logWarning( i18n('You are already connected to server %1', self.url)) client.tableList.activateWindow() raise CancelledError
def rollback(self, silent=None): """rollback and log it""" try: sqlite3.Connection.rollback(self) if not silent and Debug.sql: logDebug('%x rollbacked transaction' % id(self)) except sqlite3.Error as exc: logWarning('%s cannot rollback: %s' % (self.name, exc.message))
def rollback(self, silent=None): """rollback and log it""" try: sqlite3.Connection.rollback(self) if not silent and Debug.sql: logDebug(u'%x rollbacked transaction' % id(self)) except sqlite3.Error as exc: logWarning(u'%s cannot rollback: %s' % (self.name, exc.message))
def tableError(self, err): """log the twisted error""" if not self.connection: # lost connection to server if self.tableList: self.tableList.hide() self.tableList = None else: logWarning(err.getErrorMessage())
def remote_abort(self, tableid, message: str, *args): """the server aborted this game""" if self.table and self.table.tableid == tableid: # translate Robot to Roboter: if self.game: args = self.game.players.translatePlayerNames(args) logWarning(i18n(message, *args)) if self.game: self.game.close()
def commit(self, silent=None): """commit and log it""" try: sqlite3.Connection.commit(self) except sqlite3.Error as exc: if not silent: logWarning( '%s cannot commit: %s :' % (self.name, exc.message))
def commit(self, silent=None): """commit and log it""" try: sqlite3.Connection.commit(self) except sqlite3.Error as exc: if not silent: logWarning( u'%s cannot commit: %s :' % (self.name, exc.message))
def remote_abort(self, tableid, message, *args): """the server aborted this game""" message = nativeString(message) args = nativeStringArgs(args) if self.table and self.table.tableid == tableid: # translate Robot to Roboter: if self.game: args = self.game.players.translatePlayerNames(args) logWarning(m18n(message, *args)) if self.game: self.game.close()
def __init__(self, desktopFileName=None): if desktopFileName is None: desktopFileName = 'default' self.__svg = None self.__pmap = None QPixmapCache.setCacheLimit(20480) # the chinese landscape needs much self.defineCatalog() self.desktopFileName = desktopFileName self.path = locatebackground(desktopFileName + '.desktop') if self.path.isEmpty(): self.path = locatebackground('default.desktop') if self.path.isEmpty(): directories = '\n\n' + \ '\n'.join(str(x) for x in KGlobal.dirs().resourceDirs("kmahjonggbackground")) logException(BackgroundException(m18n( 'cannot find any background in the following directories, is libkmahjongg installed?') + directories)) else: logWarning( m18n( 'cannot find background %1, using default', desktopFileName)) self.desktopFileName = 'default' config = KConfig(self.path) group = config.group("KMahjonggBackground") self.name = group.readEntry("Name") or m18n("unknown background") # Version control backgroundversion = int(group.readEntry("VersionFormat")) or 0 # Format is increased when we have incompatible changes, meaning that # older clients are not able to use the remaining information safely if backgroundversion > BACKGROUNDVERSIONFORMAT: logException(BackgroundException('backgroundversion file / program: %d/%d' % (backgroundversion, BACKGROUNDVERSIONFORMAT))) self.tiled = group.readEntry('Tiled') == '1' if self.tiled: self.imageWidth, entryOk = group.readEntry('Width').toInt() if not entryOk: raise Exception('cannot scan Width from background file') self.imageHeight, entryOk = group.readEntry('Height').toInt() if not entryOk: raise Exception('cannot scan Height from background file') self.isPlain = bool(group.readEntry('Plain')) if not self.isPlain: graphName = QString(group.readEntry("FileName")) self.__graphicspath = locatebackground(graphName) if self.__graphicspath.isEmpty(): logException(BackgroundException( 'cannot find kmahjongglib/backgrounds/%s for %s' % (graphName, self.desktopFileName)))
def scoreMatchesServer(self, score): """do we compute the same score as the server does?""" if score is None: return True if any(not x.isKnown for x in self._concealedTiles): return True if str(self.hand) == score: return True self.game.debug('%s localScore:%s' % (self, self.hand)) self.game.debug('%s serverScore:%s' % (self, score)) logWarning( u'Game %s: client and server disagree about scoring, see logfile for details' % self.game.seed) return False
def scoreMatchesServer(self, score): """do we compute the same score as the server does?""" if score is None: return True if any(not x.isKnown for x in self._concealedTiles): return True if str(self.hand) == score: return True self.game.debug('%s localScore:%s' % (self, self.hand)) self.game.debug('%s serverScore:%s' % (self, score)) logWarning( 'Game %s: client and server disagree about scoring, see logfile for details' % self.game.seed) return False
def savedmd5Sum(self): """returns the current value of the md5sum file""" if os.path.exists(self.md5FileName()): try: line = open(self.md5FileName(), 'r').readlines()[0].replace(' -', '').strip() if len(line) == self.md5sumLength: return line else: logWarning('{} has wrong content: {}'.format( self.md5FileName(), line)) except BaseException as exc: logWarning('{} has wrong content: {}'.format( self.md5FileName(), exc))
def extractCountryPopulationForYear(populationRaw, year): population = {} for countryPopulation in populationRaw[year]: if countryPopulation["VarID"] == '2': country = pycountry.countries.get( numeric=countryPopulation["LocID"].zfill(3)) if country != None: population[country.alpha_2] = float( countryPopulation["PopTotal"]) else: log.logWarning("Countrycode of " + countryPopulation["Location"] + "couldnt be parsed") return population
def parseArgs(): """as the name says""" from optparse import OptionParser parser = OptionParser() defaultPort = Internal.defaultPort parser.add_option('', '--port', dest='port', help=i18n('the server will listen on PORT (%d)' % defaultPort), type=int, default=defaultPort) parser.add_option('', '--socket', dest='socket', help=i18n('the server will listen on SOCKET'), default=None) parser.add_option('', '--db', dest='dbpath', help=i18n('name of the database'), default=None) parser.add_option( '', '--continue', dest='continueServer', action='store_true', help=i18n( 'do not terminate local game server after last client disconnects' ), default=False) parser.add_option('', '--debug', dest='debug', help=Debug.help()) (options, args) = parser.parse_args() if args and ''.join(args): logWarning(i18n('unrecognized arguments:%1', ' '.join(args))) sys.exit(2) Options.continueServer |= options.continueServer if options.dbpath: Options.dbPath = os.path.expanduser(options.dbpath) if options.socket: Options.socket = options.socket Debug.setOptions(options.debug) Options.fixed = True # may not be changed anymore del parser # makes Debug.gc quieter return options
def __scanHandId(self, string, stringIdx): """gets the --game option. stringIdx 0 is the part in front of .. stringIdx 1 is the part after .. """ # pylint: disable=too-many-return-statements,too-many-branches if not string: return seed = int(string.split('/')[0]) assert self.seed is None or self.seed == seed, string self.seed = seed if '/' not in string: if stringIdx == 1: self.roundsFinished = 100 return string1 = string.split('/')[1] if not string1: logException('--game=%s must specify the wanted round' % string) parts = string1.split('..') if stringIdx == 1 and len(parts) == 2 and parts[1] == '': self.roundsFinished = 100 return if stringIdx == 0 and len(parts) == 2 and parts[0] == '': return if stringIdx == 1 and len(parts) == 2 and parts[1] == '': self.roundsFinished = 100 return handId = parts[min(stringIdx, len(parts) - 1)] if handId[0].lower() not in 'eswn': logException('--game=%s must specify the round wind' % string) handWind = Wind(handId[0]) ruleset = self.game.ruleset self.roundsFinished = handWind.__index__() if self.roundsFinished > ruleset.minRounds: logWarning( u'Ruleset %s has %d minimum rounds but you want round %d(%s)' % (ruleset.name, ruleset.minRounds, self.roundsFinished + 1, handWind)) self.roundsFinished = ruleset.minRounds return self.rotated = int(handId[1]) - 1 if self.rotated > 3: logWarning( u'You want %d rotations, reducing to maximum of 3' % self.rotated) self.rotated = 3 return for char in handId[2:]: if char < 'a': logWarning(u'you want %s, changed to a' % char) char = 'a' if char > 'z': logWarning(u'you want %s, changed to z' % char) char = 'z' self.notRotated = self.notRotated * 26 + ord(char) - ord('a') + 1
def __scanHandId(self, string, stringIdx): """gets the --game option. stringIdx 0 is the part in front of .. stringIdx 1 is the part after .. """ # pylint: disable=too-many-return-statements,too-many-branches if not string: return seed = int(string.split('/')[0]) assert self.seed is None or self.seed == seed, string self.seed = seed if '/' not in string: if stringIdx == 1: self.roundsFinished = 100 return string1 = string.split('/')[1] if not string1: logException('--game=%s must specify the wanted round' % string) parts = string1.split('..') if stringIdx == 1 and len(parts) == 2 and parts[1] == '': self.roundsFinished = 100 return if stringIdx == 0 and len(parts) == 2 and parts[0] == '': return if stringIdx == 1 and len(parts) == 2 and parts[1] == '': self.roundsFinished = 100 return handId = parts[min(stringIdx, len(parts) - 1)] if handId[0].lower() not in 'eswn': logException('--game=%s must specify the round wind' % string) handWind = Wind(handId[0]) ruleset = self.game.ruleset self.roundsFinished = handWind.__index__() if self.roundsFinished > ruleset.minRounds: logWarning( 'Ruleset %s has %d minimum rounds but you want round %d(%s)' % (ruleset.name, ruleset.minRounds, self.roundsFinished + 1, handWind)) self.roundsFinished = ruleset.minRounds return self.rotated = int(handId[1]) - 1 if self.rotated > 3: logWarning('You want %d rotations, reducing to maximum of 3' % self.rotated) self.rotated = 3 return for char in handId[2:]: if char < 'a': logWarning('you want %s, changed to a' % char) char = 'a' if char > 'z': logWarning('you want %s, changed to z' % char) char = 'z' self.notRotated = self.notRotated * 26 + ord(char) - ord('a') + 1
def scoreGame(): """show all games, select an existing game or create a new game""" Players.load() if len(Players.humanNames) < 4: logWarning( m18n('Please define four players in <interface>Settings|Players</interface>')) return gameSelector = Games(Internal.mainWindow) selected = None if not gameSelector.exec_(): return selected = gameSelector.selectedGame gameSelector.close() if selected is not None: return ScoringGame.loadFromDB(selected) else: selectDialog = SelectPlayers() if not selectDialog.exec_(): return return ScoringGame(list(zip(Wind.all4, selectDialog.names)), selectDialog.cbRuleset.current)
def __build(cls, name): """build a new Resource. name is either a full file path or a desktop name. None stands for 'default'.""" result = object.__new__(cls) if os.path.exists(name): result.path = name result.desktopFileName = cls.__name(name) else: result.desktopFileName = name or 'default' result.path = cls.locate(result.desktopFileName + '.desktop') if not result.path: result.path = cls.locate('default.desktop') result.desktopFileName = 'default' if not result.path: cls.__noTilesetFound() else: logWarning(i18n('cannot find %1, using default', name)) cls.cache[result.desktopFileName] = result cls.cache[result.path] = result return result
def findOggBinary(): """sets __oggBinary to exe name or an empty string""" if Sound.__oggBinary is None: if os.name == 'nt': Sound.__oggBinary = os.path.join('share', 'kajongg', 'voices', 'oggdec.exe') msg = '' # we bundle oggdec.exe with the kajongg installer, it must be there else: oggBinary = 'ogg123' msg = i18n( 'No voices will be heard because the program %1 is missing', oggBinary) if which(oggBinary): Sound.__oggBinary = oggBinary else: Sound.__oggBinary = '' Internal.Preferences.useSounds = False # checks again at next reenable if msg: logWarning(msg) if Debug.sound: logDebug('ogg123 found:' + Sound.__oggBinary) return Sound.__oggBinary
def scoreGame(): """show all games, select an existing game or create a new game""" Players.load() if len(Players.humanNames) < 4: logWarning( i18n( 'Please define four players in <interface>Settings|Players</interface>' )) return gameSelector = Games(Internal.mainWindow) selected = None if not gameSelector.exec_(): return selected = gameSelector.selectedGame gameSelector.close() if selected is not None: return ScoringGame.loadFromDB(selected) else: selectDialog = SelectPlayers() if not selectDialog.exec_(): return return ScoringGame(list(zip(Wind.all4, selectDialog.names)), selectDialog.cbRuleset.current)
def callServer(self, *args): """if we are online, call server""" if self.connection: if args[0] is None: args = args[1:] try: if Debug.traffic: self.__logCallServer(*args) def callServerError(result): """if serverDisconnected has been called meanwhile, just ignore msg about connection lost in a non-clean fashion""" if self.connection: return result return self.connection.perspective.callRemote(*args).addErrback(callServerError) except pb.DeadReferenceError: logWarning( m18n( 'The connection to the server %1 broke, please try again later.', self.connection.url)) self.remote_serverDisconnects() return succeed(None) else: return succeed(None)
def callServer(self, *args): """if we are online, call server""" if self.connection: if args[0] is None: args = args[1:] try: if Debug.traffic: self.__logCallServer(*args) def callServerError(result): """if serverDisconnected has been called meanwhile, just ignore msg about connection lost in a non-clean fashion""" if self.connection: return result return self.connection.perspective.callRemote(*args).addErrback(callServerError) except pb.DeadReferenceError: logWarning( i18n( 'The connection to the server %1 broke, please try again later.', self.connection.url)) self.remote_serverDisconnects() return succeed(None) else: return succeed(None)
def clientAction(self, dummyClient, move): """show the error message from server""" return logWarning(move.source)
def __init__(self, desktopFileName=None): if desktopFileName is None: desktopFileName = 'default' self.tileSize = None self.faceSize = None self.__renderer = None self.__shadowOffsets = None self.defineCatalog() self.path = locateTileset(desktopFileName + '.desktop') if self.path.isEmpty(): self.path = locateTileset('default.desktop') if self.path.isEmpty(): self.__noTilesetFound() else: logWarning( m18n( 'cannot find tileset %1, using default', desktopFileName)) self.desktopFileName = 'default' else: self.desktopFileName = desktopFileName self.darkenerAlpha = 120 if self.desktopFileName == 'jade' else 50 tileconfig = KConfig(self.path, KConfig.SimpleConfig) group = tileconfig.group("KMahjonggTileset") self.name = group.readEntry("Name") or m18n("unknown tileset") self.author = group.readEntry("Author") or m18n("unknown author") self.description = group.readEntry( "Description") or m18n( "no description available") self.authorEmail = group.readEntry( "AuthorEmail") or m18n( "no E-Mail address available") # Version control tileversion = int(group.readEntry("VersionFormat")) or 0 # Format is increased when we have incompatible changes, meaning that # older clients are not able to use the remaining information safely if tileversion > TILESETVERSIONFORMAT: logException(TileException('tileversion file / program: %d/%d' % (tileversion, TILESETVERSIONFORMAT))) graphName = group.readEntry("FileName") self.__graphicspath = locateTileset(graphName) if self.__graphicspath.isEmpty(): logException( TileException('cannot find kmahjongglib/tilesets/%s for %s' % (graphName, self.desktopFileName))) self.renderer() # now that we get the sizes from the svg, we need the # renderer right away self.svgName = { 'wn': North.svgName, 'ws': South.svgName, 'we': East.svgName, 'ww': West.svgName, 'db': 'DRAGON_1', 'dg': 'DRAGON_2', 'dr': 'DRAGON_3'} for value in '123456789': self.svgName['s%s' % value] = 'ROD_%s' % value self.svgName['b%s' % value] = 'BAMBOO_%s' % value self.svgName['c%s' % value] = 'CHARACTER_%s' % value for idx, wind in enumerate('eswn'): self.svgName['f%s' % wind] = 'FLOWER_%d' % (idx + 1) self.svgName['y%s' % wind] = 'SEASON_%d' % (idx + 1)
def getTopFlopCountries(coronaCasesDataDict, healthSpendingDict, count): for countryKey in healthSpendingDict: healthSpendingDict[countryKey] = sorted(healthSpendingDict[countryKey], key=lambda e: int(e["YEAR"])) # sorted of dicts returns only keys as array sortedHealthSpendingCountryKeys = sorted( healthSpendingDict, key=lambda e: float(healthSpendingDict[e][-1]["Numeric"])) topCountries = [] counter = 0 for countryKey in reversed(sortedHealthSpendingCountryKeys): try: country = pycountry.countries.get(alpha_3=countryKey) conutryAlpha2 = country.alpha_2 if conutryAlpha2 in coronaCasesDataDict.keys(): counter += 1 topCountries.append({ "coronaCases": coronaCasesDataDict[conutryAlpha2], "healthSpending": healthSpendingDict[countryKey], "alpha_2": conutryAlpha2 }) if counter >= count: break except Exception as e: log.logWarning("Error while preprocessing sortedHealthSpending " + str(e)) flopCountries = [] counter = 0 for countryKey in sortedHealthSpendingCountryKeys: try: country = pycountry.countries.get(alpha_3=countryKey) conutryAlpha2 = country.alpha_2 if conutryAlpha2 in coronaCasesDataDict.keys(): counter += 1 flopCountries.append({ "coronaCases": coronaCasesDataDict[conutryAlpha2], "healthSpending": healthSpendingDict[countryKey], "alpha_2": conutryAlpha2 }) if counter >= count: break except Exception as e: log.logWarning("Error while preprocessing sortedHealthSpending " + str(e)) return { "top": topCountries, "flop": flopCountries, }
def toolTip(self, dummyButton, dummyTile): """returns text and warning flag for button and text for tile for button and text for tile""" txt = 'toolTip is not defined for %s' % self.name logWarning(txt) return txt, True, ''
def toolTip(self, dummyButton, dummyTile): """returns text and warning flag for button and text for tile for button and text for tile""" txt = u'toolTip is not defined for %s' % self.name logWarning(txt) return txt, True, ''