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

facWarSvc.py (32447B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\services\facWarSvc.py
      2 import sys
      3 import gametime
      4 import carbonui.const as uiconst
      5 import localization
      6 import utillib
      7 from carbon.common.script.sys.service import Service
      8 from eve.client.script.ui.util.uix import GetLightYearDistance
      9 from eve.common.script.sys import idCheckers
     10 from eve.common.script.sys.idCheckers import IsNPC, IsPlayerCorporation
     11 from eve.common.script.sys.rowset import IndexRowset
     12 from eve.common.script.util import facwarCommon
     13 from eveexceptions import UserError
     14 from eve.common.script.util.facwarCommon import GetFwFactionIDForNpcCorp, GetAllFWFactions, IsAnyFWFaction, IsCombatEnemyFaction, IsOccupierFWFaction, IsFwNpcCorp
     15 from eveuniverse.security import is_low_sec_or_lower_solar_system
     16 from fwwarzone.client.facwarUtil import GetHardcodedFwFactionInStation
     17 from npcs.npccorporations import get_corporation_faction_id
     18 import eve.common.lib.appConst as appConst
     19 import random
     20 from player_messaging.client.ui_message import prompt_player_fsd_dialog
     21 
     22 class FactionalWarfare(Service):
     23     __exportedcalls__ = {'JoinFactionAsAlliance': [],
     24      'JoinFactionAsCorporation': [],
     25      'JoinFactionAsCharacter': [],
     26      'LeaveFactionAsCorporation': [],
     27      'LeaveFactionAsAlliance': [],
     28      'WithdrawJoinFactionAsAlliance': [],
     29      'WithdrawJoinFactionAsCorporation': [],
     30      'WithdrawLeaveFactionAsAlliance': [],
     31      'WithdrawLeaveFactionAsCorporation': [],
     32      'GetCorpFactionalWarStatus': [],
     33      'GetCorporationWarFactionID': [],
     34      'GetFactionCorporations': [],
     35      'GetFactionMilitiaCorporation': [],
     36      'GetCharacterRankInfo': [],
     37      'GetStats_FactionInfo': [],
     38      'GetStats_Personal': [],
     39      'GetStats_Corp': [],
     40      'GetStats_Alliance': [],
     41      'GetStats_CorpPilots': [],
     42      'GetMostDangerousSystems': [],
     43      'CheckForSafeSystem': [],
     44      'GetAllianceWarFactionID': [],
     45      'CheckOwnerInFaction': []}
     46     __guid__ = 'svc.facwar'
     47     __servicename__ = 'facwar'
     48     __displayname__ = 'Factional Warfare'
     49     __notifyevents__ = ['OnNPCStandingChange', 'OnSolarSystemLPChange', 'OnSessionChanged']
     50     __dependencies__ = ['loyaltyPointsWalletSvc']
     51 
     52     def __init__(self):
     53         Service.__init__(self)
     54         self.warFactionByOwner = {}
     55         self.topStats = None
     56         self.remoteFacWarMgr = None
     57         self.solarSystemLPs = {}
     58 
     59     def Run(self, memStream = None):
     60         self.LogInfo('Starting Factional Warfare Svc')
     61         self.objectCaching = sm.GetService('objectCaching')
     62 
     63     @property
     64     def facWarMgr(self):
     65         if self.remoteFacWarMgr is None:
     66             self.remoteFacWarMgr = sm.RemoteSvc('facWarMgr')
     67         return self.remoteFacWarMgr
     68 
     69     def OnSolarSystemLPChange(self, oldpoints, newpoints):
     70         self.LogInfo('OnSolarSystemLPChange: ', oldpoints, newpoints)
     71         self.solarSystemLPs[session.solarsystemid2] = newpoints
     72         sm.GetService('infoPanel').UpdateFactionalWarfarePanel()
     73 
     74     def OnSessionChanged(self, isRemote, sess, change):
     75         if 'warfactionid' in change:
     76             self._RefreshCache()
     77 
     78     def GetSolarSystemUpgradeLevel(self, solarsystemID):
     79         if solarsystemID in self.solarSystemLPs:
     80             points = self.solarSystemLPs[solarsystemID]
     81             return facwarCommon.GetLPUpgradeLevel(points)
     82         else:
     83             factionID = self.GetSystemOccupier(solarsystemID)
     84             if IsOccupierFWFaction(factionID):
     85                 warZoneInfo = self.GetFacWarZoneInfo(factionID)
     86                 return warZoneInfo.systemUpgradeLevel.get(solarsystemID, None)
     87             return None
     88 
     89     def GetMostDangerousSystems(self):
     90         historyDB = sm.RemoteSvc('map').GetHistory(const.mapHistoryStatFacWarKills, 24)
     91         dangerousSystems = []
     92         for each in historyDB:
     93             if each.value1 - each.value2 > 0:
     94                 dangerousSystems.append(utillib.KeyVal(solarSystemID=each.solarSystemID, numKills=each.value1 - each.value2))
     95 
     96         dangerousSystems.sort(lambda x, y: cmp(y.numKills, x.numKills))
     97         return dangerousSystems
     98 
     99     def GetCorporationWarFactionID(self, corpID):
    100         if idCheckers.IsNPC(corpID):
    101             factionID = GetFwFactionIDForNpcCorp(corpID)
    102             if factionID:
    103                 return factionID
    104             return None
    105         ret = self.facWarMgr.GetCorporationWarFactionID(corpID)
    106         if not ret:
    107             return None
    108         return ret
    109 
    110     def GetFactionCorporations(self, factionID):
    111         return self.facWarMgr.GetFactionCorporations(factionID)
    112 
    113     def GetAllianceWarFactionID(self, allianceID):
    114         return self.facWarMgr.GetAllianceWarFactionID(allianceID)
    115 
    116     def GetFactionIDByRaceID(self, raceID):
    117         return appConst.factionByRace.get(raceID, None)
    118 
    119     def GetSolarSystemsOccupiedByFactions(self, factionIDs):
    120         fwWarzoneSvc = sm.GetService('fwWarzoneSvc')
    121         occupationStatesBySolarsystemByWarzone = fwWarzoneSvc.GetAllOccupationStates()
    122         occupierBySolarsystem = {}
    123         for occupationStatesBySolarsystem in occupationStatesBySolarsystemByWarzone.itervalues():
    124             for solarsystemID, occupationState in occupationStatesBySolarsystem.iteritems():
    125                 if occupationState.occupierID in factionIDs:
    126                     occupierBySolarsystem[solarsystemID] = occupationState.occupierID
    127 
    128         return occupierBySolarsystem
    129 
    130     def GetSystemOccupier(self, solarSystemID):
    131         fwWarzoneSvc = sm.GetService('fwWarzoneSvc')
    132         occupationState = fwWarzoneSvc.GetOccupationState(solarSystemID)
    133         if occupationState is not None:
    134             return occupationState.occupierID
    135 
    136     def GetFactionWars(self, ownerID):
    137         warFactionID = self.GetCorporationWarFactionID(ownerID)
    138         factionWars = self.GetFactionWarsForWarFactionID(warFactionID)
    139         return factionWars
    140 
    141     def GetFactionWarsForWarFactionID(self, warFactionID):
    142         factionWars = {}
    143         if warFactionID:
    144             factions = GetAllFWFactions()
    145             factionWars = IndexRowset(['warID',
    146              'declaredByID',
    147              'againstID',
    148              'timeDeclared',
    149              'timeFinished',
    150              'retracted',
    151              'retractedBy',
    152              'billID',
    153              'mutual'], [], 'warID')
    154             for i, faction in enumerate(factions):
    155                 if facwarCommon.IsCombatEnemyFaction(faction, warFactionID):
    156                     factionWars[i * -1] = [None,
    157                      faction,
    158                      warFactionID,
    159                      None,
    160                      None,
    161                      None,
    162                      None,
    163                      None,
    164                      True]
    165 
    166         return factionWars
    167 
    168     def GetFactionMilitiaCorporation(self, factionID):
    169         ret = self.facWarMgr.GetFactionMilitiaCorporation(factionID)
    170         if not ret:
    171             return None
    172         return ret
    173 
    174     def GetFacWarZoneInfo(self, factionID):
    175         return sm.RemoteSvc('map').GetFacWarZoneInfo(factionID)
    176 
    177     def GetSystemUpgradeLevelBenefits(self, systemUpgradeLevel):
    178         return facwarCommon.BENEFITS_BY_LEVEL.get(systemUpgradeLevel, [])
    179 
    180     def EnforceOccupierFaction(self, factionID):
    181         if factionID and facwarCommon.IsOccupierFWFaction(factionID):
    182             return factionID
    183         return self.GetFactionIDByRaceID(session.raceID)
    184 
    185     def GetPreferredOccupierFactionID(self):
    186         factionID = self._GetActiveOccupierFactionID()
    187         return self.EnforceOccupierFaction(factionID)
    188 
    189     def _GetActiveOccupierFactionID(self):
    190         if session.warfactionid:
    191             if facwarCommon.IsOccupierFWFaction(session.warfactionid):
    192                 return session.warfactionid
    193             enemies = facwarCommon.GetInsurgencyEnemyFactions(session.warfactionid)
    194             if enemies:
    195                 return enemies[0]
    196         factionIDs = self.CheckStationElegibleForMilitia()
    197         if factionIDs:
    198             return factionIDs[0]
    199         occupierID = self.GetSystemOccupier(session.solarsystemid2)
    200         if occupierID:
    201             return occupierID
    202 
    203     def JoinFactionAsCharacter(self, factionID, warfactionid):
    204         if warfactionid:
    205             alreadyInMilitiaLabel = localization.GetByLabel('UI/FactionWarfare/AlreadyInMilitia')
    206             prompt_player_fsd_dialog('CustomInfo', {'info': alreadyInMilitiaLabel})
    207             return
    208         if IsPlayerCorporation(session.corpid):
    209             header = localization.GetByLabel('UI/FactionWarfare/leaveYourCorpForFWQuestion')
    210             question = localization.GetByLabel('UI/FactionWarfare/leaveYourCorpForFWDesc', corpName=cfg.eveowners.Get(session.corpid).name)
    211             leaveCurrentCorpAnswer = prompt_player_fsd_dialog('CustomQuestion', {'header': header,
    212              'question': question}, uiconst.YESNO)
    213             if leaveCurrentCorpAnswer != uiconst.ID_YES:
    214                 return
    215         ownerName = cfg.eveowners.Get(factionID).name
    216         headerLabel = localization.GetByLabel('UI/FactionWarfare/JoinConfirmationHeader')
    217         bodyLabel = localization.GetByLabel('UI/FactionWarfare/JoinConfirmationQuestionPlayer', factionName=ownerName)
    218         ret = prompt_player_fsd_dialog('CustomQuestion', {'header': headerLabel,
    219          'question': bodyLabel}, uiconst.YESNO)
    220         if ret == uiconst.ID_YES:
    221             sm.GetService('sessionMgr').PerformSessionChange('corp.joinmilitia', self.facWarMgr.JoinFactionAsCharacter, factionID)
    222 
    223     def _RefreshCache(self):
    224         invalidate = [('facWarMgr', 'GetMyCharacterRankInfo', ()),
    225          ('facWarMgr', 'GetMyCharacterRankOverview', ()),
    226          ('facWarMgr', 'GetCorpFactionalWarStatus', ()),
    227          ('corporationSvc', 'GetEmploymentRecord', (session.charid,))]
    228         self.objectCaching.InvalidateCachedMethodCalls(invalidate)
    229 
    230     def JoinFactionAsAlliance(self, factionID, warfactionid):
    231         ownerName = cfg.eveowners.Get(factionID).name
    232         headerLabel = localization.GetByLabel('UI/FactionWarfare/JoinConfirmationHeader')
    233         bodyLabel = localization.GetByLabel('UI/FactionWarfare/JoinConfirmationQuestionAlliance', factionName=ownerName)
    234         if warfactionid:
    235             alreadyInMilitiaLabel = localization.GetByLabel('UI/FactionWarfare/AlreadyInMilitia')
    236             prompt_player_fsd_dialog('CustomInfo', {'info': alreadyInMilitiaLabel})
    237             return
    238         ret = prompt_player_fsd_dialog('CustomQuestion', {'header': headerLabel,
    239          'question': bodyLabel}, uiconst.YESNO)
    240         if ret == uiconst.ID_YES:
    241             self.facWarMgr.JoinFactionAsAlliance(factionID)
    242             self.objectCaching.InvalidateCachedMethodCalls([('facWarMgr', 'GetCorpFactionalWarStatus', ())])
    243             sm.ScatterEvent('OnJoinMilitia')
    244 
    245     def JoinFactionAsCorporation(self, factionID, warfactionid):
    246         ownerName = cfg.eveowners.Get(factionID).name
    247         headerLabel = localization.GetByLabel('UI/FactionWarfare/JoinConfirmationHeader')
    248         bodyLabel = localization.GetByLabel('UI/FactionWarfare/JoinConfirmationQuestionCorp', factionName=ownerName)
    249         if warfactionid:
    250             alreadyInMilitiaLabel = localization.GetByLabel('UI/FactionWarfare/AlreadyInMilitia')
    251             prompt_player_fsd_dialog('CustomInfo', {'info': alreadyInMilitiaLabel})
    252             return
    253         ret = prompt_player_fsd_dialog('CustomQuestion', {'header': headerLabel,
    254          'question': bodyLabel}, uiconst.YESNO)
    255         if ret == uiconst.ID_YES:
    256             self.facWarMgr.JoinFactionAsCorporation(factionID)
    257             self.objectCaching.InvalidateCachedMethodCalls([('facWarMgr', 'GetCorpFactionalWarStatus', ())])
    258             sm.ScatterEvent('OnJoinMilitia')
    259 
    260     def LeaveFactionAsAlliance(self, factionID):
    261         self.facWarMgr.LeaveFactionAsAlliance(factionID)
    262         self.objectCaching.InvalidateCachedMethodCalls([('facWarMgr', 'GetCorpFactionalWarStatus', ())])
    263 
    264     def LeaveFactionAsCorporation(self, factionID):
    265         self.facWarMgr.LeaveFactionAsCorporation(factionID)
    266         self.objectCaching.InvalidateCachedMethodCalls([('facWarMgr', 'GetCorpFactionalWarStatus', ())])
    267 
    268     def WithdrawJoinFactionAsAlliance(self, factionID):
    269         self.facWarMgr.WithdrawJoinFactionAsAlliance(factionID)
    270         self.objectCaching.InvalidateCachedMethodCalls([('facWarMgr', 'GetCorpFactionalWarStatus', ())])
    271 
    272     def WithdrawJoinFactionAsCorporation(self, factionID):
    273         self.facWarMgr.WithdrawJoinFactionAsCorporation(factionID)
    274         self.objectCaching.InvalidateCachedMethodCalls([('facWarMgr', 'GetCorpFactionalWarStatus', ())])
    275 
    276     def WithdrawLeaveFactionAsAlliance(self, factionID):
    277         self.facWarMgr.WithdrawLeaveFactionAsAlliance(factionID)
    278         self.objectCaching.InvalidateCachedMethodCalls([('facWarMgr', 'GetCorpFactionalWarStatus', ())])
    279 
    280     def WithdrawLeaveFactionAsCorporation(self, factionID):
    281         self.facWarMgr.WithdrawLeaveFactionAsCorporation(factionID)
    282         self.objectCaching.InvalidateCachedMethodCalls([('facWarMgr', 'GetCorpFactionalWarStatus', ())])
    283 
    284     def GetCorpFactionalWarStatus(self):
    285         return self.facWarMgr.GetCorpFactionalWarStatus()
    286 
    287     def GetCharacterRankInfo(self, charID):
    288         if charID == session.charid:
    289             return self.facWarMgr.GetMyCharacterRankInfo()
    290         else:
    291             return self.facWarMgr.GetCharacterRankInfo(charID)
    292 
    293     def GetCharacterRankOverview(self, charID):
    294         if not charID == session.charid:
    295             return None
    296         return self.facWarMgr.GetMyCharacterRankOverview()
    297 
    298     def IsCharacterInFwCooldown(self):
    299         now = gametime.GetWallclockTime()
    300         cooldownTimestamp = sm.GetService('fwEnlistmentSvc').GetEnlistmentCooldownTimestamp()
    301         if cooldownTimestamp > gametime.GetWallclockTime():
    302             return True
    303         employmentHistory = sm.RemoteSvc('corporationSvc').GetEmploymentRecord(session.charid)
    304         yesterday = now - const.DAY
    305         for job in employmentHistory:
    306             if job.startDate > yesterday:
    307                 if IsFwNpcCorp(job.corporationID):
    308                     return True
    309             else:
    310                 break
    311 
    312         return False
    313 
    314     def RefreshCorps(self):
    315         return self.facWarMgr.RefreshCorps()
    316 
    317     def OnNPCStandingChange(self, fromID, newStanding, oldStanding):
    318         if session.warfactionid and fromID == self.GetFactionMilitiaCorporation(session.warfactionid):
    319             oldrank = self.GetCharacterRankInfo(session.charid).currentRank
    320             if oldrank != min(max(int(newStanding), 0), 9):
    321                 newrank = self.facWarMgr.CheckForRankChange()
    322                 if newrank is not None and oldrank != newrank:
    323                     self.DoOnRankChange(oldrank, newrank)
    324         invalidate = [('facWarMgr', 'GetMyCharacterRankInfo', ()), ('facWarMgr', 'GetMyCharacterRankOverview', ())]
    325         self.objectCaching.InvalidateCachedMethodCalls(invalidate)
    326 
    327     def DoOnRankChange(self, oldrank, newrank):
    328         messageID = 'RankGained' if newrank > oldrank else 'RankLost'
    329         rankLabel, rankDescription = self.GetRankLabel(session.warfactionid, newrank)
    330         try:
    331             prompt_player_fsd_dialog(messageID, {'rank': rankLabel})
    332         except:
    333             sys.exc_clear()
    334 
    335         sm.ScatterEvent('OnRankChange', oldrank, newrank)
    336 
    337     def GetStats_FactionInfo(self):
    338         return self.facWarMgr.GetStats_FactionInfo()
    339 
    340     def GetStats_Personal(self):
    341         header = ['you', 'top', 'all']
    342         data = {'killsY': {'you': 0,
    343                     'top': 0,
    344                     'all': 0},
    345          'killsLW': {'you': 0,
    346                      'top': 0,
    347                      'all': 0},
    348          'killsTotal': {'you': 0,
    349                         'top': 0,
    350                         'all': 0},
    351          'vpY': {'you': 0,
    352                  'top': 0,
    353                  'all': 0},
    354          'vpLW': {'you': 0,
    355                   'top': 0,
    356                   'all': 0},
    357          'vpTotal': {'you': 0,
    358                      'top': 0,
    359                      'all': 0}}
    360         if not self.topStats:
    361             self.topStats = self.facWarMgr.GetStats_TopAndAllKillsAndVPs()
    362         for k in ('killsY', 'killsLW', 'killsTotal', 'vpY', 'vpLW', 'vpTotal'):
    363             data[k]['top'] = self.topStats[0][const.groupCharacter][k]
    364             data[k]['all'] = self.topStats[1][const.groupCharacter][k]
    365 
    366         for k, v in self.GetStats_Character().items():
    367             data[k]['you'] = v
    368 
    369         return {'header': header,
    370          'data': data}
    371 
    372     def GetStats_Character(self):
    373         return self.facWarMgr.GetStats_Character()
    374 
    375     def GetStats_Corp(self, corpID):
    376         header = ['your', 'top', 'all']
    377         data = {'killsY': {'your': 0,
    378                     'top': 0,
    379                     'all': 0},
    380          'killsLW': {'your': 0,
    381                      'top': 0,
    382                      'all': 0},
    383          'killsTotal': {'your': 0,
    384                         'top': 0,
    385                         'all': 0},
    386          'vpY': {'your': 0,
    387                  'top': 0,
    388                  'all': 0},
    389          'vpLW': {'your': 0,
    390                   'top': 0,
    391                   'all': 0},
    392          'vpTotal': {'your': 0,
    393                      'top': 0,
    394                      'all': 0}}
    395         if not self.topStats:
    396             self.topStats = self.facWarMgr.GetStats_TopAndAllKillsAndVPs()
    397         for k in ('killsY', 'killsLW', 'killsTotal', 'vpY', 'vpLW', 'vpTotal'):
    398             data[k]['top'] = self.topStats[0][const.groupCorporation][k]
    399             data[k]['all'] = self.topStats[1][const.groupCorporation][k]
    400 
    401         for k, v in self.facWarMgr.GetStats_Corp().items():
    402             data[k]['your'] = v
    403 
    404         return {'header': header,
    405          'data': data}
    406 
    407     def GetStats_Alliance(self, allianceID):
    408         header = ['your', 'top', 'all']
    409         data = {'killsY': {'your': 0,
    410                     'top': 0,
    411                     'all': 0},
    412          'killsLW': {'your': 0,
    413                      'top': 0,
    414                      'all': 0},
    415          'killsTotal': {'your': 0,
    416                         'top': 0,
    417                         'all': 0},
    418          'vpY': {'your': 0,
    419                  'top': 0,
    420                  'all': 0},
    421          'vpLW': {'your': 0,
    422                   'top': 0,
    423                   'all': 0},
    424          'vpTotal': {'your': 0,
    425                      'top': 0,
    426                      'all': 0}}
    427         if not self.topStats:
    428             self.topStats = self.facWarMgr.GetStats_TopAndAllKillsAndVPs()
    429         for k in ('killsY', 'killsLW', 'killsTotal', 'vpY', 'vpLW', 'vpTotal'):
    430             data[k]['top'] = self.topStats[0][const.groupAlliance][k]
    431             data[k]['all'] = self.topStats[1][const.groupAlliance][k]
    432 
    433         for k, v in self.facWarMgr.GetStats_Alliance().items():
    434             data[k]['your'] = v
    435 
    436         return {'header': header,
    437          'data': data}
    438 
    439     def GetStats_Militia(self):
    440         return self.facWarMgr.GetStats_Militia()
    441 
    442     def GetStats_CorpPilots(self):
    443         return self.facWarMgr.GetStats_CorpPilots()
    444 
    445     def CheckOwnerInFaction(self, ownerID):
    446         if ownerID not in self.warFactionByOwner:
    447             factionID = get_corporation_faction_id(ownerID)
    448             if factionID and IsAnyFWFaction(factionID):
    449                 self.warFactionByOwner[ownerID] = factionID
    450         return self.warFactionByOwner.get(ownerID, None)
    451 
    452     def CheckForSafeSystem(self, dockableItem, factionID, solarSystemID = None):
    453         if is_low_sec_or_lower_solar_system(solarSystemID or session.solarsystemid2):
    454             return True
    455         if IsNPC(dockableItem.ownerID):
    456             fosi = get_corporation_faction_id(dockableItem.ownerID)
    457             if fosi is None:
    458                 return True
    459         foss = sm.GetService('faction').GetFactionOfSolarSystem(solarSystemID or session.solarsystemid2)
    460         if IsCombatEnemyFaction(factionID, foss):
    461             return False
    462         return True
    463 
    464     def CheckStationElegibleForMilitia(self):
    465         if session.warfactionid:
    466             return [session.warfactionid]
    467         if not session.stationid:
    468             return []
    469         factionIDs = self.GetCurrentStationFactionIDs()
    470         if factionIDs:
    471             return factionIDs
    472         return []
    473 
    474     def GetCurrentStationFactionIDs(self):
    475         factionIDs = []
    476         if not session.stationid:
    477             return factionIDs
    478         ownerID = sm.GetService('station').stationItem.ownerID
    479         if ownerID:
    480             factionID = self.CheckOwnerInFaction(ownerID)
    481             if factionID:
    482                 factionIDs.append(factionID)
    483         hardCodedFactions = GetHardcodedFwFactionInStation(session.stationid, session.solarsystemid2)
    484         factionIDs.extend(hardCodedFactions)
    485         random.shuffle(factionIDs, random.seed(session.charid))
    486         return factionIDs
    487 
    488     def GetRankLabel(self, factionID, rank):
    489         rank = min(9, rank)
    490         rankLabel, rankDescription = ('', '')
    491         if rank < 0:
    492             rankLabel = localization.GetByLabel('UI/FactionWarfare/Ranks/NoRank')
    493             rankDescription = ''
    494         else:
    495             rankPath, descPath = RankLabelsByFactionID.get((factionID, rank), ('UI/FactionWarfare/Ranks/NoRank', 'UI/FactionWarfare/Ranks/NoRank'))
    496             rankLabel = localization.GetByLabel(rankPath)
    497             rankDescription = localization.GetByLabel(descPath)
    498         return (rankLabel, rankDescription)
    499 
    500     def GetSolarSystemLPs(self, solarSystemID = None):
    501         if not solarSystemID:
    502             solarSystemID = session.solarsystemid2
    503         if not sm.GetService('fwWarzoneSvc').IsWarzoneSolarSystem(solarSystemID):
    504             return 0
    505         if solarSystemID not in self.solarSystemLPs:
    506             self.solarSystemLPs[solarSystemID] = self.facWarMgr.GetSolarSystemLPs(solarSystemID)
    507         return self.solarSystemLPs[solarSystemID]
    508 
    509     def DonateLPsToSolarSystem(self, pointsDonated, pointsToIhub):
    510         pointsDonated = max(pointsDonated, const.facwarMinLPDonation)
    511         militiaCorpID = self.GetFactionMilitiaCorporation(session.warfactionid)
    512         if militiaCorpID is None:
    513             raise RuntimeError("Don't know the militia corp for faction", session.warfactionid)
    514         pointsWithCorp = self.loyaltyPointsWalletSvc.GetCharacterWalletLPBalance(militiaCorpID)
    515         if pointsDonated > pointsWithCorp:
    516             militiaName = cfg.eveowners.Get(militiaCorpID).ownerName
    517             raise UserError('FacWarCantDonateSoMuch', {'militiaName': militiaName,
    518              'points': pointsWithCorp})
    519         solarSystemLPs = self.GetSolarSystemLPs()
    520         if pointsToIhub + solarSystemLPs > const.facwarSolarSystemMaxLPPool:
    521             militiaName = cfg.eveowners.Get(militiaCorpID).ownerName
    522             maxPointsToAdd = const.facwarSolarSystemMaxLPPool - solarSystemLPs
    523             raise UserError('FacWarPoolOverloaded', {'militiaName': militiaName,
    524              'points': maxPointsToAdd})
    525         return self.facWarMgr.DonateLPsToSolarSystem(pointsDonated, pointsToIhub)
    526 
    527     def GetNearestFactionWarfareStationData(self, preferredFaction = None, fallbackToLightYears = False):
    528         stations = sm.RemoteSvc('map').GetStationInfo()
    529         warFactionsByOwner = sm.GetService('starmap').GetWarFactionByOwner(stations)
    530         factionStationsBySolarSystem = {}
    531         for stationRow in stations:
    532             stationID = stationRow.stationID
    533             solarSystemID = stationRow.solarSystemID
    534             ownerID = stationRow.ownerID
    535             factionID = warFactionsByOwner.get(ownerID, None)
    536             hardCocedFactionIDs = list(GetHardcodedFwFactionInStation(stationID, session.solarsystemid2))
    537             factionIDs = filter(None, [factionID] + hardCocedFactionIDs)
    538             if factionIDs:
    539                 if preferredFaction in factionIDs:
    540                     factionStationsBySolarSystem[solarSystemID] = stationID
    541                 elif preferredFaction is None:
    542                     factionStationsBySolarSystem[solarSystemID] = stationID
    543 
    544         nearestStationID = None
    545         jumpsToNearestStation = 999999
    546         for solarSystemID, stationID in factionStationsBySolarSystem.iteritems():
    547             dist = sm.GetService('clientPathfinderService').GetJumpCount(session.solarsystemid2, solarSystemID)
    548             if dist <= jumpsToNearestStation:
    549                 jumpsToNearestStation = dist
    550                 nearestStationID = stationID
    551 
    552         if nearestStationID is None and fallbackToLightYears:
    553             lyToNearestStation = 999999
    554             for solarSystemID, stationID in factionStationsBySolarSystem.iteritems():
    555                 lyDistance = GetLightYearDistance(session.solarsystemid2, solarSystemID, False)
    556                 if lyDistance <= lyToNearestStation:
    557                     lyToNearestStation = lyDistance
    558                     nearestStationID = stationID
    559 
    560         return (jumpsToNearestStation, nearestStationID)
    561 
    562 
    563 RankLabelsByFactionID = {(const.factionCaldariState, 0): ('UI/FactionWarfare/Ranks/RankCaldari0', 'UI/FactionWarfare/Ranks/RankDescriptionCaldari0'),
    564  (const.factionCaldariState, 1): ('UI/FactionWarfare/Ranks/RankCaldari1', 'UI/FactionWarfare/Ranks/RankDescriptionCaldari1'),
    565  (const.factionCaldariState, 2): ('UI/FactionWarfare/Ranks/RankCaldari2', 'UI/FactionWarfare/Ranks/RankDescriptionCaldari2'),
    566  (const.factionCaldariState, 3): ('UI/FactionWarfare/Ranks/RankCaldari3', 'UI/FactionWarfare/Ranks/RankDescriptionCaldari3'),
    567  (const.factionCaldariState, 4): ('UI/FactionWarfare/Ranks/RankCaldari4', 'UI/FactionWarfare/Ranks/RankDescriptionCaldari4'),
    568  (const.factionCaldariState, 5): ('UI/FactionWarfare/Ranks/RankCaldari5', 'UI/FactionWarfare/Ranks/RankDescriptionCaldari5'),
    569  (const.factionCaldariState, 6): ('UI/FactionWarfare/Ranks/RankCaldari6', 'UI/FactionWarfare/Ranks/RankDescriptionCaldari6'),
    570  (const.factionCaldariState, 7): ('UI/FactionWarfare/Ranks/RankCaldari7', 'UI/FactionWarfare/Ranks/RankDescriptionCaldari7'),
    571  (const.factionCaldariState, 8): ('UI/FactionWarfare/Ranks/RankCaldari8', 'UI/FactionWarfare/Ranks/RankDescriptionCaldari8'),
    572  (const.factionCaldariState, 9): ('UI/FactionWarfare/Ranks/RankCaldari9', 'UI/FactionWarfare/Ranks/RankDescriptionCaldari9'),
    573  (const.factionMinmatarRepublic, 0): ('UI/FactionWarfare/Ranks/RankMinmatar0', 'UI/FactionWarfare/Ranks/RankDescriptionMinmatar0'),
    574  (const.factionMinmatarRepublic, 1): ('UI/FactionWarfare/Ranks/RankMinmatar1', 'UI/FactionWarfare/Ranks/RankDescriptionMinmatar1'),
    575  (const.factionMinmatarRepublic, 2): ('UI/FactionWarfare/Ranks/RankMinmatar2', 'UI/FactionWarfare/Ranks/RankDescriptionMinmatar2'),
    576  (const.factionMinmatarRepublic, 3): ('UI/FactionWarfare/Ranks/RankMinmatar3', 'UI/FactionWarfare/Ranks/RankDescriptionMinmatar3'),
    577  (const.factionMinmatarRepublic, 4): ('UI/FactionWarfare/Ranks/RankMinmatar4', 'UI/FactionWarfare/Ranks/RankDescriptionMinmatar4'),
    578  (const.factionMinmatarRepublic, 5): ('UI/FactionWarfare/Ranks/RankMinmatar5', 'UI/FactionWarfare/Ranks/RankDescriptionMinmatar5'),
    579  (const.factionMinmatarRepublic, 6): ('UI/FactionWarfare/Ranks/RankMinmatar6', 'UI/FactionWarfare/Ranks/RankDescriptionMinmatar6'),
    580  (const.factionMinmatarRepublic, 7): ('UI/FactionWarfare/Ranks/RankMinmatar7', 'UI/FactionWarfare/Ranks/RankDescriptionMinmatar7'),
    581  (const.factionMinmatarRepublic, 8): ('UI/FactionWarfare/Ranks/RankMinmatar8', 'UI/FactionWarfare/Ranks/RankDescriptionMinmatar8'),
    582  (const.factionMinmatarRepublic, 9): ('UI/FactionWarfare/Ranks/RankMinmatar9', 'UI/FactionWarfare/Ranks/RankDescriptionMinmatar9'),
    583  (const.factionAmarrEmpire, 0): ('UI/FactionWarfare/Ranks/RankAmarr0', 'UI/FactionWarfare/Ranks/RankDescriptionAmarr0'),
    584  (const.factionAmarrEmpire, 1): ('UI/FactionWarfare/Ranks/RankAmarr1', 'UI/FactionWarfare/Ranks/RankDescriptionAmarr1'),
    585  (const.factionAmarrEmpire, 2): ('UI/FactionWarfare/Ranks/RankAmarr2', 'UI/FactionWarfare/Ranks/RankDescriptionAmarr2'),
    586  (const.factionAmarrEmpire, 3): ('UI/FactionWarfare/Ranks/RankAmarr3', 'UI/FactionWarfare/Ranks/RankDescriptionAmarr3'),
    587  (const.factionAmarrEmpire, 4): ('UI/FactionWarfare/Ranks/RankAmarr4', 'UI/FactionWarfare/Ranks/RankDescriptionAmarr4'),
    588  (const.factionAmarrEmpire, 5): ('UI/FactionWarfare/Ranks/RankAmarr5', 'UI/FactionWarfare/Ranks/RankDescriptionAmarr5'),
    589  (const.factionAmarrEmpire, 6): ('UI/FactionWarfare/Ranks/RankAmarr6', 'UI/FactionWarfare/Ranks/RankDescriptionAmarr6'),
    590  (const.factionAmarrEmpire, 7): ('UI/FactionWarfare/Ranks/RankAmarr7', 'UI/FactionWarfare/Ranks/RankDescriptionAmarr7'),
    591  (const.factionAmarrEmpire, 8): ('UI/FactionWarfare/Ranks/RankAmarr8', 'UI/FactionWarfare/Ranks/RankDescriptionAmarr8'),
    592  (const.factionAmarrEmpire, 9): ('UI/FactionWarfare/Ranks/RankAmarr9', 'UI/FactionWarfare/Ranks/RankDescriptionAmarr9'),
    593  (const.factionGallenteFederation, 0): ('UI/FactionWarfare/Ranks/RankGallente0', 'UI/FactionWarfare/Ranks/RankDescriptionGallente0'),
    594  (const.factionGallenteFederation, 1): ('UI/FactionWarfare/Ranks/RankGallente1', 'UI/FactionWarfare/Ranks/RankDescriptionGallente1'),
    595  (const.factionGallenteFederation, 2): ('UI/FactionWarfare/Ranks/RankGallente2', 'UI/FactionWarfare/Ranks/RankDescriptionGallente2'),
    596  (const.factionGallenteFederation, 3): ('UI/FactionWarfare/Ranks/RankGallente3', 'UI/FactionWarfare/Ranks/RankDescriptionGallente3'),
    597  (const.factionGallenteFederation, 4): ('UI/FactionWarfare/Ranks/RankGallente4', 'UI/FactionWarfare/Ranks/RankDescriptionGallente4'),
    598  (const.factionGallenteFederation, 5): ('UI/FactionWarfare/Ranks/RankGallente5', 'UI/FactionWarfare/Ranks/RankDescriptionGallente5'),
    599  (const.factionGallenteFederation, 6): ('UI/FactionWarfare/Ranks/RankGallente6', 'UI/FactionWarfare/Ranks/RankDescriptionGallente6'),
    600  (const.factionGallenteFederation, 7): ('UI/FactionWarfare/Ranks/RankGallente7', 'UI/FactionWarfare/Ranks/RankDescriptionGallente7'),
    601  (const.factionGallenteFederation, 8): ('UI/FactionWarfare/Ranks/RankGallente8', 'UI/FactionWarfare/Ranks/RankDescriptionGallente8'),
    602  (const.factionGallenteFederation, 9): ('UI/FactionWarfare/Ranks/RankGallente9', 'UI/FactionWarfare/Ranks/RankDescriptionGallente9'),
    603  (const.factionAngelCartel, 0): ('UI/FactionWarfare/Ranks/RankAngel0', 'UI/FactionWarfare/Ranks/RankDescriptionAngel0'),
    604  (const.factionAngelCartel, 1): ('UI/FactionWarfare/Ranks/RankAngel1', 'UI/FactionWarfare/Ranks/RankDescriptionAngel1'),
    605  (const.factionAngelCartel, 2): ('UI/FactionWarfare/Ranks/RankAngel2', 'UI/FactionWarfare/Ranks/RankDescriptionAngel2'),
    606  (const.factionAngelCartel, 3): ('UI/FactionWarfare/Ranks/RankAngel3', 'UI/FactionWarfare/Ranks/RankDescriptionAngel3'),
    607  (const.factionAngelCartel, 4): ('UI/FactionWarfare/Ranks/RankAngel4', 'UI/FactionWarfare/Ranks/RankDescriptionAngel4'),
    608  (const.factionAngelCartel, 5): ('UI/FactionWarfare/Ranks/RankAngel5', 'UI/FactionWarfare/Ranks/RankDescriptionAngel5'),
    609  (const.factionAngelCartel, 6): ('UI/FactionWarfare/Ranks/RankAngel6', 'UI/FactionWarfare/Ranks/RankDescriptionAngel6'),
    610  (const.factionAngelCartel, 7): ('UI/FactionWarfare/Ranks/RankAngel7', 'UI/FactionWarfare/Ranks/RankDescriptionAngel7'),
    611  (const.factionAngelCartel, 8): ('UI/FactionWarfare/Ranks/RankAngel8', 'UI/FactionWarfare/Ranks/RankDescriptionAngel8'),
    612  (const.factionAngelCartel, 9): ('UI/FactionWarfare/Ranks/RankAngel9', 'UI/FactionWarfare/Ranks/RankDescriptionAngel9'),
    613  (const.factionGuristasPirates, 0): ('UI/FactionWarfare/Ranks/RankGuristas0', 'UI/FactionWarfare/Ranks/RankDescriptionGuristas0'),
    614  (const.factionGuristasPirates, 1): ('UI/FactionWarfare/Ranks/RankGuristas1', 'UI/FactionWarfare/Ranks/RankDescriptionGuristas1'),
    615  (const.factionGuristasPirates, 2): ('UI/FactionWarfare/Ranks/RankGuristas2', 'UI/FactionWarfare/Ranks/RankDescriptionGuristas2'),
    616  (const.factionGuristasPirates, 3): ('UI/FactionWarfare/Ranks/RankGuristas3', 'UI/FactionWarfare/Ranks/RankDescriptionGuristas3'),
    617  (const.factionGuristasPirates, 4): ('UI/FactionWarfare/Ranks/RankGuristas4', 'UI/FactionWarfare/Ranks/RankDescriptionGuristas4'),
    618  (const.factionGuristasPirates, 5): ('UI/FactionWarfare/Ranks/RankGuristas5', 'UI/FactionWarfare/Ranks/RankDescriptionGuristas5'),
    619  (const.factionGuristasPirates, 6): ('UI/FactionWarfare/Ranks/RankGuristas6', 'UI/FactionWarfare/Ranks/RankDescriptionGuristas6'),
    620  (const.factionGuristasPirates, 7): ('UI/FactionWarfare/Ranks/RankGuristas7', 'UI/FactionWarfare/Ranks/RankDescriptionGuristas7'),
    621  (const.factionGuristasPirates, 8): ('UI/FactionWarfare/Ranks/RankGuristas8', 'UI/FactionWarfare/Ranks/RankDescriptionGuristas8'),
    622  (const.factionGuristasPirates, 9): ('UI/FactionWarfare/Ranks/RankGuristas9', 'UI/FactionWarfare/Ranks/RankDescriptionGuristas9')}