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

lpStoreSvc.py (23062B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\station\loyaltyPointStore\lpStoreSvc.py
      2 import copy
      3 import blue
      4 import evetypes
      5 import localization
      6 import log
      7 import sys
      8 import telemetry
      9 import uthread
     10 from featuremanagement.client.flag import flag_bool
     11 from appConst import corpHeraldry
     12 from carbon.client.script.util.misc import TryDel
     13 from carbon.common.script.sys.service import Service
     14 from carbonui import uiconst
     15 from carbonui.util.bunch import Bunch
     16 from caching.memoize import Memoize
     17 from collections import defaultdict
     18 from carbon.common.script.util.format import FmtAmt
     19 from corporation.common import FLAG_CORP_LP_PURCHASES_KILLSWITCH, FLAG_CORP_LP_PURCHASES_KILLSWITCH_DEFAULT
     20 from cosmetics.common import cosmeticsConst
     21 from eve.client.script.ui.station.loyaltyPointStore.lpExchangeDialog import LPExhangeDialog
     22 from eve.client.script.ui.station.loyaltyPointStore.lpStoreSignals import on_corp_lp_purchases_killswitch_changed
     23 from eve.client.script.ui.station.loyaltyPointStore.lpStoreWindow import LPStoreWindow
     24 from eve.client.script.ui.station.loyaltyPointStore.lpUtil import GetItemText
     25 from eve.client.script.ui.station.loyaltyPointStore.paragonLpStoreConst import DEFAULT_PARAGON_FILTERS
     26 from eve.client.script.ui.station.lpstoreRequirement import LpRequirement, ISKRequirement, AnalysisKreditsRequirement, EMRequirement
     27 from eve.common.lib import appConst
     28 from eve.common.script.sys import idCheckers
     29 from eve.common.script.util.facwarCommon import GetFwFactionIDForNpcCorp, IsPirateFWFaction
     30 from loyaltypoints.lpUtil import get_hardcoded_lp_stations_for_corp
     31 from npcs.npccorporations import get_corporation_exchange_rates
     32 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     33 from resourcewars.common.const import FACTION_TO_RW_LP_CORP
     34 from uthread2 import BufferedCall
     35 
     36 class LPStoreSvc(Service):
     37     __guid__ = 'svc.lpstore'
     38     __notifyevents__ = ['OnAccountChange',
     39      'ProcessSessionChange',
     40      'OnCharacterLPBalanceChange_Local',
     41      'OnCorporationLPBalanceChange_Local',
     42      'OnAnalysisKreditsChange',
     43      'OnItemChangeProcessed']
     44     __dependencies__ = ['settings',
     45      'clientPathfinderService',
     46      'loyaltyPointsWalletSvc',
     47      'wallet']
     48     settingsVersion = 4
     49 
     50     def Run(self, *etc):
     51         Service.Run(self, *etc)
     52         self.cache = Bunch()
     53         self._ClearCache()
     54         self.LpOfferRequirements = {}
     55         self.defaultPreset = localization.GetByLabel('UI/LPStore/PresetAll')
     56         self.currentParagonFilters = {}
     57         self.storesUsingCorpWalletMode = set()
     58         self._corp_spending_killswitch = FLAG_CORP_LP_PURCHASES_KILLSWITCH_DEFAULT
     59         flag_bool(key=FLAG_CORP_LP_PURCHASES_KILLSWITCH, default_value=FLAG_CORP_LP_PURCHASES_KILLSWITCH_DEFAULT, callback=self._on_corp_spending_killswitch_changed)
     60 
     61     @staticmethod
     62     def _GetRemoteLPService():
     63         return sm.RemoteSvc('LPSvc')
     64 
     65     def _ClearCache(self):
     66         self.cache.clear()
     67         self.cache.offers = {}
     68 
     69     def GetCurrentFilters(self):
     70         return self.currentFilters.copy()
     71 
     72     def GetCurrentParagonFilters(self):
     73         return copy.deepcopy(self.currentParagonFilters)
     74 
     75     def GetCurrentPresetLabel(self):
     76         return self.currentPreset
     77 
     78     def IsRWCorp(self, corpID):
     79         return corpID in FACTION_TO_RW_LP_CORP.values()
     80 
     81     def OpenConcordExchange(self, corpID):
     82         exchangeRate = self.GetConcordLPExchangeRate(corpID)
     83         myConcordLP = self.loyaltyPointsWalletSvc.GetCharacterConcordLPBalance()
     84         corporationLPs = self.loyaltyPointsWalletSvc.GetCharacterWalletLPBalance(corpID)
     85         LPExhangeDialog.CloseIfOpen(windowID='LPExhangeDialog_%s' % corpID)
     86         LPExhangeDialog.Open(windowID='LPExhangeDialog_%s' % corpID, currentFromCorpLPs=myConcordLP, currentToCorpLPs=corporationLPs, exchangeRate=exchangeRate, toCorpID=corpID)
     87 
     88     def GetConcordLPExchangeRate(self, corpID):
     89         stationItem = sm.GetService('station').stationItem
     90         if not corpID and idCheckers.IsNPC(stationItem.ownerID):
     91             corpID = stationItem.ownerID
     92         return get_corporation_exchange_rates(appConst.ownerCONCORD, default={}).get(corpID)
     93 
     94     def GetOffers(self, corpID):
     95         if self.cache.offers.get(corpID, None) is None:
     96             self.cache.offers[corpID] = sm.RemoteSvc('LPStoreMgr').GetAvailableOffersFromCorp(corpID)
     97             self._RefreshOfferSortValues(corpID)
     98         return self.cache.offers[corpID]
     99 
    100     def ConvertConcordLP(self, corpID, amount):
    101         self._GetRemoteLPService().ExchangeConcordLP(corpID, amount)
    102 
    103     def GetCorpName(self, corpID):
    104         return cfg.eveowners.Get(corpID).name
    105 
    106     def AddFilters(self, newFilters):
    107         newFilters = dict(self.currentFilters, **newFilters)
    108         self.ChangeFilters(newFilters)
    109 
    110     def RemoveFilter(self, key):
    111         TryDel(self.currentFilters, key)
    112         self.ChangeFilters(self.currentFilters)
    113 
    114     def ChangeFilters(self, newFilters):
    115         self.currentFilters = newFilters
    116         self.currentPreset = localization.GetByLabel('UI/LPStore/PresetNone')
    117         self._PersistFilters()
    118         sm.ScatterEvent('OnLPStoreCurrentPresetChange')
    119         sm.ScatterEvent('OnLPStoreFilterChange')
    120 
    121     def ChangeParagonFilters(self, newFilters):
    122         self.currentParagonFilters = newFilters
    123         self._PersistParagonFilters()
    124         sm.ScatterEvent('OnLPStoreParagonFilterChange')
    125 
    126     def ChangeCurrentPreset(self, newPreset):
    127         self.currentPreset = newPreset
    128         self.currentFilters = self._GetPresetFilters(newPreset)
    129         self._PersistFilters()
    130         sm.ScatterEvent('OnLPStoreCurrentPresetChange')
    131         sm.ScatterEvent('OnLPStoreFilterChange')
    132 
    133     def GetPresets(self):
    134         ret = self._GetDefaultPresets() + self.userPresets
    135         if self.currentPreset == localization.GetByLabel('UI/LPStore/PresetNone'):
    136             ret.insert(0, Bunch(label=localization.GetByLabel('UI/LPStore/PresetNone'), filters=None, editable=False))
    137         return ret
    138 
    139     def AddPreset(self, name, filters):
    140         self.userPresets.append(Bunch(label=name, filters=filters, editable=True))
    141         self._PersistPresets()
    142         sm.ScatterEvent('OnLPStorePresetsChange')
    143 
    144     def OverwritePreset(self, label, filters):
    145         for i, p in enumerate(self.userPresets):
    146             if p.label == label:
    147                 self.userPresets[i] = Bunch(label=label, filters=filters.copy(), editable=True)
    148                 self.ChangeCurrentPreset(label)
    149                 self._PersistPresets()
    150                 return
    151         else:
    152             log.LogError('svc.lpstore.OverwritePreset: Preset not found.')
    153 
    154     def DeletePreset(self, label):
    155         if label == self.currentPreset:
    156             self.ChangeCurrentPreset(self.defaultPreset)
    157         for p in self.userPresets:
    158             if p.label == label:
    159                 self.userPresets.remove(p)
    160                 self._PersistPresets()
    161                 sm.ScatterEvent('OnLPStorePresetsChange')
    162                 return
    163         else:
    164             log.LogError('svc.lpstore.DeletePreset: Preset not found.')
    165 
    166     def _GetSetting(self, key, default):
    167         return settings.user.ui.Get('%s_%s' % (key, self.settingsVersion), default)
    168 
    169     def _SetSetting(self, key, value):
    170         return settings.user.ui.Set('%s_%s' % (key, self.settingsVersion), value)
    171 
    172     def _InitPresets(self):
    173         if hasattr(self, 'initedPresets'):
    174             return
    175         self.userPresets = [ Bunch(**d) for d in self._GetSetting('lpStoreFilterPresets', []) ]
    176         self.currentPreset = self._GetSetting('lpStoreCurrentPreset', self.defaultPreset)
    177         if self.currentPreset == localization.GetByLabel('UI/LPStore/PresetNone'):
    178             self.currentFilters = settings.user.ui.Get('lpStoreCurrentFilters', self._GetPresetFilters(self.defaultPreset))
    179         else:
    180             self.currentFilters = self._GetPresetFilters(self.currentPreset)
    181         self.currentParagonFilters = self._GetSetting('lpStoreCurrentParagonFilters', DEFAULT_PARAGON_FILTERS)
    182         self.initedPresets = True
    183 
    184     def _GetPresetFilters(self, label):
    185         if label == localization.GetByLabel('UI/LPStore/PresetNone'):
    186             return self.currentFilters
    187         for preset in self.GetPresets():
    188             if preset.label == label:
    189                 return preset.filters
    190 
    191         return self._GetPresetFilters(self.defaultPreset)
    192 
    193     def _PersistPresets(self):
    194         self._SetSetting('lpStoreFilterPresets', [ {'label': preset.label,
    195          'filters': preset.filters,
    196          'editable': True} for preset in self.userPresets ])
    197         self.settings.SaveSettings()
    198 
    199     def _PersistFilters(self):
    200         self._SetSetting('lpStoreCurrentPreset', self.currentPreset)
    201         if self.currentPreset == localization.GetByLabel('UI/LPStore/PresetNone'):
    202             self._SetSetting('lpStoreCurrentFilters', self.currentFilters)
    203         self.settings.SaveSettings()
    204 
    205     def _PersistParagonFilters(self):
    206         self._SetSetting('lpStoreCurrentParagonFilters', self.currentParagonFilters)
    207         self.settings.SaveSettings()
    208 
    209     def _GetDefaultPresets(self):
    210         affordableFilters = {'reqNotInHangar': True,
    211          'dynamicMaxLP': True,
    212          'dynamicMaxISK': True,
    213          'dynamicMaxAnalysisKredits': True,
    214          'dynamicStandings': True}
    215         return [Bunch(label=localization.GetByLabel('UI/LPStore/PresetAffordable'), filters=affordableFilters, editable=False), Bunch(label=localization.GetByLabel('UI/LPStore/PresetAll'), filters={}, editable=False)]
    216 
    217     def _RefreshOfferSortValues(self, corpID):
    218         for offer in self.cache.offers[corpID]:
    219             self._SetOfferDataSortOrder(offer)
    220 
    221     def AcceptOffer(self, data, numberOfOffers = 1):
    222         if getattr(self, 'acceptingOffer', False):
    223             return uiconst.ID_NO
    224         try:
    225             self.acceptingOffer = True
    226             message, args = self._GetConfirmMessage(data, numberOfOffers)
    227             if prompt_player_fsd_dialog(message, args, uiconst.OKCANCEL, uiconst.ID_OK) != uiconst.ID_OK:
    228                 return uiconst.OKCANCEL
    229             if self.IsUsingCharacterWallets(data.corpID):
    230                 ret = sm.RemoteSvc('LPStoreMgr').TakeOfferForCharacter(data.corpID, data.offerID, numberOfOffers)
    231             elif self.IsUsingCorpWallets(data.corpID):
    232                 ret = sm.RemoteSvc('LPStoreMgr').TakeOfferForCorporation(data.corpID, data.offerID, numberOfOffers)
    233             else:
    234                 raise RuntimeError('Invalid LPStoreSvc walletMode {0}'.format(self.walletMode))
    235             if ret:
    236                 prompt_player_fsd_dialog('LPStoreOfferAccepted', {'name': cfg.eveowners.Get(session.charid).name})
    237             if self.cache.analysisKredits:
    238                 del self.cache.analysisKredits
    239             if len(data.reqItems) > 0 and self.cache.hangarInv:
    240                 del self.cache.hangarInv
    241             self.DirtyWindow()
    242         finally:
    243             self.acceptingOffer = False
    244 
    245         if ret:
    246             return uiconst.ID_YES
    247         return uiconst.ID_NO
    248 
    249     def _GetConfirmMessage(self, data, numberOfOffers):
    250         offer = GetItemText(data.typeID, data.qty, numberOfOffers).replace('<br>', ' ')
    251         if evetypes.GetGroupID(data.typeID) == appConst.groupShipCosmeticLicense:
    252             price = localization.GetByLabel('UI/LPStore/PriceInEMSimple', lpCost=FmtAmt(data.lpCost))
    253             return ('ConfirmAcceptEmblemLPOffer', {'offer': offer,
    254               'price': price})
    255         else:
    256             price = self._GetPrice(data, numberOfOffers)
    257             if self.IsUsingCharacterWallets(data.corpID):
    258                 messageName = 'ConfirmAcceptLPOffer'
    259             elif self.IsUsingCorpWallets(data.corpID):
    260                 messageName = 'ConfirmAcceptLPOfferUsingCorpWallet'
    261             else:
    262                 raise RuntimeError('Invalid LPStoreSvc walletMode {0}'.format(self.walletMode))
    263             return (messageName, {'offer': offer,
    264               'price': price})
    265 
    266     def _GetPrice(self, data, numberOfOffers):
    267         price = ''
    268         for requirement in self.LpOfferRequirements[data.corpID]:
    269             requirementName = requirement.name
    270             if requirementName:
    271                 cost = data.Get(requirementName, 0)
    272                 if cost > 0:
    273                     totalCost = requirement.formatAmount(cost * numberOfOffers)
    274                     if requirement.priceLabelPath:
    275                         keywords = {requirementName: totalCost}
    276                         price += localization.GetByLabel(requirement.priceLabelPath, **keywords) + '<br>'
    277                     else:
    278                         price += localization.GetByLabel('UI/LPStore/OfferItems', itemText=totalCost) + '<br>'
    279 
    280         for item in data.reqItems:
    281             price += localization.GetByLabel('UI/LPStore/OfferItems', itemText=GetItemText(item[0], item[1], numberOfOffers)) + '<br>'
    282 
    283         return price
    284 
    285     def HaveItem(self, typeID, qty):
    286         return self.GetInvenoryItemQuantity(typeID) >= qty
    287 
    288     def GetInvenoryItemQuantity(self, typeID):
    289         if self.cache.hangarInv is None:
    290             hi = {}
    291             inv = sm.GetService('invCache').GetInventory(appConst.containerHangar).List(appConst.flagHangar)
    292             for item in inv:
    293                 if not item.singleton:
    294                     hi[item.typeID] = max(hi.get(item.typeID, 0), item.stacksize)
    295 
    296             self.cache.hangarInv = hi
    297         return self.cache.hangarInv.get(typeID, 0)
    298 
    299     def GetISKBalanceForStorePurchase(self, storeCorpID):
    300         if self.IsUsingCharacterWallets(storeCorpID):
    301             return self.wallet.GetWealth()
    302         elif self.IsUsingCorpWallets(storeCorpID):
    303             return self._GetCorpWealth_Memozied(accountKey=session.corpAccountKey)
    304         else:
    305             return None
    306 
    307     @Memoize(1.0 / 60.0)
    308     def _GetCorpWealth_Memozied(self, accountKey):
    309         return self.wallet.GetCorpWealth(accountKey)
    310 
    311     def GetLPBalanceForStorePurchase(self, storeCorpID):
    312         if self.IsUsingCharacterWallets(storeCorpID):
    313             return self.loyaltyPointsWalletSvc.GetCharacterWalletLPBalance(storeCorpID)
    314         elif self.IsUsingCorpWallets(storeCorpID):
    315             return self.loyaltyPointsWalletSvc.GetCorporationWalletLPBalance(storeCorpID)
    316         else:
    317             return None
    318 
    319     def GetMyAnalysisKredits(self):
    320         if self.cache.analysisKredits is None:
    321             self.cache.analysisKredits = sm.RemoteSvc('ProjectDiscovery').get_player_analysis_kredits()
    322         return self.cache.analysisKredits
    323 
    324     def OpenLPStore(self, corpIDs):
    325         for corpID in corpIDs:
    326             self.GetOffers(corpID)
    327 
    328         self._InitPresets()
    329         self.cache.hangarInv = None
    330         wnd = LPStoreWindow.GetIfOpen()
    331         if wnd is None:
    332             wnd = LPStoreWindow(corpIDs=corpIDs)
    333         else:
    334             wnd.ToggleOpenClose()
    335         if wnd:
    336             wnd.RefreshIfNotAlready()
    337             wnd.RefreshOffers()
    338         return wnd
    339 
    340     def DirtyWindow(self):
    341         if not getattr(self, 'refreshpending', False):
    342             self.refreshpending = True
    343             uthread.pool('lpStore::ReportDirtyWindow', self.__DirtyWindow)
    344 
    345     def __DirtyWindow(self):
    346         try:
    347             blue.pyos.synchro.SleepWallclock(1000)
    348             for corpID in self.cache.offers.keys():
    349                 self._RefreshOfferSortValues(corpID)
    350 
    351             w = self._GetWnd()
    352             if w is not None:
    353                 w.Refresh()
    354         finally:
    355             self.refreshpending = False
    356 
    357     def _GetWnd(self):
    358         return LPStoreWindow.GetIfOpen()
    359 
    360     def OnAccountChange(self, accountKey, ownerID, _balance):
    361         if accountKey == 'cash' and ownerID == session.charid:
    362             self.DirtyWindow()
    363 
    364     def ProcessSessionChange(self, _isremote, _session, change):
    365         if 'stationid' in change:
    366             self._ClearCache()
    367             w = self._GetWnd()
    368             if w:
    369                 w.Close()
    370             self.ResetWalletsSourceChoices()
    371         if 'corprole' in change or 'corpAccountKey' in change:
    372             self.ResetWalletsSourceChoices()
    373 
    374     def OnCharacterLPBalanceChange_Local(self, issuerCorpID, lpBefore, lpAfter):
    375         if self.IsUsingCharacterWallets(issuerCorpID):
    376             self.DirtyWindow()
    377 
    378     def OnCorporationLPBalanceChange_Local(self, issuerCorpID):
    379         if self.IsUsingCorpWallets(issuerCorpID):
    380             self.DirtyWindow()
    381 
    382     def OnAnalysisKreditsChange(self):
    383         currentAnalysisKredits = self.cache.analysisKredits
    384         if self.cache.analysisKredits is not None:
    385             del self.cache.analysisKredits
    386         self.DirtyWindow()
    387         if session.stationid and currentAnalysisKredits == 0:
    388             sm.GetService('station').ReloadLobby()
    389 
    390     def OnItemChangeProcessed(self, item = None, change = None):
    391         self._on_item_change_processed_internal()
    392 
    393     @BufferedCall(200)
    394     def _on_item_change_processed_internal(self):
    395         if self.cache.hangarInv is not None:
    396             del self.cache.hangarInv
    397         self.DirtyWindow()
    398 
    399     def ResetWalletsSourceChoices(self):
    400         self.storesUsingCorpWalletMode.clear()
    401         self.DirtyWindow()
    402 
    403     def UseCharacterWallets(self, storeCorpID):
    404         self.storesUsingCorpWalletMode.discard(storeCorpID)
    405         self.DirtyWindow()
    406 
    407     def UseCorporationWallets(self, storeCorpID):
    408         self.storesUsingCorpWalletMode.add(storeCorpID)
    409         self.DirtyWindow()
    410 
    411     def IsUsingCharacterWallets(self, storeCorpID):
    412         return storeCorpID not in self.storesUsingCorpWalletMode
    413 
    414     def IsUsingCorpWallets(self, storeCorpID):
    415         return storeCorpID in self.storesUsingCorpWalletMode
    416 
    417     def CanCharacterUseCorpWallets(self, storeCorpID):
    418         if self._corp_spending_killswitch:
    419             return False
    420         if storeCorpID == corpHeraldry:
    421             return False
    422         return bool(session.corprole & appConst.corpRoleDirector)
    423 
    424     def _SetOfferDataSortOrder(self, data):
    425         offerData = [(localization.GetByLabel('UI/LPStore/Reward'), evetypes.GetName(data.typeID))]
    426         for requirement in self.GetRequirements(data.corpID):
    427             requirementName = requirement.name
    428             cost = data.Get(requirementName, 0)
    429             if requirement.costLabelPath:
    430                 costLabel = localization.GetByLabel(requirement.costLabelPath)
    431                 if not cost:
    432                     cost = 0
    433                 offerData.append((costLabel, cost))
    434 
    435         requiredStandings = data.Get('requiredStandings', None)
    436         standingsValue = requiredStandings['value'] if requiredStandings else -11
    437         offerData.append((localization.GetByLabel('UI/LPStore/StandingsRequired'), standingsValue))
    438         for label, sortval in offerData:
    439             data.Set('sort_%s' % label, sortval)
    440 
    441     def GetRequirements(self, corpID):
    442         if corpID not in self.LpOfferRequirements:
    443             self._CreateRequirements(corpID)
    444         return self.LpOfferRequirements[corpID]
    445 
    446     def _CreateRequirements(self, corpID):
    447         if corpID == cosmeticsConst.LP_STORE_CORP:
    448             self.LpOfferRequirements[corpID] = [EMRequirement(checkAmountFunction=lambda : self.loyaltyPointsWalletSvc.GetCharacterEvermarkBalance())]
    449         else:
    450             self.LpOfferRequirements[corpID] = [LpRequirement(checkAmountFunction=lambda : self.GetLPBalanceForStorePurchase(corpID)), ISKRequirement(checkAmountFunction=lambda : self.GetISKBalanceForStorePurchase(corpID)), AnalysisKreditsRequirement(checkAmountFunction=self.GetMyAnalysisKredits)]
    451 
    452     def CanAcceptOffer(self, data):
    453         requiredItems = data.Get('reqItems', [])
    454         missingItems = [ 1 for typeID, qty in requiredItems if not self.HaveItem(typeID, qty) ]
    455         areCostRequirementsFulfilled = self.AreRequirementsFulfilled(data)
    456         return areCostRequirementsFulfilled and not missingItems and self.IsStandingsFulfilled(data)
    457 
    458     def AreRequirementsFulfilled(self, data):
    459         requirementList = self.LpOfferRequirements[data.corpID]
    460         for requirement in requirementList:
    461             if not self._IsRequirementFulfilled(data, requirement):
    462                 return False
    463 
    464         return True
    465 
    466     def _IsRequirementFulfilled(self, data, requirement):
    467         requirementName = requirement.name
    468         if not requirementName:
    469             return True
    470         cost = data.Get(requirementName, 0)
    471         return requirement.checkAmount(cost)
    472 
    473     def IsStandingsFulfilled(self, data):
    474         requiredStandings = data.Get('requiredStandings', None)
    475         if not requiredStandings:
    476             return True
    477         currentStanding = sm.GetService('standing').GetStandingWithSkillBonus(requiredStandings['ownerID'], session.charid)
    478         return requiredStandings['value'] < currentStanding
    479 
    480     @telemetry.ZONE_FUNCTION
    481     def GetNearestDockableWithLPStoreForCorp(self, corpID):
    482         if sm.GetService('lpstore').IsRWCorp(corpID):
    483             rw_station_ids = sm.RemoteSvc('RWManager').get_closest_rw_stations(session.solarsystemid2)
    484             nearestRWStationID = rw_station_ids.get(corpID, None)
    485             return nearestRWStationID
    486         stationsOwnedByCorp = sm.RemoteSvc('stationSvc').GetStationsForOwner(corpID)
    487         stationsOwnedByCorpBySolarSystemID = defaultdict(list)
    488         for station in stationsOwnedByCorp:
    489             stationsOwnedByCorpBySolarSystemID[station.solarSystemID].append(station.stationID)
    490 
    491         hardcoded_stations = get_hardcoded_lp_stations_for_corp(corpID)
    492         for stationID in hardcoded_stations:
    493             stationsOwnedByCorpBySolarSystemID[cfg.evelocations.Get(stationID).solarSystemID].append(stationID)
    494 
    495         fwFactionID = GetFwFactionIDForNpcCorp(corpID)
    496         if IsPirateFWFaction(fwFactionID):
    497             structureID, solarSystemID = sm.GetService('insurgencyCampaignSvc').GetActiveFobStructureIdAndSystemIdForFaction(fwFactionID)
    498             if structureID and solarSystemID:
    499                 stationsOwnedByCorpBySolarSystemID[solarSystemID].append(structureID)
    500         nearestDockableLocation = None
    501         jumpsToNearestStation = sys.maxint
    502         for solarSystemID, stationIDs in stationsOwnedByCorpBySolarSystemID.iteritems():
    503             for dockableLocationID in stationIDs:
    504                 blue.pyos.BeNice()
    505                 if session.stationid == dockableLocationID:
    506                     return dockableLocationID
    507                 if session.structureid == dockableLocationID:
    508                     return dockableLocationID
    509                 dist = self.clientPathfinderService.GetJumpCount(session.solarsystemid2, solarSystemID)
    510                 if dist <= jumpsToNearestStation:
    511                     jumpsToNearestStation = dist
    512                     nearestDockableLocation = dockableLocationID
    513 
    514         return nearestDockableLocation
    515 
    516     def _on_corp_spending_killswitch_changed(self, evaluate_flag):
    517         current_value = self._corp_spending_killswitch
    518         self._corp_spending_killswitch = evaluate_flag()
    519         if self._corp_spending_killswitch != current_value:
    520             on_corp_lp_purchases_killswitch_changed(self._corp_spending_killswitch)