NovaBryan/EVE_Dump
Log | Files | 📦 下载最新源码 (.zip) | Refs | README

eveCfg.py (62645B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\common\script\sys\eveCfg.py
      2 import cPickle
      3 import copy
      4 import logging
      5 import math
      6 import random
      7 import re
      8 import sqlite3
      9 import sys
     10 import types
     11 import blue
     12 import carbon.common.script.sys.cfg as sysCfg
     13 import carbon.common.script.util.format as formatUtil
     14 import eve.common.script.util.eveFormat as evefmtutil
     15 import evetypes
     16 import fsd.schemas.binaryLoader as fsdBinaryLoader
     17 import fsdlite
     18 import industry
     19 import localization
     20 import pytelemetry.zoning as telemetry
     21 import remotefilecache
     22 import uthread
     23 import utillib
     24 from caching.memoize import Memoize
     25 from carbon.common.script.sys.crowset import CRowset
     26 from characterdata.factions import iter_factions, get_faction_name
     27 from characterdata.npccharacters import get_npc_character_name, iter_npc_characters
     28 from eve.common.lib import appConst as const
     29 from eve.common.script.util import standingUtil
     30 from eveprefs import boot
     31 from evestations.const import DOOMHEIM_STATION, NPCStation, NPCStationProps
     32 from evestations.data import LOCATION_NPC_STATION_FORMATTER_NO_OP_NAME_RAW, LOCATION_NPC_STATION_FORMATTER_RAW, get_station_operation_name
     33 from inventorycommon.const import CONTAINER_GROUPS
     34 from inventorycommon.util import IsSubsystemFlagVisible, IsTypeContainer
     35 from marketgroups.data import MarketGroupObject
     36 from npcs.npccorporations import CorporationTicker, CorporationTickerProps, get_corporation_ticker_name, get_npc_corporation_name, iter_npc_corporation_ids, iter_npc_corporations
     37 from player_messaging import PromptResult
     38 from spacecomponents.common.helper import HasCargoBayComponent
     39 import eve.common.script.sys.idCheckers as idCheckers
     40 OWNER_AURA_IDENTIFIER = -1
     41 OWNER_SYSTEM_IDENTIFIER = -2
     42 logger = logging.getLogger(__name__)
     43 
     44 class Standings():
     45     __guid__ = 'eveCfg.Standings'
     46     __passbyvalue__ = 1
     47 
     48     def __init__(self, fromID, fromFactionID, fromCorpID, fromCharID, toID, toFactionID, toCorpID, toCharID):
     49         self.fromID, self.fromFactionID, self.fromCorpID, self.fromCharID, self.toID, self.toFactionID, self.toCorpID, self.toCharID = (fromID,
     50          fromFactionID,
     51          fromCorpID,
     52          fromCharID,
     53          toID,
     54          toFactionID,
     55          toCorpID,
     56          toCharID)
     57         self.faction = utillib.KeyVal(faction=0.0, corp=0.0, char=0.0)
     58         self.corp = utillib.KeyVal(faction=0.0, corp=0.0, char=0.0)
     59         self.char = utillib.KeyVal(faction=0.0, corp=0.0, char=0.0)
     60 
     61     def __str__(self):
     62         return 'Standing from %s toward %s: faction:(%s,%s,%s), corp:(%s,%s,%s), char:(%s,%s,%s)' % (self.fromID,
     63          self.toID,
     64          self.faction.faction,
     65          self.faction.corp,
     66          self.faction.char,
     67          self.corp.faction,
     68          self.corp.corp,
     69          self.corp.char,
     70          self.char.faction,
     71          self.char.corp,
     72          self.char.char)
     73 
     74     def __repr__(self):
     75         return self.__str__()
     76 
     77     def CanUseAgent(self, level, agentTypeID = None, noL1Check = 1):
     78         return CanUseAgent(level, agentTypeID, self.faction.char, self.corp.char, self.char.char, self.fromCorpID, self.fromFactionID, {}, noL1Check)
     79 
     80     def __getattr__(self, theKey):
     81         if theKey == 'minimum':
     82             m = None
     83             for each in (self.faction, self.corp, self.char):
     84                 for other in (each.faction, each.corp, each.char):
     85                     if other != 0.0 and (m is None or other < m):
     86                         m = other
     87 
     88             if m is None:
     89                 return 0.0
     90             return m
     91         if theKey == 'maximum':
     92             m = None
     93             for each in (self.faction, self.corp, self.char):
     94                 for other in (each.faction, each.corp, each.char):
     95                     if other != 0.0 and (m is None or other > m):
     96                         m = other
     97 
     98             if m is None:
     99                 return 0.0
    100             return m
    101         if theKey == 'direct':
    102             if self.fromID == self.fromFactionID:
    103                 tmp = self.faction
    104             elif self.fromID == self.fromCorpID:
    105                 tmp = self.corp
    106             elif self.fromID == self.fromCharID:
    107                 tmp = self.char
    108             if self.toID == self.toFactionID:
    109                 return tmp.faction
    110             elif self.toID == self.toCorpID:
    111                 return tmp.corp
    112             elif self.toID == self.toCharID:
    113                 return tmp.char
    114             else:
    115                 return 0.0
    116         else:
    117             if theKey == 'all':
    118                 return [(self.fromFactionID, self.toFactionID, self.faction.faction),
    119                  (self.fromFactionID, self.toCorpID, self.faction.corp),
    120                  (self.fromFactionID, self.toCharID, self.faction.char),
    121                  (self.fromCorpID, self.toFactionID, self.corp.faction),
    122                  (self.fromCorpID, self.toCorpID, self.corp.corp),
    123                  (self.fromCorpID, self.toCharID, self.corp.char),
    124                  (self.fromCharID, self.toFactionID, self.char.faction),
    125                  (self.fromCharID, self.toCorpID, self.char.corp),
    126                  (self.fromCharID, self.toCharID, self.char.char)]
    127             raise AttributeError(theKey)
    128 
    129 
    130 def CanUseAgent(level, agentTypeID, fac, coc, cac, fromCorpID, fromFactionID, skills, noL1Check = 1):
    131     if agentTypeID == const.agentTypeAura:
    132         return True
    133     elif level == 1 and agentTypeID != const.agentTypeResearchAgent and noL1Check:
    134         return 1
    135     m = (level - 1) * 2.0 - 1.0
    136     if boot.role == 'client':
    137         if not skills:
    138             mySkills = sm.GetService('skills').GetSkill
    139             for skillTypeID in (const.typeConnections, const.typeDiplomacy, const.typeCriminalConnections):
    140                 skillInfo = mySkills(skillTypeID)
    141                 if skillInfo:
    142                     skills[skillTypeID] = skillInfo
    143 
    144         unused, facBonus = standingUtil.GetStandingBonus(fac, fromFactionID, skills)
    145         unused, cocBonus = standingUtil.GetStandingBonus(coc, fromFactionID, skills)
    146         unused, cacBonus = standingUtil.GetStandingBonus(cac, fromFactionID, skills)
    147         if facBonus > 0.0:
    148             fac = (1.0 - (1.0 - fac / 10.0) * (1.0 - facBonus / 10.0)) * 10.0
    149         if cocBonus > 0.0:
    150             coc = (1.0 - (1.0 - coc / 10.0) * (1.0 - cocBonus / 10.0)) * 10.0
    151         if cacBonus > 0.0:
    152             cac = (1.0 - (1.0 - cac / 10.0) * (1.0 - cacBonus / 10.0)) * 10.0
    153     if max(fac, coc, cac) >= m and min(fac, coc, cac) > -2.0:
    154         if agentTypeID == const.agentTypeResearchAgent and coc < m - 2.0:
    155             return 0
    156         return 1
    157     else:
    158         return 0
    159 
    160 
    161 class EveDataConfig(sysCfg.DataConfig):
    162     __guid__ = 'svc.eveDataconfig'
    163     __replaceservice__ = 'dataconfig'
    164 
    165     def __init__(self):
    166         sysCfg.DataConfig.__init__(self)
    167 
    168     def _CreateConfig(self):
    169         return eveConfig
    170 
    171 
    172 class EveConfig(sysCfg.Config):
    173     __guid__ = 'util.EveConfig'
    174 
    175     def __init__(self):
    176         sysCfg.Config.__init__(self)
    177         self.fmtMapping[const.UE_OWNERID] = lambda value, value2: cfg.eveowners.Get(value).ownerName
    178         self.fmtMapping[const.UE_OWNERIDNICK] = lambda value, value2: cfg.eveowners.Get(value).ownerName.split(' ')[0]
    179         self.fmtMapping[const.UE_LOCID] = lambda value, value2: cfg.evelocations.Get(value).locationName
    180         self.fmtMapping[const.UE_TYPEID] = lambda value, value2: evetypes.GetName(value)
    181         self.fmtMapping[const.UE_TYPEID2] = lambda value, value2: evetypes.GetDescription(value)
    182         self.fmtMapping[const.UE_TYPEIDL] = lambda value, value2: cfg.FormatConvert(const.UE_LIST, [ (const.UE_TYPEID, x) for x in value ], value2)
    183         self.fmtMapping[const.UE_BPTYPEID] = lambda value, value2: evetypes.GetName(cfg.blueprints.Get(value).blueprintTypeID)
    184         self.fmtMapping[const.UE_GROUPID] = lambda value, value2: evetypes.GetGroupNameByGroup(value)
    185         self.fmtMapping[const.UE_GROUPID2] = lambda value, value2: ''
    186         self.fmtMapping[const.UE_CATID] = lambda value, value2: evetypes.GetCategoryNameByCategory(value)
    187         self.fmtMapping[const.UE_CATID2] = lambda value, value2: ''
    188         self.fmtMapping[const.UE_AMT] = lambda value, value2: formatUtil.FmtAmt(value)
    189         self.fmtMapping[const.UE_AMT2] = lambda value, value2: evefmtutil.FmtISK(value)
    190         self.fmtMapping[const.UE_AMT3] = lambda value, value2: evefmtutil.FmtISK(value)
    191         self.fmtMapping[const.UE_ISK] = lambda value, value2: evefmtutil.FmtISK(value)
    192         self.fmtMapping[const.UE_AUR] = lambda value, value2: evefmtutil.FmtAUR(value)
    193         self.fmtMapping[const.UE_DIST] = lambda value, value2: formatUtil.FmtDist(value)
    194         self.fmtMapping[const.UE_TYPEIDANDQUANTITY] = self.__FormatTypeIDAndQuantity
    195         self.crystalgroups = []
    196         self.rawCelestialCache = {}
    197         self.stationLocalizationData = {}
    198         self._mapRegionCache = None
    199         self._mapConstellationCache = None
    200         self._mapSystemCache = None
    201         self._mapJumpCache = None
    202         self._mapSolarSystemContentCache = None
    203         self._map_stargate_id_mapping = None
    204         self.mapObjectsDb = None
    205         self.staticMapDb = None
    206 
    207     def Release(self):
    208         sysCfg.Config.Release(self)
    209         self.graphics = None
    210         self.graphicEffects = None
    211         self.eveowners = None
    212         self.evelocations = None
    213         self.rawCelestialCache = None
    214         self.corptickernames = None
    215         self.allianceshortnames = None
    216         self.crystalgroups = None
    217         self._ReleaseMapCache()
    218         self.planetResources = None
    219         self.planetBlacklist = None
    220         self.overviewDefaults = None
    221         self.overviewDefaultGroups = None
    222         self.positions = None
    223         self.messages = None
    224         self.mapObjectsDb = None
    225 
    226     def _ReleaseMapCache(self):
    227         self._mapRegionCache = None
    228         self._mapConstellationCache = None
    229         self._mapSystemCache = None
    230         self._mapJumpCache = None
    231         self._mapSolarSystemContentCache = None
    232         self._map_stargate_id_mapping = None
    233 
    234     def GetStartupData(self):
    235         sysCfg.Config.GetStartupData(self)
    236         if self.IsClient():
    237             self.messages = _LoadMessagesFromFSD()
    238 
    239     def IsClient(self):
    240         return boot.role == 'client'
    241 
    242     @telemetry.ZONE_METHOD
    243     def GetMessage(self, key, dict = None, onNotFound = 'return', onDictMissing = 'error', languageID = None):
    244         try:
    245             msg = self.messages[key]
    246         except KeyError:
    247             return self._GetContentForMissingMessage(key, dict, languageID=languageID)
    248 
    249         bodyID, titleID = msg.bodyID, msg.titleID
    250         title, text = self._GetTitleAndTextForMessage(dict, titleID, bodyID, languageID=languageID)
    251         return utillib.KeyVal(text=text, title=title, type=msg.dialogType, audio=msg.urlAudio, icon=msg.urlIcon, suppress=msg.suppressable, closable=msg.closable)
    252 
    253     @telemetry.ZONE_METHOD
    254     def GetMessageTypeAndText(self, key, paramDict, onNotFound = 'return', onDictMissing = 'error', languageID = None):
    255         try:
    256             msg = self.messages[key]
    257         except KeyError:
    258             return self._GetContentForMissingMessage(key, paramDict, languageID=languageID)
    259 
    260         for k, v in paramDict.iteritems():
    261             if type(v) != types.TupleType:
    262                 continue
    263             value2 = None
    264             if len(v) >= 3:
    265                 value2 = v[2]
    266             paramDict[k] = self.FormatConvert(v[0], v[1], value2)
    267 
    268         text = localization.GetByMessageID(msg.bodyID, languageID=languageID, **paramDict)
    269         return utillib.KeyVal(text=text, type=msg.dialogType)
    270 
    271     def _GetContentForMissingMessage(self, key, paramDict, languageID):
    272         if key != 'ErrMessageNotFound':
    273             return self.GetMessage('ErrMessageNotFound', {'msgid': key,
    274              'args': repr(paramDict)}, languageID=languageID)
    275         else:
    276             return utillib.KeyVal(text='Could not find message with key ' + key, title='Message not found', type='fatal', audio='', icon='', suppress=False)
    277 
    278     def _GetTitleAndTextForMessage(self, paramDict, titleID, bodyID, languageID):
    279         if paramDict is not None and paramDict != -1:
    280             paramDict = self.__prepdict(paramDict)
    281             title = localization.GetByMessageID(titleID, languageID=languageID, **paramDict) if titleID is not None else None
    282             text = localization.GetByMessageID(bodyID, languageID=languageID, **paramDict) if bodyID is not None else None
    283         else:
    284             title = localization.GetByMessageID(titleID, languageID=languageID) if titleID is not None else None
    285             text = localization.GetByMessageID(bodyID, languageID=languageID) if bodyID is not None else None
    286         return (title, text)
    287 
    288     def GetRawMessageTitle(self, key):
    289         msg = self.messages.get(key, None)
    290         if msg:
    291             if msg.titleID is not None:
    292                 return localization._GetRawByMessageID(msg.titleID)
    293 
    294     @Memoize
    295     def GetSuppressValueForMessage(self, msgKey, msgParams):
    296         constMapping = {'ID_YES': PromptResult.YES,
    297          'ID_NO': PromptResult.NO,
    298          False: None,
    299          True: True}
    300         try:
    301             return constMapping[cfg.GetMessage(msgKey, msgParams).suppress]
    302         except Exception:
    303             return
    304 
    305     def IsChargeCompatible(self, item):
    306         if not item[const.ixSingleton]:
    307             return 0
    308         else:
    309             return item[const.ixGroupID] in self.__chargecompatiblegroups__
    310 
    311     def IsContainer(self, item, doSpaceComponentCheck = True):
    312         if not item.singleton:
    313             return False
    314         elif IsTypeContainer(item.typeID):
    315             return True
    316         elif doSpaceComponentCheck:
    317             return idCheckers.IsSolarSystem(item.locationID) and HasCargoBayComponent(item.typeID)
    318         else:
    319             return False
    320 
    321     def IsCargoContainer(self, item):
    322         return item.singleton and item.groupID in CONTAINER_GROUPS
    323 
    324     def AppGetStartupData(self):
    325         self.LoadCfgData()
    326 
    327     def LoadSqliteDB(self, fileName):
    328         res = blue.ResFile()
    329         if boot.role == 'client' and blue.pyos.packaged:
    330             mapObjectsResPath = blue.paths.ResolvePath('bin:/staticdata/{fileName}.db'.format(fileName=fileName))
    331         else:
    332             mapObjectsResPath = blue.paths.ResolvePath('res:/staticdata/{fileName}.db'.format(fileName=fileName))
    333         if not res.Open(mapObjectsResPath):
    334             cfg.LogError('Could not find file %s.' % mapObjectsResPath)
    335         else:
    336             dbConnection = sqlite3.connect(mapObjectsResPath)
    337             dbConnection.row_factory = sqlite3.Row
    338         res.Close()
    339         return dbConnection
    340 
    341     def LoadCfgData(self):
    342         cfg.LogNotice('App LoadCfgData')
    343         remotefilecache.prefetch_folder('res:/staticdata')
    344         sysCfg.Config.LoadCfgData(self)
    345         self.fsdDustIcons = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/dustIcons.static')
    346         self.messages = _LoadMessagesFromFSD()
    347         cfg.LogNotice('Done Loading static data')
    348         if self.IsClient():
    349             self.mapObjectsDb = self.LoadSqliteDB('mapObjects')
    350             self.mapCelestialLocationCache = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/locationCache.static')
    351             self.mapFactionsOwningSolarSystems = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/factionsOwningSolarSystems.static', 'res:/staticdata/factionsOwningSolarSystems.schema', optimize=False)
    352             infoBubbleData = fsdlite.EveStorage(data='infoBubbleElements', cache='infoBubbles.static')
    353             self.infoBubbleElements = {int(k):v for k, v in infoBubbleData['infoBubbleElements'].items()}
    354             self.infoBubbleFactions = {int(k):v for k, v in infoBubbleData['infoBubbleFactions'].items()}
    355             self.infoBubbleGroups = {int(k):v for k, v in infoBubbleData['infoBubbleGroups'].items()}
    356             self.infoBubbleTypeElements = {int(k):v['elements'] for k, v in infoBubbleData['infoBubbleTypeElements'].items()}
    357             self.infoBubbleTypeBonuses = {int(k):v for k, v in infoBubbleData['infoBubbleTypeBonuses'].items()}
    358             self.certificates = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/certificates.static', optimize=False)
    359             self.LoadTypesUsedByBlueprints()
    360         else:
    361             self.securityForSystemsWithPlanetsInLocation = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/securityForSystemsWithPlanetsInLocation.static')
    362             self.staticMapDb = self.LoadSqliteDB('staticMap')
    363         self.LoadStationLocalizationData()
    364         cfg.LogNotice('Done loading sqlite data')
    365         self.LoadPlanetBlacklist()
    366         self.LoadCrpTickerNames()
    367         self.LoadEveOwners()
    368         self.LoadEveLocations()
    369         cfg.LogNotice('Done loading owner and location data')
    370         self.blueprints = industry.BlueprintStorage()
    371         allianceshortnameRowHeader = blue.DBRowDescriptor((('allianceID', const.DBTYPE_I4), ('shortName', const.DBTYPE_WSTR)))
    372         self.allianceshortnameRowset = CRowset(allianceshortnameRowHeader, [])
    373         self.allianceshortnames = sysCfg.Recordset(AllShortNames, 'allianceID', 'GetAllianceShortNamesEx', 'GetMultiAllianceShortNamesEx')
    374         self.ConvertData(self.allianceshortnameRowset, self.allianceshortnames)
    375         positionRowHeader = blue.DBRowDescriptor((('itemID', const.DBTYPE_I8),
    376          ('x', const.DBTYPE_R5),
    377          ('y', const.DBTYPE_R5),
    378          ('z', const.DBTYPE_R5),
    379          ('yaw', const.DBTYPE_R4),
    380          ('pitch', const.DBTYPE_R4),
    381          ('roll', const.DBTYPE_R4)))
    382         positionRowset = CRowset(positionRowHeader, [])
    383         self.positions = sysCfg.Recordset(Position, 'itemID', 'GetPositionEx', 'GetPositionsEx')
    384         self.ConvertData(positionRowset, self.positions)
    385         cfg.LogNotice('Done loading alliance and position data')
    386         if self.IsClient():
    387             self._averageMarketPrice = {}
    388             uthread.new(self.GetAveragePricesThread)
    389         else:
    390             self._averageMarketPrice = self.GetConfigSvc().GetAverageMarketPrices()
    391         cfg.LogNotice('Done loading market data')
    392         self.__chargecompatiblegroups__ = (const.groupFrequencyMiningLaser,
    393          const.groupEnergyWeapon,
    394          const.groupProjectileWeapon,
    395          const.groupMissileLauncher,
    396          const.groupCapacitorBooster,
    397          const.groupHybridWeapon,
    398          const.groupScanProbeLauncher,
    399          const.groupComputerInterfaceNode,
    400          const.groupMissileLauncherBomb,
    401          const.groupMissileLauncherCruise,
    402          const.groupMissileLauncherDefender,
    403          const.groupMissileLauncherAssault,
    404          const.groupMissileLauncherSiege,
    405          const.groupMissileLauncherHeavy,
    406          const.groupMissileLauncherHeavyAssault,
    407          const.groupMissileLauncherRocket,
    408          const.groupMissileLauncherStandard,
    409          const.groupMissileLauncherXLTorpedo,
    410          const.groupMissileLauncherXLCruise,
    411          const.groupMissileLauncherRapidTorpedo,
    412          const.groupMissileLauncherFestival,
    413          const.groupMissileLauncherDot,
    414          const.groupBubbleProbeLauncher,
    415          const.groupSensorBooster,
    416          const.groupStructureECM,
    417          const.groupRemoteSensorBooster,
    418          const.groupRemoteSensorDamper,
    419          const.groupTrackingComputer,
    420          const.groupTrackingDisruptor,
    421          const.groupTrackingLink,
    422          const.groupWarpDisruptFieldGenerator,
    423          const.groupFueledShieldBooster,
    424          const.groupFueledArmorRepairer,
    425          const.groupSurveyProbeLauncher,
    426          const.groupMissileLauncherRapidHeavy,
    427          const.groupDroneTrackingModules,
    428          const.groupMissileGuidanceComputer,
    429          const.groupStructureAreaMissileLauncher,
    430          const.groupStructureECMScript,
    431          const.groupStructureFlakMissileLauncher,
    432          const.groupStructureMissileLauncher,
    433          const.groupFlexArmorHardener,
    434          const.groupFlexShieldHardener,
    435          const.groupFueledRemoteShieldBooster,
    436          const.groupFueledRemoteArmorRepairer,
    437          const.groupCommandBurstModule,
    438          const.groupStructureWarpDisruptor,
    439          const.groupStructureFestivalLauncher,
    440          const.groupPrecursorTurret,
    441          const.groupStasisNullifier,
    442          const.groupChainLightningTurret,
    443          const.groupStructureDefenseBattery)
    444 
    445     def LoadTypesUsedByBlueprints(self):
    446         res = blue.ResFile()
    447         resPath = 'res:/staticdata/blueprintsByMaterialTypeIDs.pickle'
    448         if not res.open('%s' % resPath):
    449             self.LogError('Could not load Blueprints by material Cache data file: %s' % resPath)
    450         else:
    451             try:
    452                 pickleData = res.Read()
    453                 self.blueprintsByMaterialTypeIDs = cPickle.loads(pickleData)
    454             finally:
    455                 res.Close()
    456 
    457     def LoadPlanetBlacklist(self):
    458         self.planetBlacklist = self.GetConfigSvc().GetBlackListedPlanets()
    459 
    460     def LoadCrpTickerNames(self):
    461         self.corptickernames = sysCfg.Recordset(CrpTickerNames, 'corporationID', 'GetCorpTickerNamesEx', 'GetMultiCorpTickerNamesEx')
    462         tickers = []
    463         for corporationID in iter_npc_corporation_ids():
    464             tickers.append(CorporationTicker(corporationID=corporationID, tickerName=get_corporation_ticker_name(corporationID), shape1=None, shape2=None, shape3=None, color1=None, color2=None, color3=None))
    465 
    466         self.corptickernames.PopulateDataset(CorporationTickerProps, tickers)
    467 
    468     @telemetry.ZONE_METHOD
    469     def __prepdict(self, dict):
    470         dict = copy.deepcopy(dict)
    471         if charsession:
    472             for k, v in {'session.char': (const.UE_OWNERID, charsession.charid),
    473              'session.nick': (const.UE_OWNERIDNICK, charsession.charid),
    474              'session.corp': (const.UE_OWNERID, charsession.corpid),
    475              'session.station': (const.UE_LOCID, charsession.stationid),
    476              'session.solarsystem': (const.UE_LOCID, charsession.solarsystemid2),
    477              'session.constellation': (const.UE_LOCID, charsession.constellationid),
    478              'session.region': (const.UE_LOCID, charsession.regionid),
    479              'session.location': (const.UE_LOCID, charsession.locationid)}.iteritems():
    480                 if v[1] is not None:
    481                     dict[k] = v
    482 
    483         for k, v in dict.iteritems():
    484             if type(v) != types.TupleType:
    485                 continue
    486             value2 = None
    487             if len(v) >= 3:
    488                 value2 = v[2]
    489             dict[k] = self.FormatConvert(v[0], v[1], value2)
    490 
    491         return dict
    492 
    493     def __FormatTypeIDAndQuantity(self, typeID, quantity):
    494         return localization.GetByLabel('UI/Common/QuantityAndItem', quantity=quantity, item=typeID)
    495 
    496     def GetAveragePricesThread(self):
    497         blue.pyos.synchro.SleepWallclock(2000)
    498         self._averageMarketPrice = self.GetConfigSvc().GetAverageMarketPrices()
    499 
    500     def GetCrystalGroups(self):
    501         if not self.crystalgroups:
    502             crystalGroupIDs = [ groupID for groupID in evetypes.GetGroupIDsByCategory(const.categoryCharge) if localization.CleanImportantMarkup(evetypes.GetGroupNameByGroup(groupID, 'en')).endswith('Crystal') ]
    503             self.crystalgroups.extend(crystalGroupIDs)
    504             scriptGroupIDs = [ groupID for groupID in evetypes.GetGroupIDsByCategory(const.categoryCharge) if localization.CleanImportantMarkup(evetypes.GetGroupNameByGroup(groupID, 'en')).endswith('Script') ]
    505             self.crystalgroups.extend(scriptGroupIDs)
    506         return self.crystalgroups
    507 
    508     def GetLocationWormholeClass(self, solarSystemID):
    509         system = self.mapSystemCache[solarSystemID]
    510         return getattr(system, 'wormholeClassID', const.INVALID_WORMHOLE_CLASS_ID)
    511 
    512     def GetNebula(self, solarSystemID, constellationID, regionID, returnPath = True):
    513         if returnPath:
    514             return self.mapRegionCache.Get(regionID).nebulaPath
    515         else:
    516             return self.mapRegionCache.Get(regionID).nebulaID
    517 
    518     @telemetry.ZONE_METHOD
    519     def LoadEveOwners(self):
    520         rowDescriptor = self.GetOwnersRowDescriptor()
    521         self.eveowners = sysCfg.Recordset(EveOwners, 'ownerID', 'GetOwnersEx', 'GetMultiOwnersEx')
    522         self.eveowners.header = ['ownerID',
    523          'ownerName',
    524          'typeID',
    525          'gender',
    526          'ownerNameID']
    527         for factionID, faction in iter_factions():
    528             if self.IsClient():
    529                 factionName = get_faction_name(factionID, faction, important=True)
    530             else:
    531                 factionName = get_faction_name(factionID, faction)
    532             self.eveowners.data[factionID] = blue.DBRow(rowDescriptor, [factionID,
    533              factionName,
    534              const.typeFaction,
    535              None,
    536              faction.nameID])
    537 
    538         for corporationID, corporation in iter_npc_corporations():
    539             if self.IsClient():
    540                 corporationName = get_npc_corporation_name(corporationID, corporation, important=True)
    541             else:
    542                 corporationName = get_npc_corporation_name(corporationID, corporation)
    543             self.eveowners.data[corporationID] = blue.DBRow(rowDescriptor, [corporationID,
    544              corporationName,
    545              const.typeCorporation,
    546              None,
    547              corporation.nameID])
    548 
    549         for charID, character in iter_npc_characters():
    550             if self.IsClient():
    551                 important = True
    552             else:
    553                 important = False
    554             npcName = get_npc_character_name(charID, character, important=important)
    555             try:
    556                 self.eveowners.data[charID] = blue.DBRow(rowDescriptor, [charID,
    557                  npcName,
    558                  const.typeCharacter,
    559                  character.gender,
    560                  character.nameID])
    561             except KeyError:
    562                 self.LogError('ERROR: NPC missing from eveowner table - PLEASE FIX THIS!', charID, npcName)
    563 
    564         self.eveowners.data[1] = blue.DBRow(rowDescriptor, [1,
    565          localization.GetByLabel(OWNER_NAME_OVERRIDES[OWNER_SYSTEM_IDENTIFIER]),
    566          0,
    567          None,
    568          None])
    569 
    570     def UpdateEveOwnerName(self, ownerID, ownerName):
    571         owner = self.eveowners.Get(ownerID)
    572         self.eveowners.data[ownerID] = blue.DBRow(self.GetOwnersRowDescriptor(), [ownerID,
    573          ownerName,
    574          owner.typeID,
    575          owner.gender,
    576          owner.ownerNameID])
    577 
    578     def GetOwnersRowDescriptor(self):
    579         return blue.DBRowDescriptor((('ownerID', const.DBTYPE_I4),
    580          ('ownerName', const.DBTYPE_WSTR),
    581          ('typeID', const.DBTYPE_I4),
    582          ('gender', const.DBTYPE_I2),
    583          ('ownerNameID', const.DBTYPE_I4)))
    584 
    585     def GetLocationRowDescriptor(self):
    586         return blue.DBRowDescriptor((('locationID', const.DBTYPE_I8),
    587          ('locationName', const.DBTYPE_WSTR),
    588          ('solarSystemID', const.DBTYPE_I8),
    589          ('x', const.DBTYPE_R5),
    590          ('y', const.DBTYPE_R5),
    591          ('z', const.DBTYPE_R5),
    592          ('locationNameID', const.DBTYPE_I4)))
    593 
    594     @property
    595     def mapRegionCache(self):
    596         if not self._mapRegionCache:
    597             self._mapRegionCache = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/regions.static', 'res:/staticdata/regions.schema', optimize=False)
    598         return self._mapRegionCache
    599 
    600     @property
    601     def mapConstellationCache(self):
    602         if not self._mapConstellationCache:
    603             self._mapConstellationCache = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/constellations.static', 'res:/staticdata/constellations.schema', optimize=False)
    604         return self._mapConstellationCache
    605 
    606     @property
    607     def mapSystemCache(self):
    608         if not self._mapSystemCache:
    609             self._mapSystemCache = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/systems.static', 'res:/staticdata/systems.schema', optimize=False)
    610         return self._mapSystemCache
    611 
    612     @property
    613     def mapJumpCache(self):
    614         if not self._mapJumpCache:
    615             self._mapJumpCache = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/jumps.static', 'res:/staticdata/jumps.schema', optimize=False)
    616         return self._mapJumpCache
    617 
    618     @property
    619     def mapSolarSystemContentCache(self):
    620         if not self._mapSolarSystemContentCache:
    621             self._mapSolarSystemContentCache = fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/solarSystemContent.static')
    622         return self._mapSolarSystemContentCache
    623 
    624     @property
    625     def mapStargateIdMappingCache(self):
    626         if not self._map_stargate_id_mapping:
    627             self._map_stargate_id_mapping = {}
    628             for solarSystemID, solarSystem in self.mapSolarSystemContentCache.iteritems():
    629                 for stargate_id, stargate in solarSystem.stargates.iteritems():
    630                     self._map_stargate_id_mapping[stargate_id] = stargate.destination
    631                     self._map_stargate_id_mapping[stargate.destination] = stargate_id
    632 
    633         return self._map_stargate_id_mapping
    634 
    635     @telemetry.ZONE_METHOD
    636     def LoadEveLocations(self):
    637         rowDescriptor = self.GetLocationRowDescriptor()
    638         self.evelocations = sysCfg.Recordset(EveLocations, 'locationID', 'GetLocationsEx', 'GetMultiLocationsEx', 'GetLocationsLocal')
    639         self.evelocations.header = ['locationID',
    640          'locationName',
    641          'solarSystemID',
    642          'x',
    643          'y',
    644          'z',
    645          'locationNameID']
    646         for regionID, region in self.mapRegionCache.iteritems():
    647             regionName = localization.GetImportantByMessageID(region.nameID)
    648             self.evelocations.data[regionID] = blue.DBRow(rowDescriptor, [regionID,
    649              regionName,
    650              None,
    651              region.center[0],
    652              region.center[1],
    653              region.center[2],
    654              region.nameID])
    655 
    656         for constellationID, constellation in self.mapConstellationCache.iteritems():
    657             constellationName = localization.GetImportantByMessageID(constellation.nameID)
    658             self.evelocations.data[constellationID] = blue.DBRow(rowDescriptor, [constellationID,
    659              constellationName,
    660              None,
    661              constellation.center.x,
    662              constellation.center.y,
    663              constellation.center.z,
    664              constellation.nameID])
    665 
    666         for solarSystemID, solarSystem in self.mapSystemCache.iteritems():
    667             solarSystemName = localization.GetImportantByMessageID(solarSystem.nameID)
    668             self.evelocations.data[solarSystemID] = blue.DBRow(rowDescriptor, [solarSystemID,
    669              solarSystemName,
    670              solarSystemID,
    671              solarSystem.center.x,
    672              solarSystem.center.y,
    673              solarSystem.center.z,
    674              solarSystem.nameID])
    675 
    676         self.LoadOldStationsInfo()
    677         self.LoadNPCStations()
    678         localStations = {}
    679         if self.IsClient():
    680             localStations = self.PrimeStationCelestials()
    681         for row in self.stations:
    682             if self.IsClient() and row.stationID in localStations:
    683                 stationName = self.GetNPCStationNameFromLocalRow(localStations[row.stationID])
    684             else:
    685                 stationName = row.stationName
    686             stationName = unicode(stationName)
    687             self.evelocations.data[row.stationID] = blue.DBRow(rowDescriptor, [row.stationID,
    688              stationName,
    689              row.solarSystemID,
    690              row.x,
    691              row.y,
    692              row.z,
    693              None])
    694 
    695         self.LoadStationLocalizationData()
    696 
    697     @telemetry.ZONE_METHOD
    698     def LoadStationLocalizationData(self):
    699         if self.IsClient():
    700             db = self.mapObjectsDb
    701             key = 'stationID'
    702             sql = 'SELECT stationID, celestialIndex, orbitIndex, useOperationName FROM npcStations'
    703         else:
    704             db = self.staticMapDb
    705             key = 'id'
    706             sql = 'SELECT id, celestialIndex, orbitIndex, useOperationName FROM NpcStations'
    707         cursor = db.execute(sql)
    708         self.stationLocalizationData = {row[key]:(row['celestialIndex'], row['orbitIndex'], row['useOperationName']) for row in cursor}
    709 
    710     def LoadNPCStations(self):
    711         npcStations = []
    712         for stationID, data in self.mapSolarSystemContentCache.npcStations.iteritems():
    713             position = data.position
    714             npcStations.append(NPCStation(stationID=stationID, stationName=data.stationName, x=position[0], y=position[1], z=position[2], stationTypeID=data.typeID, solarSystemID=data.solarSystemID, orbitID=data.orbitID, ownerID=data.ownerID))
    715 
    716         npcStations.append(DOOMHEIM_STATION)
    717         self.stations = sysCfg.Recordset(sysCfg.Row, 'stationID', (NPCStationProps, npcStations))
    718 
    719     def LoadOldStationsInfo(self):
    720         self.oldStations = sysCfg.Recordset(sysCfg.Row, 'stationID')
    721         if self.IsClient():
    722             uthread.new(self._LoadOldStationsInfo)
    723         else:
    724             self._LoadOldStationsInfo()
    725 
    726     def _LoadOldStationsInfo(self):
    727         oldStations = self.GetConfigSvc().GetOldStationData()
    728         if oldStations:
    729             self.oldStations = sysCfg.Recordset(sysCfg.Row, 'stationID', (oldStations.columns, oldStations.values()))
    730 
    731     @telemetry.ZONE_METHOD
    732     def PrimeStationCelestials(self):
    733         if boot.role != 'client':
    734             raise RuntimeError('PrimeStationCelestials::Non-client based call to PrimeStationCelestials!')
    735         sql = 'SELECT *\n                   FROM npcStations\n              '
    736         stations = self.mapObjectsDb.execute(sql)
    737         localStations = {}
    738         primeList = []
    739         for station in stations:
    740             if station['orbitID'] is not None:
    741                 primeList.append(station['orbitID'])
    742             localStations[station['stationID']] = station
    743 
    744         cfg.evelocations.Prime(primeList)
    745         return localStations
    746 
    747     @telemetry.ZONE_METHOD
    748     def GetMarketGroup(self, marketGroupID):
    749         if boot.role != 'client':
    750             raise RuntimeError('GetMarketGroup::Non-clientbased call made!!')
    751         return MarketGroupObject(marketGroupID)
    752 
    753     @telemetry.ZONE_METHOD
    754     def GetLocationsLocalBySystem(self, solarSystemID, requireLocalizedTexts = True, doYields = False):
    755         if boot.role != 'client':
    756             raise RuntimeError('GetLocationsLocalBySystem::Non-clientbased call made!!')
    757         solarSystemObjectRowDescriptor = blue.DBRowDescriptor((('groupID', const.DBTYPE_I4),
    758          ('typeID', const.DBTYPE_I4),
    759          ('itemID', const.DBTYPE_I8),
    760          ('itemName', const.DBTYPE_WSTR),
    761          ('locationID', const.DBTYPE_I4),
    762          ('orbitID', const.DBTYPE_I4),
    763          ('connector', const.DBTYPE_BOOL),
    764          ('x', const.DBTYPE_R5),
    765          ('y', const.DBTYPE_R5),
    766          ('z', const.DBTYPE_R5),
    767          ('celestialIndex', const.DBTYPE_I4),
    768          ('orbitIndex', const.DBTYPE_I4)))
    769         sql = ' SELECT *\n                    FROM celestials\n                   WHERE solarSystemID = %d' % solarSystemID
    770         data = []
    771         rs = self.mapObjectsDb.execute(sql)
    772         for row in rs:
    773             try:
    774                 celestialName = self.GetCelestialNameFromLocalRow(row, requireLocalizedTexts)
    775                 data.append(blue.DBRow(solarSystemObjectRowDescriptor, [row['groupID'],
    776                  row['typeID'],
    777                  row['celestialID'],
    778                  celestialName,
    779                  solarSystemID,
    780                  row['orbitID'],
    781                  0,
    782                  row['x'],
    783                  row['y'],
    784                  row['z'],
    785                  row['celestialIndex'],
    786                  row['orbitIndex']]))
    787             except IndexError as e:
    788                 rowContents = 'Row: '
    789                 if row:
    790                     rowContents = ', '.join([ '%s=%s' % (key, row[key]) for key in row.keys() ])
    791                 error = 'GetLocationsLocalBySystem: Failed getting local celestial data!\nRow is: %s\nError is: %s' % (rowContents, e)
    792                 self.LogError(error)
    793 
    794             if doYields:
    795                 blue.synchro.Yield()
    796 
    797         sql = '\n                SELECT *\n                  FROM npcStations\n                 WHERE solarSystemID = %d\n              ' % solarSystemID
    798         rs = self.mapObjectsDb.execute(sql)
    799         for row in rs:
    800             try:
    801                 celestialName = self.GetNPCStationNameFromLocalRow(row, requireLocalizedTexts)
    802                 data.append(blue.DBRow(solarSystemObjectRowDescriptor, [evetypes.GetGroupID(row['typeID']),
    803                  row['typeID'],
    804                  row['stationID'],
    805                  celestialName,
    806                  solarSystemID,
    807                  row['orbitID'],
    808                  0,
    809                  row['x'],
    810                  row['y'],
    811                  row['z'],
    812                  row['celestialIndex'],
    813                  row['orbitIndex']]))
    814             except IndexError as e:
    815                 rowContents = 'Row: '
    816                 if row:
    817                     rowContents = ', '.join([ '%s=%s' % (key, row[key]) for key in row.keys() ])
    818                 error = 'GetLocationsLocalBySystem: Failed getting local station data!\nRow is: %s\nError is: %s' % (rowContents, e)
    819                 self.LogError(error)
    820 
    821             if doYields:
    822                 blue.synchro.Yield()
    823 
    824         data = CRowset(solarSystemObjectRowDescriptor, data)
    825         return data
    826 
    827     @telemetry.ZONE_METHOD
    828     def GetLocationsLocal(self, keys):
    829         if boot.role != 'client':
    830             raise RuntimeError('GetLocationsLocal::Non-clientbased call made!!')
    831         rowDescriptor = self.GetLocationRowDescriptor()
    832         data = []
    833         keyString = ','.join([ str(x) for x in keys ])
    834         sql = 'SELECT *\n                   FROM celestials\n                  WHERE celestialID IN (%s)' % keyString
    835         rs = self.mapObjectsDb.execute(sql)
    836         for row in rs:
    837             celestialNameData = self._GetCelestialNameDataFromLocalRow(row)
    838             self.rawCelestialCache[row['celestialID']] = celestialNameData
    839             celestialName = localization.GetImportantByLabel(celestialNameData[0], **celestialNameData[1])
    840             data.append(blue.DBRow(rowDescriptor, [row['celestialID'],
    841              celestialName,
    842              row['solarSystemID'],
    843              row['x'],
    844              row['y'],
    845              row['z'],
    846              None]))
    847 
    848         data = CRowset(rowDescriptor, data)
    849         return (data.columns, data)
    850 
    851     @telemetry.ZONE_METHOD
    852     def GetNPCStationNameFromLocalRow(self, row, requireLocalizedTexts = True):
    853         orbitID = row['orbitID']
    854         if row['celestialIndex'] is None:
    855             orbitID = row['solarSystemID']
    856         if not requireLocalizedTexts:
    857             return ''
    858         if row['useOperationName']:
    859             labelPath = 'UI/Locations/LocationNPCStationFormatter'
    860             operationName = get_station_operation_name(row['operationID'])
    861             operationNameEN = get_station_operation_name(row['operationID'], localization.const.LOCALE_SHORT_ENGLISH)
    862         else:
    863             labelPath = 'UI/Locations/LocationNPCStationFormatter_NoOpName'
    864             operationName = ''
    865             operationNameEN = ''
    866         locName = localization.GetByLabel(labelPath, orbitID=orbitID, corporationID=row['ownerID'], operationName=operationName)
    867         locNameEN = localization.GetByLabel(labelPath, localization.const.LOCALE_SHORT_ENGLISH, orbitID=orbitID, corporationID=row['ownerID'], operationName=operationNameEN)
    868         return localization.FormatImportantString(locName, locNameEN)
    869 
    870     def GetNpcStationName(self, stationID, solarSystemID, ownerID, operationID, languageID = None):
    871         celestialIndex, orbitIndex, useOperationName = self.stationLocalizationData[stationID]
    872         if celestialIndex is None:
    873             orbit_name = None
    874         elif orbitIndex is not None:
    875             orbit_name = localization.GetByLabel('UI/Locations/LocationMoonFormatter', solarSystemID=solarSystemID, romanCelestialIndex=formatUtil.IntToRoman(celestialIndex), orbitIndex=orbitIndex, languageID=languageID)
    876         else:
    877             orbit_name = localization.GetByLabel('UI/Locations/LocationPlanetFormatter', solarSystemID=solarSystemID, romanCelestialIndex=formatUtil.IntToRoman(celestialIndex), languageID=languageID)
    878         corp = self.eveowners.Get(ownerID)
    879         corp_name = corp.GetRawName(languageID=languageID)
    880         operation_name = get_station_operation_name(operationID, languageID)
    881         if useOperationName:
    882             return localization.GetByLabel(LOCATION_NPC_STATION_FORMATTER_RAW, orbitName=orbit_name, npcOrganizationName=corp_name, operationName=operation_name)
    883         return localization.GetByLabel(LOCATION_NPC_STATION_FORMATTER_NO_OP_NAME_RAW, orbitName=orbit_name, npcOrganizationName=corp_name)
    884 
    885     @telemetry.ZONE_METHOD
    886     def _GetCelestialNameDataFromLocalRow(self, row):
    887         celestialGroupID = row['groupID']
    888         celestialNameID = row['celestialNameID']
    889         celestialNameData = (None, None)
    890         if celestialNameID is not None and celestialGroupID != const.groupStargate:
    891             celestialNameData = ('UI/Util/GenericText', {'text': celestialNameID})
    892         elif celestialGroupID == const.groupAsteroidBelt:
    893             celestialNameData = ('UI/Locations/LocationAsteroidBeltFormatter', {'solarSystemID': row['solarSystemID'],
    894               'romanCelestialIndex': formatUtil.IntToRoman(row['celestialIndex']),
    895               'typeID': row['typeID'],
    896               'orbitIndex': row['orbitIndex']})
    897         elif celestialGroupID == const.groupMoon:
    898             celestialNameData = ('UI/Locations/LocationMoonFormatter', {'solarSystemID': row['solarSystemID'],
    899               'romanCelestialIndex': formatUtil.IntToRoman(row['celestialIndex']),
    900               'orbitIndex': row['orbitIndex']})
    901         elif celestialGroupID == const.groupPlanet:
    902             celestialNameData = ('UI/Locations/LocationPlanetFormatter', {'solarSystemID': row['solarSystemID'],
    903               'romanCelestialIndex': formatUtil.IntToRoman(row['celestialIndex'])})
    904         elif celestialGroupID == const.groupStargate:
    905             celestialNameData = ('UI/Locations/LocationStargateFormatter', {'destinationSystemID': row['celestialNameID']})
    906         elif celestialGroupID == const.groupSun:
    907             celestialNameData = ('UI/Locations/LocationStarFormatter', {'solarSystemID': row['solarSystemID']})
    908         return celestialNameData
    909 
    910     @telemetry.ZONE_METHOD
    911     def GetCelestialNameFromLocalRow(self, row, requireLocalizedTexts = True):
    912         if not requireLocalizedTexts:
    913             return ''
    914         lbl, kwargs = self._GetCelestialNameDataFromLocalRow(row)
    915         if lbl:
    916             return localization.GetByLabel(lbl, **kwargs)
    917 
    918     def ReloadLocalizedNames(self):
    919         self.LoadEveOwners()
    920         self.LoadEveLocations()
    921 
    922     def GetShipGroupByClassType(self):
    923         try:
    924             return self.shipGroupByClassType
    925         except AttributeError:
    926             self.shipGroupByClassType = {const.GROUP_CAPSULES: (const.groupCapsule,),
    927              const.GROUP_FRIGATES: (const.groupShuttle,
    928                                     const.groupRookieship,
    929                                     const.groupFrigate,
    930                                     const.groupAssaultFrigate,
    931                                     const.groupCovertOps,
    932                                     const.groupElectronicAttackShips,
    933                                     const.groupPrototypeExplorationShip,
    934                                     const.groupInterceptor,
    935                                     const.groupStealthBomber,
    936                                     const.groupExpeditionFrigate,
    937                                     const.groupLogisticsFrigate),
    938              const.GROUP_DESTROYERS: (const.groupDestroyer,
    939                                       const.groupInterdictor,
    940                                       const.groupTacticalDestroyer,
    941                                       const.groupCommandDestroyer),
    942              const.GROUP_CRUISERS: (const.groupCruiser,
    943                                     const.groupStrategicCruiser,
    944                                     const.groupCombatReconShip,
    945                                     const.groupForceReconShip,
    946                                     const.groupHeavyAssaultCruiser,
    947                                     const.groupHeavyInterdictors,
    948                                     const.groupLogistics,
    949                                     const.groupFlagCruiser,
    950                                     const.groupSpecialEditionYacht),
    951              const.GROUP_BATTLECRUISERS: (const.groupBattlecruiser,
    952                                           const.groupAttackBattlecruiser,
    953                                           const.groupCommandShip,
    954                                           const.groupExpeditionCommandShip),
    955              const.GROUP_BATTLESHIPS: (const.groupBattleship, const.groupBlackOps, const.groupMarauders),
    956              const.GROUP_CAPITALSHIPS: (const.groupCarrier,
    957                                         const.groupCommandCarrier,
    958                                         const.groupCapitalIndustrialShip,
    959                                         const.groupDreadnought,
    960                                         const.groupTitan,
    961                                         const.groupSupercarrier,
    962                                         const.groupForceAux,
    963                                         const.groupLancerDreadnought),
    964              const.GROUP_INDUSTRIALS: (const.groupBlockadeRunner,
    965                                        const.groupExhumer,
    966                                        const.groupFreighter,
    967                                        const.groupIndustrial,
    968                                        const.groupIndustrialCommandShip,
    969                                        const.groupJumpFreighter,
    970                                        const.groupMiningBarge,
    971                                        const.groupTransportShip),
    972              const.GROUP_POS: tuple((groupID for groupID in evetypes.GetGroupIDsByCategory(const.categoryStarbase))),
    973              const.GROUP_STRUCTURES: tuple((groupID for groupID in evetypes.GetGroupIDsByCategory(const.categoryStructure)))}
    974 
    975         return self.shipGroupByClassType
    976 
    977     def GetShipClassTypeByGroupID(self, groupID):
    978         for classTypeID, groupIDs in self.GetShipGroupByClassType().iteritems():
    979             if groupID in groupIDs:
    980                 return classTypeID
    981 
    982 
    983 eveConfig = EveConfig()
    984 
    985 def GetStrippedEnglishMessage(messageID):
    986     msg = localization._GetRawByMessageID(messageID, 'en-us')
    987     if msg:
    988         regex = '</localized>|<localized>|<localized .*?>|<localized *=.*?>'
    989         return ''.join(re.split(regex, msg))
    990     else:
    991         return ''
    992 
    993 
    994 def CfgFsdDustIcons():
    995     return cfg.fsdDustIcons
    996 
    997 
    998 def CfgAverageMarketPrice():
    999     return cfg._averageMarketPrice
   1000 
   1001 
   1002 class Region(sysCfg.Row):
   1003     __guid__ = 'eveCfg.Region'
   1004     __slots__ = tuple()
   1005 
   1006     def __getattr__(self, name):
   1007         if name == 'regionName':
   1008             if self.regionID < const.mapWormholeRegionMin:
   1009                 return sysCfg.Row.__getattr__(self, 'regionName')
   1010             else:
   1011                 return 'Unknown'
   1012         return sysCfg.Row.__getattr__(self, name)
   1013 
   1014     def __str__(self):
   1015         return 'Region ID: %d, name: %s' % (self.regionID, self.regionName)
   1016 
   1017 
   1018 class Constellation(sysCfg.Row):
   1019     __guid__ = 'eveCfg.Constellation'
   1020     __slots__ = tuple()
   1021 
   1022     def __getattr__(self, name):
   1023         if name == 'constellationName':
   1024             if self.constellationID < const.mapWormholeConstellationMin:
   1025                 return sysCfg.Row.__getattr__(self, 'constellationName')
   1026             else:
   1027                 return 'Unknown'
   1028         return sysCfg.Row.__getattr__(self, name)
   1029 
   1030     def __str__(self):
   1031         return 'Constellation ID: %d, name: %s' % (self.constellationID, self.constellationName)
   1032 
   1033 
   1034 class SolarSystem(sysCfg.Row):
   1035     __guid__ = 'eveCfg.SolarSystem'
   1036     __slots__ = tuple()
   1037 
   1038     def __getattr__(self, name):
   1039         if name == 'pseudoSecurity':
   1040             value = sysCfg.Row.__getattr__(self, 'security')
   1041             if value > 0.0 and value < 0.05:
   1042                 return 0.05
   1043             else:
   1044                 return value
   1045         return sysCfg.Row.__getattr__(self, name)
   1046 
   1047     def __str__(self):
   1048         return 'SolarSystem ID: %d, name: %s' % (self.solarSystemID, self.solarSystemName)
   1049 
   1050 
   1051 def StackSize(item):
   1052     if item[const.ixQuantity] < 0:
   1053         return 1
   1054     return item[const.ixQuantity]
   1055 
   1056 
   1057 def Singleton(item):
   1058     if item[const.ixQuantity] < 0:
   1059         return -item[const.ixQuantity]
   1060     if 30000000 <= item[const.ixLocationID] < 40000000:
   1061         return 1
   1062     return 0
   1063 
   1064 
   1065 def CheckShipHasFighterBay(shipID):
   1066     item = sm.GetService('godma').GetItem(shipID)
   1067     if not item:
   1068         return False
   1069     godmaSM = sm.GetService('godma').GetStateManager()
   1070     return godmaSM.GetType(item.typeID).fighterCapacity > 0
   1071 
   1072 
   1073 def IsPreviewable(typeID):
   1074     if not evetypes.Exists(typeID):
   1075         return False
   1076     if IsApparel(typeID):
   1077         return True
   1078     if IsShipSkin(typeID):
   1079         return True
   1080     if evetypes.GetGraphicID(typeID) is None:
   1081         return False
   1082     return evetypes.GetCategoryID(typeID) in const.previewCategories or evetypes.GetGroupID(typeID) in const.previewGroups
   1083 
   1084 
   1085 def IsShip(typeID):
   1086     if not evetypes.Exists(typeID):
   1087         return False
   1088     return evetypes.GetCategoryID(typeID) == const.categoryShip
   1089 
   1090 
   1091 def IsShipSkin(typeID):
   1092     if not evetypes.Exists(typeID):
   1093         return False
   1094     return evetypes.GetCategoryID(typeID) == const.categoryShipSkin
   1095 
   1096 
   1097 def IsApparel(typeID):
   1098     if not evetypes.Exists(typeID):
   1099         return False
   1100     return evetypes.GetCategoryID(typeID) == const.categoryApparel
   1101 
   1102 
   1103 def IsBlueprint(typeID):
   1104     if not evetypes.Exists(typeID):
   1105         return False
   1106     return evetypes.GetCategoryID(typeID) == const.categoryBlueprint
   1107 
   1108 
   1109 def IsPlaceable(typeID):
   1110     if not evetypes.Exists(typeID):
   1111         return False
   1112     return evetypes.GetCategoryID(typeID) == const.categoryPlaceables
   1113 
   1114 
   1115 def GetCharacterType(characterID):
   1116     if idCheckers.IsEveUser(characterID):
   1117         return 'capsuleer'
   1118     else:
   1119         return 'unknown'
   1120 
   1121 
   1122 def IsOutlawStatus(securityStatus):
   1123     if securityStatus is None:
   1124         return False
   1125     else:
   1126         return round(securityStatus, 1) <= const.outlawSecurityStatus
   1127 
   1128 
   1129 OWNER_NAME_OVERRIDES = {OWNER_AURA_IDENTIFIER: 'UI/Agents/AuraAgentName',
   1130  OWNER_SYSTEM_IDENTIFIER: 'UI/Chat/ChatEngine/EveSystem'}
   1131 
   1132 class EveOwners(sysCfg.Row):
   1133     __guid__ = 'cfg.EveOwners'
   1134     __slots__ = tuple()
   1135 
   1136     def __getattr__(self, name):
   1137         if name == 'name' or name == 'description':
   1138             name = 'ownerName'
   1139         elif name == 'groupID':
   1140             typeID = sysCfg.Row.__getattr__(self, 'typeID')
   1141             if typeID is None:
   1142                 return
   1143             return evetypes.GetGroupID(typeID)
   1144         ownerNameID = sysCfg.Row.__getattr__(self, 'ownerNameID')
   1145         if name == 'ownerName' and boot.role != 'client' and ownerNameID is not None:
   1146             return localization.GetByMessageID(ownerNameID)
   1147         return sysCfg.Row.__getattr__(self, name)
   1148 
   1149     def __str__(self):
   1150         return 'EveOwner ID: %d, "%s"' % (self.ownerID, self.ownerName)
   1151 
   1152     def GetRawName(self, languageID = None):
   1153         if self.ownerNameID is not None:
   1154             if self.ownerNameID in OWNER_NAME_OVERRIDES:
   1155                 return localization.GetByLabel(OWNER_NAME_OVERRIDES[self.ownerNameID], languageID)
   1156             return localization.GetByMessageID(self.ownerNameID, languageID)
   1157         return self.name
   1158 
   1159     def IsSystem(self):
   1160         return self.ownerID <= 15
   1161 
   1162     def IsNPC(self):
   1163         return idCheckers.IsNPC(self.ownerID)
   1164 
   1165     def IsCharacter(self):
   1166         return self.groupID == const.groupCharacter
   1167 
   1168     def IsCorporation(self):
   1169         return self.groupID == const.groupCorporation
   1170 
   1171     def IsAlliance(self):
   1172         return self.typeID == const.typeAlliance
   1173 
   1174     def IsFaction(self):
   1175         return self.groupID == const.groupFaction
   1176 
   1177     def Type(self):
   1178         raise evetypes.TypeNotFoundException('Not supported anymore to get a whole type, please change the caller. Hint: you have self.typeID')
   1179 
   1180     def Group(self):
   1181         raise evetypes.TypeNotFoundException('Not supported anymore to get a whole group, please change the caller. Hint: you have self.groupID')
   1182 
   1183 
   1184 class CrpTickerNames(sysCfg.Row):
   1185     __guid__ = 'cfg.CrpTickerNames'
   1186     __slots__ = tuple()
   1187 
   1188     def __getattr__(self, name):
   1189         if name == 'name' or name == 'description':
   1190             return sysCfg.Row.__getattr__(self, 'tickerName')
   1191         else:
   1192             return sysCfg.Row.__getattr__(self, name)
   1193 
   1194     def __str__(self):
   1195         return 'CorpTicker ID: %d, "%s"' % (self.corporationID, self.tickerName)
   1196 
   1197 
   1198 class AllShortNames(sysCfg.Row):
   1199     __guid__ = 'cfg.AllShortNames'
   1200     __slots__ = tuple()
   1201 
   1202     def __getattr__(self, name):
   1203         if name == 'name' or name == 'description':
   1204             return sysCfg.Row.__getattr__(self, 'shortName')
   1205         else:
   1206             return sysCfg.Row.__getattr__(self, name)
   1207 
   1208     def __str__(self):
   1209         return 'AllianceShortName ID: %d, "%s"' % (self.allianceID, self.shortName)
   1210 
   1211 
   1212 class EveLocations(sysCfg.Row):
   1213     __guid__ = 'dbrow.Location'
   1214     __slots__ = ('cachedLocationName',)
   1215 
   1216     def __init__(self, header, line):
   1217         sysCfg.Row.__init__(self, header, line)
   1218         self.cachedLocationName = None
   1219 
   1220     def __setattr__(self, name, value):
   1221         if name in EveLocations.__slots__:
   1222             object.__setattr__(self, name, value)
   1223         else:
   1224             sysCfg.Row.__setattr__(self, name, value)
   1225 
   1226     def __getattr__(self, name):
   1227         if name == 'name' or name == 'description' or name == 'locationName':
   1228             if self.cachedLocationName is not None:
   1229                 return self.cachedLocationName
   1230             locationName = sysCfg.Row.__getattr__(self, 'locationName')
   1231             if boot.role == 'client' and idCheckers.IsAbyssalSpaceSystem(self.locationID):
   1232                 locationName = localization.GetByLabel('UI/Common/Unknown')
   1233             elif (locationName is None or len(locationName) == 0) and self.locationNameID is not None:
   1234                 if isinstance(self.locationNameID, (int, long)):
   1235                     locationName = localization.GetImportantByMessageID(self.locationNameID)
   1236                 elif isinstance(self.locationNameID, tuple):
   1237                     locationName = localization.GetImportantByLabel(self.locationNameID[0], **self.locationNameID[1])
   1238                 if boot.role == 'client':
   1239                     self.cachedLocationName = locationName
   1240             elif boot.role != 'client' and self.locationNameID is not None:
   1241                 locationName = localization.GetByMessageID(self.locationNameID)
   1242             return locationName
   1243         return sysCfg.Row.__getattr__(self, name)
   1244 
   1245     def __str__(self):
   1246         return 'EveLocation ID: %d, "%s"' % (self.locationID, self.locationName)
   1247 
   1248     def GetRawName(self, languageID = None):
   1249         if self.locationNameID is not None:
   1250             return localization.GetByMessageID(self.locationNameID, languageID)
   1251         if self.locationID in cfg.rawCelestialCache:
   1252             lbl, kwargs = cfg.rawCelestialCache[self.locationID]
   1253             return localization.GetByLabel(lbl, languageID, **kwargs)
   1254         return self.name
   1255 
   1256     def Station(self):
   1257         return cfg.GetSvc('stationSvc').GetStation(self.id)
   1258 
   1259 
   1260 class RamCompletedStatus(sysCfg.Row):
   1261     __guid__ = 'cfg.RamCompletedStatus'
   1262     __slots__ = tuple()
   1263 
   1264     def __getattr__(self, name):
   1265         if name == 'name':
   1266             name = 'completedStatusText'
   1267         value = sysCfg.Row.__getattr__(self, name)
   1268         if name == 'completedStatusText':
   1269             value = localization.GetByMessageID(self.completedStatusTextID)
   1270         elif name == 'description':
   1271             return localization.GetByMessageID(self.descriptionID)
   1272         return value
   1273 
   1274     def __str__(self):
   1275         try:
   1276             return 'RamCompletedStatus ID: %d, "%s"' % (self.completedStatus, self.completedStatusText)
   1277         except:
   1278             sys.exc_clear()
   1279             return 'RamCompletedStatus containing crappy data'
   1280 
   1281 
   1282 class RamActivity(sysCfg.Row):
   1283     __guid__ = 'cfg.RamActivity'
   1284     __slots__ = tuple()
   1285 
   1286     def __getattr__(self, name):
   1287         if name in ('activityName', 'name'):
   1288             return localization.GetByMessageID(self.activityNameID)
   1289         if name == 'description':
   1290             return localization.GetByMessageID(self.descriptionID)
   1291         return sysCfg.Row.__getattr__(self, name)
   1292 
   1293     def __str__(self):
   1294         try:
   1295             return 'RamActivity ID: %d, "%s"' % (self.activityID, self.activityName)
   1296         except:
   1297             sys.exc_clear()
   1298             return 'RamActivity containing crappy data'
   1299 
   1300 
   1301 class OverviewDefault(sysCfg.Row):
   1302     __guid__ = 'eveCfg.OverviewDefault'
   1303     __slots__ = tuple()
   1304 
   1305     def __getattr__(self, name):
   1306         if name == '_overviewName':
   1307             return sysCfg.Row.__getattr__(self, 'overviewName')
   1308         if name in ('name', 'overviewName'):
   1309             return localization.GetByMessageID(self.overviewNameID)
   1310         value = sysCfg.Row.__getattr__(self, name)
   1311         return value
   1312 
   1313     def __str__(self):
   1314         return 'DefaultOverview ID: %d, "%s"' % (self.overviewID, self.overviewName)
   1315 
   1316 
   1317 class Position(sysCfg.Row):
   1318     __guid__ = 'cfg.Position'
   1319     __slots__ = tuple()
   1320 
   1321     @property
   1322     def latitude(self):
   1323         return self.x
   1324 
   1325     @property
   1326     def longitude(self):
   1327         return self.y
   1328 
   1329     @property
   1330     def radius(self):
   1331         return self.z
   1332 
   1333 
   1334 def _LoadMessagesFromFSD():
   1335     return fsdBinaryLoader.LoadFSDDataForCFG('res:/staticdata/dialogs.static', 'res:/staticdata/dialogs.schema', optimize=False)
   1336 
   1337 
   1338 def IsPolarisFrigate(typeID):
   1339     return typeID in (const.typePolarisCenturion,
   1340      const.typePolarisCenturionFrigate,
   1341      const.typePolarisInspectorFrigate,
   1342      const.typePolarisLegatusFrigate,
   1343      const.typePolarisEnigmaFrigate)
   1344 
   1345 
   1346 def MakeConstantName(val, prefix):
   1347     name = val.replace(' ', '')
   1348     if name == '':
   1349         name = 'invalidName_' + val
   1350     name = prefix + name[0].upper() + name[1:]
   1351     ret = ''
   1352     okey = range(ord('a'), ord('z') + 1) + range(ord('A'), ord('Z') + 1) + range(ord('0'), ord('9') + 1)
   1353     for ch in name:
   1354         if ord(ch) in okey:
   1355             ret += ch
   1356 
   1357     if ret == '':
   1358         ret = 'invalidName_' + ret
   1359     elif ord(ret[0]) in range(ord('0'), ord('9') + 1):
   1360         ret = '_' + ret
   1361     return ret
   1362 
   1363 
   1364 locationPathByFlagID = {const.flagCargo: 'UI/Ship/CargoHold',
   1365  const.flagDroneBay: 'UI/Ship/DroneBay',
   1366  const.flagShipHangar: 'UI/Ship/ShipMaintenanceBay',
   1367  const.flagSpecializedFuelBay: 'UI/Ship/FuelBay',
   1368  const.flagGeneralMiningHold: 'UI/Ship/GeneralMiningHold',
   1369  const.flagSpecializedIceHold: 'UI/Ship/IceHold',
   1370  const.flagSpecialAsteroidHold: 'UI/Ship/AsteroidHold',
   1371  const.flagSpecializedGasHold: 'UI/Ship/GasHold',
   1372  const.flagSpecializedMineralHold: 'UI/Ship/MineralHold',
   1373  const.flagSpecializedSalvageHold: 'UI/Ship/SalvageHold',
   1374  const.flagSpecializedShipHold: 'UI/Ship/ShipHold',
   1375  const.flagSpecializedSmallShipHold: 'UI/Ship/SmallShipHold',
   1376  const.flagSpecializedMediumShipHold: 'UI/Ship/MediumShipHold',
   1377  const.flagSpecializedLargeShipHold: 'UI/Ship/LargeShipHold',
   1378  const.flagSpecializedIndustrialShipHold: 'UI/Ship/IndustrialShipHold',
   1379  const.flagSpecializedAmmoHold: 'UI/Ship/AmmoHold',
   1380  const.flagSpecializedCommandCenterHold: 'UI/Ship/CommandCenterHold',
   1381  const.flagSpecializedPlanetaryCommoditiesHold: 'UI/Ship/PlanetaryCommoditiesHold',
   1382  const.flagSpecializedMaterialBay: 'UI/Ship/MaterialBay',
   1383  const.flagFighterBay: 'UI/Ship/FighterBay',
   1384  const.flagFrigateEscapeBay: 'UI/Ship/FrigateEscapeBay'}
   1385 
   1386 def GetShipFlagLocationName(flagID):
   1387     if flagID in const.hiSlotFlags:
   1388         locationPath = 'UI/Ship/HighSlot'
   1389     elif flagID in const.medSlotFlags:
   1390         locationPath = 'UI/Ship/MediumSlot'
   1391     elif flagID in const.loSlotFlags:
   1392         locationPath = 'UI/Ship/LowSlot'
   1393     elif flagID in const.rigSlotFlags:
   1394         locationPath = 'UI/Ship/RigSlot'
   1395     elif IsSubsystemFlagVisible(flagID):
   1396         locationPath = 'UI/Ship/Subsystem'
   1397     elif flagID in const.flagCorpSAGs:
   1398         locationPath = 'UI/Corporations/Common/CorporateHangar'
   1399     elif flagID in const.fighterTubeFlags:
   1400         locationPath = 'UI/Ship/FighterLaunchTube'
   1401     else:
   1402         locationPath = locationPathByFlagID.get(flagID, '')
   1403     if locationPath:
   1404         return localization.GetByLabel(locationPath)
   1405     else:
   1406         return ''
   1407 
   1408 
   1409 def GetSunWarpInPoint(ballID, position, radius):
   1410     offset = 100000
   1411     x = position[0] + (radius + offset) * math.cos(radius)
   1412     y = position[1] + radius / 5
   1413     z = position[2] - (radius + offset) * math.sin(radius)
   1414     return (x, y, z)
   1415 
   1416 
   1417 def GetPlanetWarpInPoint(ballID, position, radius):
   1418     dx = float(position[0])
   1419     dz = float(-position[2])
   1420     f = float(dz) / float(math.sqrt(dx ** 2 + dz ** 2))
   1421     if dz > 0 and dx > 0 or dz < 0 and dx > 0:
   1422         f *= -1.0
   1423     theta = math.asin(f)
   1424     myRandom = random.Random(ballID)
   1425     rr = (myRandom.random() - 1.0) / 3.0
   1426     theta += rr
   1427     offset = 1000000
   1428     FACTOR = 20.0
   1429     dd = math.pow((FACTOR - 5.0 * math.log10(radius / 1000000) - 0.5) / FACTOR, FACTOR) * FACTOR
   1430     dd = min(10.0, max(0.0, dd))
   1431     dd += 0.5
   1432     offset += radius * dd
   1433     d = radius + offset
   1434     x = 1000000
   1435     z = 0
   1436     x = position[0] + math.sin(theta) * d
   1437     y = position[1] + radius * math.sin(rr) * 0.5
   1438     z = position[2] - math.cos(theta) * d
   1439     return (x, y, z)
   1440 
   1441 
   1442 def GetWarpInPoint(ballID, position, radius):
   1443     offset = 5000000
   1444     p = const.jumpRadiusFactor / 100.0
   1445     x = position[0] + (radius + offset) * math.cos(radius)
   1446     y = position[1] + p * radius - 7500.0
   1447     z = position[2] - (radius + offset) * math.sin(radius)
   1448     return (x, y, z)
   1449 
   1450 
   1451 def GetActiveShip():
   1452     return session.shipid
   1453 
   1454 
   1455 def InSpace():
   1456     return bool(session.solarsystemid) and bool(session.shipid) and session.structureid in (session.shipid, None)
   1457 
   1458 
   1459 def InShip():
   1460     return bool(session.shipid) and bool(session.shipid != session.structureid)
   1461 
   1462 
   1463 def InShipInSpace():
   1464     return bool(session.solarsystemid) and bool(session.shipid) and not bool(session.structureid)
   1465 
   1466 
   1467 def IsDocked():
   1468     return bool(session.stationid) or IsDockedInStructure()
   1469 
   1470 
   1471 def InStructure():
   1472     return bool(session.structureid)
   1473 
   1474 
   1475 def IsDockedInStructure():
   1476     return bool(session.structureid) and bool(session.structureid != session.shipid)
   1477 
   1478 
   1479 def IsControllingStructure():
   1480     return bool(session.structureid) and bool(session.structureid == session.shipid)
   1481 
   1482 
   1483 def IsAtLocation(locationID):
   1484     if locationID is None:
   1485         return False
   1486     elif InStructure():
   1487         return locationID == session.structureid
   1488     else:
   1489         return locationID == session.locationid
   1490 
   1491 
   1492 def IsBookmarkModerator(corpRole):
   1493     return corpRole & const.corpRoleChatManager == const.corpRoleChatManager