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

searchUtil.py (16862B)


      1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\eve\client\script\ui\util\searchUtil.py
      2 from collections import defaultdict
      3 import localization
      4 import evetypes
      5 from eve.client.script.ui.control.entries.generic import Generic
      6 from eve.client.script.ui.control.entries.item import Item
      7 from eve.client.script.ui.control.entries.universe import SolarSystem, SolarSystemStructure
      8 from eve.client.script.ui.control.entries.util import GetFromClass
      9 from eve.client.script.ui.control.listgroup import ListGroup
     10 from eve.client.script.ui.shared.userentry import AgentEntry, User
     11 from eve.common.script.util.systemExclusions import IsValidDestination
     12 from eve.common.lib import appConst
     13 from eve.common.script.search import const as search_const
     14 from eveexceptions import UserError
     15 from globalConfig.getFunctions import ArePointerLinksActive
     16 from localization import GetByLabel
     17 from bannedwords.client import bannedwords
     18 SEARCHBY_OPTIONS = ([GetByLabel('UI/Search/UniversalSearch/PartialTerms'), search_const.MatchBy.partial_terms],
     19  [GetByLabel('UI/Search/UniversalSearch/ExactTerms'), search_const.MatchBy.exact_terms],
     20  [GetByLabel('UI/Search/UniversalSearch/ExactPhrase'), search_const.MatchBy.exact_phrase],
     21  [GetByLabel('UI/Search/UniversalSearch/OnlyExactPhrase'), search_const.MatchBy.exact_phrase_only])
     22 RESULT_ORDER = (search_const.ResultType.agent,
     23  search_const.ResultType.character,
     24  search_const.ResultType.faction,
     25  search_const.ResultType.corporation,
     26  search_const.ResultType.alliance,
     27  search_const.ResultType.region,
     28  search_const.ResultType.solar_system,
     29  search_const.ResultType.station,
     30  search_const.ResultType.structure,
     31  search_const.ResultType.structure_with_inlined_data,
     32  search_const.ResultType.constellation,
     33  search_const.ResultType.item_type)
     34 RESULT_LABELS = {search_const.ResultType.agent: 'UI/Search/UniversalSearch/Agents',
     35  search_const.ResultType.character: 'UI/Search/UniversalSearch/Characters',
     36  search_const.ResultType.faction: 'UI/Search/UniversalSearch/Factions',
     37  search_const.ResultType.corporation: 'UI/Search/UniversalSearch/Corporations',
     38  search_const.ResultType.alliance: 'UI/Search/UniversalSearch/Alliances',
     39  search_const.ResultType.region: 'UI/Search/UniversalSearch/Regions',
     40  search_const.ResultType.solar_system: 'UI/Search/UniversalSearch/SolarSystems',
     41  search_const.ResultType.station: 'UI/Common/LocationTypes/Stations',
     42  search_const.ResultType.structure: 'UI/Common/LocationTypes/Structures',
     43  search_const.ResultType.structure_with_inlined_data: 'UI/Common/LocationTypes/Structures',
     44  search_const.ResultType.constellation: 'UI/Search/UniversalSearch/Constellations',
     45  search_const.ResultType.item_type: 'UI/Search/UniversalSearch/Types'}
     46 
     47 def GetSearchByChoices():
     48     return SEARCHBY_OPTIONS
     49 
     50 
     51 def GetResultsScrollList(searchStr, groupIDList, searchBy = search_const.MatchBy.partial_terms, searchWndName = 'mySearch', corpMemberIDs = None):
     52     resultsByType = GetResultsByGroupID(searchStr, groupIDList, searchBy)
     53     return _GetResultsScrollList(resultsByType, corpMemberIDs)
     54 
     55 
     56 def GetResultsInNewWindow(searchStr, groupIDList, searchBy = search_const.MatchBy.partial_terms, searchWndName = 'mySearch', corpMemberIDs = None, includeUiElements = False):
     57     resultsByType = GetResultsByGroupID(searchStr, groupIDList, searchBy)
     58     scrolllist = _GetResultsScrollList(resultsByType, corpMemberIDs)
     59     header = localization.GetByLabel('UI/Common/SearchResults')
     60     numUiElements = 0
     61     if includeUiElements:
     62         uiElementResults, numUiElements = _GetResultsForUiElements(searchStr)
     63         scrolllist += uiElementResults
     64     totalResults = sum([ len(results) for results in resultsByType.values() ])
     65     if totalResults >= search_const.max_result_count:
     66         top = localization.GetByLabel('UI/Search/UniversalSearch/WindowHeaderOverMax', maxNumber=search_const.max_result_count, searchStr=searchStr)
     67     else:
     68         totalResults += numUiElements
     69         top = localization.GetByLabel('UI/Search/UniversalSearch/WindowHeaderNumResults', numResults=totalResults, searchStr=searchStr)
     70     noContentHint = localization.GetByLabel('UI/Search/UniversalSearch/NoResultsReturned', searchStr=searchStr)
     71     from eve.client.script.ui.control.listwindow import ListWindow
     72     chosen = ListWindow.ShowList(scrolllist, 'generic', header, top, 0, isModal=0, minChoices=0, windowName=searchWndName, lstDataIsGrouped=1, unstackable=1, noContentHint=noContentHint, showCollapseBtn=True)
     73     if chosen:
     74         return chosen[1]
     75 
     76 
     77 def _GetResultsScrollList(resultsByType, corpMemberIDs):
     78     scrolllist = []
     79     for resultType in RESULT_ORDER:
     80         if resultType not in resultsByType:
     81             continue
     82         results = resultsByType[resultType]
     83         entryList = GetScrollEntryData(results, resultType, corpMemberIDs)
     84         if entryList:
     85             _AppendScrollGroups(entryList, resultType, scrolllist)
     86 
     87     return scrolllist
     88 
     89 
     90 def _GetResultsForUiElements(searchStr):
     91     if ArePointerLinksActive(sm.GetService('machoNet')):
     92         return sm.GetService('helpPointer').SearchPointers(searchStr)
     93     return ([], 0)
     94 
     95 
     96 def _AppendScrollGroups(entryList, resultType, scrolllist):
     97     if resultType == search_const.ResultType.item_type:
     98         _AppendScrollGroupsInvItems(entryList, resultType, scrolllist)
     99     else:
    100         _AppendScrollGroup(entryList, resultType, scrolllist)
    101 
    102 
    103 def _AppendScrollGroupsInvItems(entryList, resultType, scrolllist):
    104     entriesByCategory = defaultdict(list)
    105     for entry in entryList:
    106         categoryID = evetypes.GetCategoryID(entry['typeID'])
    107         entriesByCategory[categoryID].append(entry)
    108 
    109     for categoryID, entries in sorted(entriesByCategory.items()):
    110         searchGroupID = 'inv_%s_%s' % (resultType, categoryID)
    111         data = GetScrollListGroup(entries, _GetInvItemEntryType(categoryID), evetypes.GetCategoryNameByCategory(categoryID), searchGroupID)
    112         scrolllist.append(GetFromClass(ListGroup, data))
    113 
    114 
    115 def _GetInvItemEntryType(categoryID):
    116     return Item
    117 
    118 
    119 def _AppendScrollGroup(entryList, resultType, scrolllist):
    120     label = localization.GetByLabel(RESULT_LABELS[resultType])
    121     entryType = GetScrollEntryType(resultType)
    122     data = GetScrollListGroup(entryList, entryType, label, str(resultType))
    123     scrolllist.append(GetFromClass(ListGroup, data))
    124 
    125 
    126 def GetScrollListGroup(entryList, entryType, label, searchGroupID):
    127     sectionHeader = localization.GetByLabel('UI/Search/UniversalSearch/SectionHeader', resultType=label, numberReturned=len(entryList))
    128     data = {'GetSubContent': GetSearchSubContent,
    129      'label': sectionHeader,
    130      'groupItems': (entryType, entryList),
    131      'id': ('search_cat', searchGroupID),
    132      'sublevel': 0,
    133      'showlen': 0,
    134      'showicon': 'hide',
    135      'state': 'locked'}
    136     return data
    137 
    138 
    139 def GetScrollEntryData(results, resultType, corpMemberIDs):
    140     entryList = []
    141     if resultType == search_const.ResultType.agent:
    142         for agentID in results:
    143             agentSvc = sm.GetService('agents')
    144             agentInfo = agentSvc.GetAgentByID(agentID)
    145             if agentInfo is None:
    146                 continue
    147             if IsValidDestination(agentInfo.solarsystemID):
    148                 data = {'charID': agentID,
    149                  'sublevel': 0}
    150                 entryList.append(data)
    151 
    152     elif resultType in (search_const.ResultType.corporation,
    153      search_const.ResultType.alliance,
    154      search_const.ResultType.faction,
    155      search_const.ResultType.character):
    156         for ownerID in results:
    157             if corpMemberIDs and ownerID not in corpMemberIDs:
    158                 continue
    159             data = {'charID': ownerID,
    160              'sublevel': 0,
    161              'showinfo': True}
    162             entryList.append(data)
    163 
    164     elif resultType == search_const.ResultType.solar_system:
    165         for itemID in results:
    166             if IsValidDestination(itemID):
    167                 data = {'itemID': itemID,
    168                  'solarSystemID': itemID,
    169                  'typeID': appConst.typeSolarSystem,
    170                  'label': cfg.evelocations.Get(itemID).name,
    171                  'sublevel': 0,
    172                  'showinfo': True}
    173                 entryList.append(data)
    174 
    175     elif resultType == search_const.ResultType.constellation:
    176         for itemID in results:
    177             if IsValidDestination(itemID):
    178                 data = {'itemID': itemID,
    179                  'typeID': appConst.typeConstellation,
    180                  'label': cfg.evelocations.Get(itemID).name,
    181                  'sublevel': 0,
    182                  'showinfo': True}
    183                 entryList.append(data)
    184 
    185     elif resultType == search_const.ResultType.region:
    186         for itemID in results:
    187             if IsValidDestination(itemID):
    188                 data = {'itemID': itemID,
    189                  'typeID': appConst.typeRegion,
    190                  'label': cfg.evelocations.Get(itemID).name,
    191                  'sublevel': 0,
    192                  'showinfo': True}
    193                 entryList.append(data)
    194 
    195     elif resultType == search_const.ResultType.structure:
    196         for itemID in results:
    197             info = sm.GetService('structureDirectory').GetStructureInfo(itemID)
    198             if IsValidDestination(info.solarSystemID):
    199                 data = {'itemID': itemID,
    200                  'solarSystemID': info.solarSystemID,
    201                  'sublevel': 0,
    202                  'typeID': info.typeID,
    203                  'label': info.itemName,
    204                  'showinfo': True}
    205                 entryList.append(data)
    206 
    207     elif resultType == search_const.ResultType.structure_with_inlined_data:
    208         for info in results:
    209             data = {'itemID': info.structureID,
    210              'sublevel': 0,
    211              'typeID': info.typeID,
    212              'label': info.itemName}
    213             entryList.append(data)
    214 
    215     elif resultType == search_const.ResultType.station:
    216         for itemID in results:
    217             station = cfg.stations.Get(itemID)
    218             if IsValidDestination(station.solarSystemID):
    219                 data = {'itemID': itemID,
    220                  'solarSystemID': station.solarSystemID,
    221                  'typeID': station.stationTypeID,
    222                  'label': cfg.evelocations.Get(itemID).name,
    223                  'sublevel': 0,
    224                  'showinfo': True}
    225                 entryList.append(data)
    226 
    227     elif resultType == search_const.ResultType.item_type:
    228         for typeID in results:
    229             if not evetypes.Exists(typeID):
    230                 continue
    231             data = {'itemID': None,
    232              'typeID': typeID,
    233              'getIcon': 1,
    234              'label': evetypes.GetName(typeID),
    235              'sublevel': 0,
    236              'showinfo': True}
    237             entryList.append(data)
    238 
    239     return entryList
    240 
    241 
    242 def GetScrollEntryType(resultType):
    243     if resultType == search_const.ResultType.agent:
    244         return AgentEntry
    245     elif resultType in (search_const.ResultType.corporation,
    246      search_const.ResultType.alliance,
    247      search_const.ResultType.faction,
    248      search_const.ResultType.character):
    249         return User
    250     elif resultType == search_const.ResultType.item_type:
    251         return Item
    252     elif resultType == search_const.ResultType.structure:
    253         return SolarSystemStructure
    254     elif resultType in (search_const.ResultType.solar_system, search_const.ResultType.station):
    255         return SolarSystem
    256     else:
    257         return Generic
    258 
    259 
    260 def GetResultsByGroupID(searchStr, groupIDList, searchBy = search_const.MatchBy.partial_terms):
    261     searchStr = _FormatSearchInput(searchStr)
    262     _ValidateSearchInput(searchStr, searchBy)
    263     searchMgr = sm.ProxySvc('search')
    264     resultsByType = searchMgr.Query(searchStr, groupIDList, exact=searchBy)
    265     if resultsByType:
    266         _PrimeResults(resultsByType)
    267     _SortResults(resultsByType)
    268     return resultsByType or {}
    269 
    270 
    271 def _SortResults(resultsByType):
    272     for resultID, results in resultsByType.iteritems():
    273         if resultID in search_const.location_result_types:
    274             results.sort(key=lambda x: cfg.evelocations.Get(x).locationName)
    275         elif resultID in search_const.owner_result_types:
    276             results.sort(key=lambda x: cfg.eveowners.Get(x).ownerName)
    277         elif resultID == search_const.ResultType.item_type:
    278             results.sort(key=lambda x: evetypes.GetName(x))
    279 
    280 
    281 def GetResultsList(searchStr, groupIDList, searchBy = search_const.MatchBy.partial_terms, hideNPC = 0, onlyAltName = 0):
    282     searchStr = _FormatSearchInput(searchStr)
    283     _ValidateSearchInput(searchStr, searchBy)
    284     searchMgr = sm.ProxySvc('search')
    285     return searchMgr.QuickQuery(searchStr, groupIDList, hideNPC=hideNPC, onlyAltName=onlyAltName, exact=searchBy)
    286 
    287 
    288 def _FormatSearchInput(searchStr):
    289     searchStr = searchStr.replace('*', '')
    290     searchStr = searchStr.strip()
    291     return searchStr
    292 
    293 
    294 def _ValidateSearchInput(searchStr, exact):
    295     if len(searchStr) < 1:
    296         raise UserError('LookupStringMinimum', {'minimum': 1})
    297     elif len(searchStr) >= 100:
    298         raise UserError('CustomInfo', {'info': localization.GetByLabel('UI/Common/SearchStringTooLong')})
    299     elif exact == search_const.MatchBy.partial_terms and not localization.util.IsTextInConciseLanguage(session.languageID, searchStr):
    300         if len([ x for x in searchStr.split() if len(x) >= search_const.min_wildcard_length ]) == 0:
    301             raise UserError('PartialSearchLessThanMinLength', {'minChars': search_const.min_wildcard_length})
    302     bannedwords.check_search_words_allowed(searchStr)
    303 
    304 
    305 def _PrimeResults(resultsByType):
    306     _PrimeOwners(resultsByType)
    307     _PrimeCorpTickers(resultsByType)
    308     _RemoveNonExistingTypes(resultsByType)
    309 
    310 
    311 def _PrimeCorpTickers(resultsByType):
    312     results = resultsByType.get(search_const.ResultType.corporation, None)
    313     if results:
    314         cfg.corptickernames.Prime(results)
    315 
    316 
    317 def _PrimeOwners(resultsByType):
    318     toPrime = []
    319     for resultType in search_const.owner_result_types:
    320         toPrime.extend(resultsByType.get(resultType, []))
    321 
    322     cfg.eveowners.Prime(toPrime)
    323 
    324 
    325 def _RemoveNonExistingTypes(resultsByType):
    326     if search_const.ResultType.item_type in resultsByType:
    327         results = resultsByType[search_const.ResultType.item_type]
    328         filteredResults = filter(evetypes.Exists, results)
    329         resultsByType[search_const.ResultType.item_type] = filteredResults
    330 
    331 
    332 def GetSearchSubContent(dataX, *args):
    333     scrolllist = []
    334     entryType, typeList = dataX['groupItems']
    335     for data in typeList:
    336         scrolllist.append(GetFromClass(entryType, data))
    337 
    338     return scrolllist
    339 
    340 
    341 def SearchCharacters(searchStr, searchBy = search_const.MatchBy.partial_terms):
    342     scrolllist = GetResultsScrollList(searchStr, [search_const.ResultType.character], searchBy=searchBy)
    343     if len(scrolllist):
    344         return GetSearchSubContent(scrolllist[0])
    345     return []
    346 
    347 
    348 def SearchCharactersInCorp(searchStr, corpMemberIDs):
    349     scrolllist = GetResultsScrollList(searchStr, [search_const.ResultType.character], corpMemberIDs=corpMemberIDs)
    350     if len(scrolllist):
    351         return GetSearchSubContent(scrolllist[0])
    352     return []
    353 
    354 
    355 def SearchCorporations(searchStr, searchBy = search_const.MatchBy.partial_terms):
    356     scrolllist = GetResultsScrollList(searchStr, [search_const.ResultType.corporation], searchBy=searchBy)
    357     if len(scrolllist):
    358         return GetSearchSubContent(scrolllist[0])
    359     return []
    360 
    361 
    362 def IsMatch(searchStr, candidate, exact):
    363     if exact == search_const.MatchBy.partial_terms and not localization.util.IsTextInConciseLanguage(session.languageID, searchStr):
    364         if len([ x for x in searchStr.split() if len(x) >= search_const.min_wildcard_length ]) == 0:
    365             exact = search_const.MatchBy.exact_terms
    366     searchStr = searchStr.lower().strip()
    367     candidate = candidate.lower().strip()
    368     if exact == search_const.MatchBy.partial_terms:
    369         searchTermList = searchStr.split()
    370         candTermList = candidate.lower().split()
    371         matches = True
    372         for searchTerm in searchTermList:
    373             termMatches = False
    374             for candTerm in candTermList:
    375                 if candTerm.startswith(searchTerm):
    376                     termMatches = True
    377                     break
    378 
    379             if not termMatches:
    380                 matches = False
    381                 break
    382 
    383         return matches
    384     if exact == search_const.MatchBy.exact_terms:
    385         candTermList = candidate.split()
    386         return all([ s in candTermList for s in searchStr.split() ])
    387     if exact == search_const.MatchBy.exact_phrase:
    388         searchTermList = searchStr.split()
    389         lBound = 0
    390         uBound = len(searchTermList)
    391         candTermList = candidate.split()
    392         for idx in range(uBound, len(candTermList) + 1):
    393             if searchTermList == candTermList[lBound:idx]:
    394                 return True
    395             lBound += 1
    396 
    397         return False
    398     if exact == search_const.MatchBy.exact_phrase_only:
    399         return searchStr == candidate
    400     raise RuntimeError('Unknown value passed in for exact flag')