fittingWarningsStackingPenalty.py (7816B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\shipfitting\fittingWarningsStackingPenalty.py 2 from __future__ import print_function 3 from collections import defaultdict 4 import evetypes 5 import dogma.data as dogma_data 6 import dogma.const as dogmaConst 7 from brennivin.itertoolsext import Bundle 8 ITEM_MODIFIER = 1 9 NOT_ITEM_MOTIFIER = 2 10 11 def FindModulesWithStackingPenalty(fittedModules): 12 typeIDs = {x for x, _ in fittedModules} 13 nonStackableByTypeID, nonStackableByTypeIDTargeted = _FindModulesWithStackingPenalty(set(typeIDs)) 14 nonStackableAttributes = defaultdict(set) 15 nonStackableAttributesTargeted = defaultdict(set) 16 for eachTypeID, eachFlagID in fittedModules: 17 nonStackable = nonStackableByTypeID.get(eachTypeID, []) 18 nonStackableTarget = nonStackableByTypeIDTargeted.get(eachTypeID, []) 19 if not nonStackable and not nonStackableTarget: 20 continue 21 for x in nonStackable: 22 nonStackableAttributes[x.modifiedAttributeID, x.operation, x.skillTypeID, x.domain].add((eachTypeID, eachFlagID)) 23 24 for x in nonStackableTarget: 25 nonStackableAttributesTargeted[x.modifiedAttributeID, x.operation, x.skillTypeID, x.domain].add((eachTypeID, eachFlagID)) 26 27 return (nonStackableAttributes, nonStackableAttributesTargeted) 28 29 30 def _FindModulesWithStackingPenalty(typeIDs): 31 nonStackableByTypeID = {} 32 nonStackableByTypeIDTargeted = {} 33 ghostFittingEffectCompiler = sm.GetService('ghostFittingEffectCompiler') 34 typesWithPythonEffect = set() 35 pythonEffects = set() 36 for typeID in typeIDs: 37 if not IsModuleOfInterestForStacking(typeID): 38 continue 39 nonStackable = [] 40 nonStackableTargeted = [] 41 effectList = dogma_data.get_type_effects(typeID) 42 for each in effectList: 43 effect = dogma_data.get_effect(each.effectID) 44 if effect.effectCategory == dogmaConst.dgmEffOverload: 45 continue 46 effectFromCompiler = ghostFittingEffectCompiler.effects.get(effect.effectID) 47 if effectFromCompiler and effectFromCompiler.isPythonEffect: 48 domainToUse = 'target' if effect.effectCategory == dogmaConst.dgmEffTarget else 'shipID' 49 modifierInfo = _GetModifierInfoFromPythonEffect(effectFromCompiler, domainToUse) 50 typesWithPythonEffect.add(typeID) 51 pythonEffects.add(effect.effectID) 52 else: 53 modifierInfo = effect.modifierInfo 54 for m in modifierInfo or []: 55 modifiedAttributeID = m.modifiedAttributeID 56 modifyingAttributeID = m.modifyingAttributeID 57 if modifiedAttributeID is None: 58 continue 59 modifiedAttribute = dogma_data.get_attribute(modifiedAttributeID) 60 modifyingAttribute = dogma_data.get_attribute(modifyingAttributeID) 61 if modifiedAttribute.stackable: 62 continue 63 x = Bundle(typeID=typeID, modifiedAttributeID=modifiedAttributeID, modifyingAttributeID=modifyingAttributeID, cat=modifyingAttribute.categoryID, effectID=each.effectID, operation=m.operation, domain=(m.domain, ITEM_MODIFIER if m.func == 'ItemModifier' else NOT_ITEM_MOTIFIER), skillTypeID=m.skillTypeID) 64 if effect.effectCategory == dogmaConst.dgmEffTarget: 65 nonStackableTargeted.append(x) 66 else: 67 modifyingValue = dogma_data.get_type_attribute(typeID, modifyingAttributeID) 68 goodChange = IsItGoodChange(modifyingValue, m.operation, modifiedAttribute.highIsGood) 69 if goodChange: 70 nonStackable.append(x) 71 72 if nonStackable: 73 nonStackableByTypeID[typeID] = nonStackable 74 if nonStackableTargeted: 75 nonStackableByTypeIDTargeted[typeID] = nonStackableTargeted 76 77 return (nonStackableByTypeID, nonStackableByTypeIDTargeted) 78 79 80 def IsItGoodChange(modifyingValue, operation, wantHigh): 81 if modifyingValue is None: 82 return False 83 if operation in (dogmaConst.dgmAssModAdd, dogmaConst.dgmAssModSub): 84 return False 85 goodChange = False 86 if wantHigh: 87 if operation in (dogmaConst.dgmAssPreMul, dogmaConst.dgmAssPostMul): 88 goodChange = modifyingValue > 1.0 89 elif operation == dogmaConst.dgmAssPostPercent: 90 goodChange = modifyingValue > 0 91 elif operation in (dogmaConst.dgmAssPreDiv, dogmaConst.dgmAssPostDiv): 92 goodChange = modifyingValue < 1.0 93 elif operation in (dogmaConst.dgmAssPreMul, dogmaConst.dgmAssPostMul): 94 goodChange = modifyingValue < 1.0 and modifyingValue != 0 95 elif operation == dogmaConst.dgmAssPostPercent: 96 goodChange = modifyingValue < 0 97 elif operation in (dogmaConst.dgmAssPreDiv, dogmaConst.dgmAssPostDiv): 98 goodChange = modifyingValue > 1.0 99 return goodChange 100 101 102 def _GetModifierInfoFromPythonEffect(effectFromCompiler, domainToUse): 103 modifierInfo = [] 104 for operation, toAttribID, fromAttribID in effectFromCompiler.MODIFIER_CHANGES: 105 x = Bundle(operation=operation, modifiedAttributeID=toAttribID, modifyingAttributeID=fromAttribID, domain=(domainToUse, ITEM_MODIFIER), skillTypeID=None, func='ItemModifier') 106 modifierInfo.append(x) 107 108 for operation, skillTypeID, toAttribID, fromAttribID in effectFromCompiler.SKILL_MODIFIER_CHANGES_FOR_LOCATION: 109 x = Bundle(operation=operation, modifiedAttributeID=toAttribID, modifyingAttributeID=fromAttribID, domain=(domainToUse, NOT_ITEM_MOTIFIER), skillTypeID=skillTypeID, func='LocationRequiredSkillModifier') 110 modifierInfo.append(x) 111 112 return modifierInfo 113 114 115 def IsModuleOfInterestForStacking(typeID): 116 if not evetypes.IsPublished(typeID): 117 return False 118 if evetypes.GetCategoryID(typeID) not in (const.categoryModule, const.categoryStructureModule): 119 return False 120 return True 121 122 123 def Test(): 124 typeIDs = [ x for x in evetypes.Iterate() if IsModuleOfInterestForStacking(x) ] 125 x, y = _FindModulesWithStackingPenalty(typeIDs) 126 return (x, y) 127 128 129 def FindModulesWithStackingPenaltyTest(): 130 allTypeIDs = {x for x in evetypes.Iterate()} 131 typesPenalized = _FindModulesWithStackingPenalty(allTypeIDs) 132 missingText = {} 133 textButNotInList = set() 134 correct = set() 135 for eachTypeID in evetypes.Iterate(): 136 if not evetypes.IsPublished(eachTypeID): 137 continue 138 if evetypes.GetCategoryID(eachTypeID) not in (const.categoryModule, const.categoryStructureModule): 139 continue 140 desc = evetypes.GetDescription(eachTypeID).lower() 141 isPenaltyText = desc.find('penalty') >= 0 and desc.find('same attribute') >= 0 142 containsWarning = isPenaltyText or desc.find('diminishing returns') >= 0 143 if containsWarning: 144 if eachTypeID not in typesPenalized: 145 textButNotInList.add(eachTypeID) 146 continue 147 elif eachTypeID in typesPenalized: 148 missingText[eachTypeID] = typesPenalized[eachTypeID] 149 continue 150 correct.add(eachTypeID) 151 152 print('-------------- correct ------------------- = ', len(correct)) 153 print('-------------- Missing text ------------------- = ', len(missingText)) 154 print('-------------- Missing stacking ------------------- = ', len(textButNotInList)) 155 PrintList(textButNotInList) 156 157 158 def PrintList(typeIDs): 159 grouped = [] 160 for eachTypeID in typeIDs: 161 sortValue = (evetypes.GetGroupID(eachTypeID), evetypes.GetName(eachTypeID)) 162 grouped.append((sortValue, eachTypeID)) 163 164 import localization 165 grouped = [ y[1] for y in sorted(grouped) ] 166 for eachTypeID in grouped: 167 print('- ', evetypes.GetName(eachTypeID), eachTypeID)