def testShip(self): tgtAttr = self.ch.attribute(attributeId=1) srcAttr = self.ch.attribute(attributeId=2) modifier = Modifier() modifier.state = State.offline modifier.context = Context.local modifier.sourceAttributeId = srcAttr.id modifier.operator = Operator.postPercent modifier.targetAttributeId = tgtAttr.id modifier.location = Location.ship modifier.filterType = None modifier.filterValue = None effect = self.ch.effect(effectId=1, categoryId=EffectCategory.passive) effect._modifiers = (modifier,) fit = Fit() influenceSource = IndependentItem(self.ch.type_(typeId=1, effects=(effect,), attributes={srcAttr.id: 20})) fit.items.append(influenceSource) item = self.ch.type_(typeId=None, attributes={tgtAttr.id: 100}) influenceTarget1 = IndependentItem(item) fit.ship = influenceTarget1 self.assertNotAlmostEqual(influenceTarget1.attributes[tgtAttr.id], 100) fit.ship = None influenceTarget2 = IndependentItem(item) fit.ship = influenceTarget2 self.assertNotAlmostEqual(influenceTarget2.attributes[tgtAttr.id], 100) fit.items.remove(influenceSource) fit.ship = None self.assertBuffersEmpty(fit)
def testCalculation(self): attr1 = self.ch.attribute(attributeId=1) attr2 = self.ch.attribute(attributeId=2) attr3 = self.ch.attribute(attributeId=3) attr4 = self.ch.attribute(attributeId=4) modifier1 = Modifier() modifier1.state = State.offline modifier1.context = Context.local modifier1.sourceAttributeId = attr1.id modifier1.operator = Operator.postMul modifier1.targetAttributeId = attr2.id modifier1.location = Location.self_ modifier1.filterType = None modifier1.filterValue = None effect1 = self.ch.effect(effectId=1, categoryId=EffectCategory.passive) effect1._modifiers = (modifier1,) modifier2 = Modifier() modifier2.state = State.offline modifier2.context = Context.local modifier2.sourceAttributeId = attr2.id modifier2.operator = Operator.postPercent modifier2.targetAttributeId = attr3.id modifier2.location = Location.ship modifier2.filterType = None modifier2.filterValue = None effect2 = self.ch.effect(effectId=2, categoryId=EffectCategory.passive) effect2._modifiers = (modifier2,) holder1 = CharacterItem(self.ch.type_(typeId=1, effects=(effect1, effect2), attributes={attr1.id: 5, attr2.id: 20})) modifier3 = Modifier() modifier3.state = State.offline modifier3.context = Context.local modifier3.sourceAttributeId = attr3.id modifier3.operator = Operator.postPercent modifier3.targetAttributeId = attr4.id modifier3.location = Location.ship modifier3.filterType = FilterType.all_ modifier3.filterValue = None effect3 = self.ch.effect(effectId=3, categoryId=EffectCategory.passive) effect3._modifiers = (modifier3,) holder2 = IndependentItem(self.ch.type_(typeId=2, effects=(effect3,), attributes={attr3.id: 150})) holder3 = ShipItem(self.ch.type_(typeId=3, attributes={attr4.id: 12.5})) fit = Fit() fit.items.append(holder1) fit.ship = holder2 fit.items.append(holder3) # If everything is processed properly, holder1 will multiply attr2 by attr1 # on self, resulting in 20 * 5 = 100, then apply it as percentage modifier # on ship's (holder2) attr3, resulting in 150 + 100% = 300, then it is applied # to all entities assigned to ship, including holder3, to theirs attr4 as # percentage modifier again - so final result is 12.5 + 300% = 50 self.assertAlmostEqual(holder3.attributes[attr4.id], 50) fit.items.remove(holder1) fit.ship = None fit.items.remove(holder3) self.assertBuffersEmpty(fit)
def testAttribute(self): attr1 = self.ch.attribute(attributeId=1) attr2 = self.ch.attribute(attributeId=2) attr3 = self.ch.attribute(attributeId=3) modifier1 = Modifier() modifier1.state = State.offline modifier1.context = Context.local modifier1.sourceAttributeId = attr1.id modifier1.operator = Operator.postMul modifier1.targetAttributeId = attr2.id modifier1.location = Location.ship modifier1.filterType = None modifier1.filterValue = None effect1 = self.ch.effect(effectId=1, categoryId=EffectCategory.passive) effect1._modifiers = (modifier1, ) holder1 = CharacterItem( self.ch.type_( typeId=1, effects=(effect1, ), attributes={attr1.id: 5})) modifier2 = Modifier() modifier2.state = State.offline modifier2.context = Context.local modifier2.sourceAttributeId = attr2.id modifier2.operator = Operator.postPercent modifier2.targetAttributeId = attr3.id modifier2.location = Location.ship modifier2.filterType = FilterType.all_ modifier2.filterValue = None effect2 = self.ch.effect(effectId=2, categoryId=EffectCategory.passive) effect2._modifiers = (modifier2, ) holder2 = IndependentItem( self.ch.type_( typeId=2, effects=(effect2, ), attributes={attr2.id: 7.5})) holder3 = ShipItem(self.ch.type_(typeId=3, attributes={attr3.id: 0.5})) fit = Fit() fit.items.append(holder1) fit.ship = holder2 fit.items.append(holder3) self.assertAlmostEqual(holder3.attributes[attr3.id], 0.6875) holder1.attributes[attr1.id] = 4 # Manually changed attribute must trigger damaging whole chain # of attributes, effectively allowing us to recalculate its new value self.assertAlmostEqual(holder3.attributes[attr3.id], 0.65) fit.items.remove(holder1) fit.ship = None fit.items.remove(holder3) self.assertBuffersEmpty(fit)
def testFitAttrUpdate(self): # Here we create 2 separate fits with ships affecting it; # each ship affects module with different strength. When we # pass module from one fit to another, its internal attribute # storage should be cleared. If it wasn't cleared, we wouldn't # be able to get refreshed value of attribute srcAttr = self.ch.attribute(attributeId=1) tgtAttr = self.ch.attribute(attributeId=2) modifier = Modifier() modifier.state = State.offline modifier.context = Context.local modifier.sourceAttributeId = srcAttr.id modifier.operator = Operator.postPercent modifier.targetAttributeId = tgtAttr.id modifier.location = Location.ship modifier.filterType = FilterType.all_ modifier.filterValue = None effect = self.ch.effect(effectId=1, categoryId=EffectCategory.passive) effect.modifiers = (modifier, ) ship1 = IndependentItem( self.ch.type_(typeId=1, effects=(effect, ), attributes={srcAttr.id: 10})) ship2 = IndependentItem( self.ch.type_(typeId=2, effects=(effect, ), attributes={srcAttr.id: 20})) module = ShipItem(self.ch.type_(typeId=3, attributes={tgtAttr.id: 50})) fit1 = Fit(self.ch) fit1.ship = ship1 fit2 = Fit(self.ch) fit2.ship = ship2 fit1.items.add(module) self.assertAlmostEqual(module.attributes.get(tgtAttr.id), 55) fit1.items.remove(module) fit1.ship = None self.assertLinkBuffersEmpty(fit1) fit2.items.add(module) self.assertAlmostEqual(module.attributes.get(tgtAttr.id), 60) fit2.ship = None fit2.items.remove(module) self.assertLinkBuffersEmpty(fit2)
def testAttribute(self): attr1 = self.ch.attribute(attributeId=1) attr2 = self.ch.attribute(attributeId=2) attr3 = self.ch.attribute(attributeId=3) modifier1 = Modifier() modifier1.state = State.offline modifier1.context = Context.local modifier1.sourceAttributeId = attr1.id modifier1.operator = Operator.postMul modifier1.targetAttributeId = attr2.id modifier1.location = Location.ship modifier1.filterType = None modifier1.filterValue = None effect1 = self.ch.effect(effectId=1, categoryId=EffectCategory.passive) effect1._modifiers = (modifier1,) holder1 = CharacterItem(self.ch.type_(typeId=1, effects=(effect1,), attributes={attr1.id: 5})) modifier2 = Modifier() modifier2.state = State.offline modifier2.context = Context.local modifier2.sourceAttributeId = attr2.id modifier2.operator = Operator.postPercent modifier2.targetAttributeId = attr3.id modifier2.location = Location.ship modifier2.filterType = FilterType.all_ modifier2.filterValue = None effect2 = self.ch.effect(effectId=2, categoryId=EffectCategory.passive) effect2._modifiers = (modifier2,) holder2 = IndependentItem(self.ch.type_(typeId=2, effects=(effect2,), attributes={attr2.id: 7.5})) holder3 = ShipItem(self.ch.type_(typeId=3, attributes={attr3.id: 0.5})) fit = Fit() fit.items.append(holder1) fit.ship = holder2 fit.items.append(holder3) self.assertAlmostEqual(holder3.attributes[attr3.id], 0.6875) fit.items.remove(holder1) # When holder1 is removed, attr2 of holder2 and attr3 of holder3 # must be cleaned to allow recalculation of attr3 based on new data self.assertAlmostEqual(holder3.attributes[attr3.id], 0.5375) fit.ship = None fit.items.remove(holder3) self.assertBuffersEmpty(fit)
def testFitAttrUpdate(self): # Here we create 2 separate fits with ships affecting it; # each ship affects module with different strength. When we # pass module from one fit to another, its internal attribute # storage should be cleared. If it wasn't cleared, we wouldn't # be able to get refreshed value of attribute srcAttr = self.ch.attribute(attributeId=1) tgtAttr = self.ch.attribute(attributeId=2) modifier = Modifier() modifier.state = State.offline modifier.context = Context.local modifier.sourceAttributeId = srcAttr.id modifier.operator = Operator.postPercent modifier.targetAttributeId = tgtAttr.id modifier.location = Location.ship modifier.filterType = FilterType.all_ modifier.filterValue = None effect = self.ch.effect(effectId=1, categoryId=EffectCategory.passive) effect.modifiers = (modifier,) ship1 = IndependentItem(self.ch.type_(typeId=1, effects=(effect,), attributes={srcAttr.id: 10})) ship2 = IndependentItem(self.ch.type_(typeId=2, effects=(effect,), attributes={srcAttr.id: 20})) module = ShipItem(self.ch.type_(typeId=3, attributes={tgtAttr.id: 50})) fit1 = Fit(self.ch) fit1.ship = ship1 fit2 = Fit(self.ch) fit2.ship = ship2 fit1.items.add(module) self.assertAlmostEqual(module.attributes.get(tgtAttr.id), 55) fit1.items.remove(module) fit1.ship = None self.assertLinkBuffersEmpty(fit1) fit2.items.add(module) self.assertAlmostEqual(module.attributes.get(tgtAttr.id), 60) fit2.ship = None fit2.items.remove(module) self.assertLinkBuffersEmpty(fit2)
def testEosAttrUpdate(self): # Here we check if attributes are updated if fit changes # eos' instance; we do not actually switch eos instance, # but we switch cacheHandler, and it should be enough cacheHandler1 = CacheHandler() cacheHandler2 = CacheHandler() srcAttr1 = cacheHandler1.attribute(attributeId=1) tgtAttr1 = cacheHandler1.attribute(attributeId=2, maxAttributeId=33) cacheHandler1.attribute(attributeId=33, defaultValue=100) srcAttr2 = cacheHandler2.attribute(attributeId=1) tgtAttr2 = cacheHandler2.attribute(attributeId=2, maxAttributeId=333) cacheHandler2.attribute(attributeId=333, defaultValue=500) modifier = Modifier() modifier.state = State.offline modifier.context = Context.local modifier.sourceAttributeId = 1 modifier.operator = Operator.postPercent modifier.targetAttributeId = 2 modifier.location = Location.ship modifier.filterType = FilterType.all_ modifier.filterValue = None effect1 = cacheHandler1.effect(effectId=1, categoryId=EffectCategory.passive) effect1.modifiers = (modifier, ) effect2 = cacheHandler1.effect(effectId=111, categoryId=EffectCategory.passive) effect2.modifiers = (modifier, ) # Our holders from test environment fo not update undelying # item automatically when eos instance is switched, thus we # do it manually shipItem1 = cacheHandler1.type_(typeId=8, effects=(effect1, ), attributes={srcAttr1.id: 10}) shipItem2 = cacheHandler2.type_(typeId=8, effects=(effect2, ), attributes={srcAttr2.id: 20}) moduleItem1 = cacheHandler1.type_(typeId=4, attributes={tgtAttr1.id: 50}) moduleItem2 = cacheHandler2.type_(typeId=4, attributes={tgtAttr2.id: 75}) fit = Fit(cacheHandler1) ship = IndependentItem(shipItem1) module = ShipItem(moduleItem1) fit.ship = ship fit.items.add(module) self.assertAlmostEqual(module.attributes.get(tgtAttr1.id), 55) # As we have capped attr, this auxiliary map shouldn't be None self.assertIsNotNone(module.attributes._capMap) # Make an 'eos switch': remove holders from attributeCalculator for holder in (ship, module): disabledStates = set(filter(lambda s: s <= holder.state, State)) fit._linkTracker.disableStates(holder, disabledStates) fit._linkTracker.removeHolder(holder) # Refresh holders and replace eos fit.eos._cacheHandler = cacheHandler2 ship.attributes.clear() ship.item = shipItem2 module.attributes.clear() module.item = moduleItem2 # When we cleared holders, auxiliary map for capped attrs should be None. # Using data in this map, attributes which depend on capping attribute will # be cleared. If we don't clear it, there're chances that in new data this # capping-capped attribute pair won't exist, thus if attribute with ID which # used to cap is changed, it will clear attribute which used to be capped - # and we do not want it within scope of new data. self.assertIsNone(module.attributes._capMap) # Add holders again, when new items are in holders for holder in (ship, module): fit._linkTracker.addHolder(holder) enabledStates = set(filter(lambda s: s <= holder.state, State)) fit._linkTracker.enableStates(holder, enabledStates) # Now we should have calculated value based on both updated attribs # if attribs weren't refreshed, we would use old value for modification # (10 instead of 20) self.assertAlmostEqual(module.attributes.get(tgtAttr2.id), 90) fit.ship = None fit.items.remove(module) self.assertLinkBuffersEmpty(fit)
def testEosAttrUpdate(self): # Here we check if attributes are updated if fit changes # eos' instance; we do not actually switch eos instance, # but we switch cacheHandler, and it should be enough cacheHandler1 = CacheHandler() cacheHandler2 = CacheHandler() srcAttr1 = cacheHandler1.attribute(attributeId=1) tgtAttr1 = cacheHandler1.attribute(attributeId=2, maxAttributeId=33) cacheHandler1.attribute(attributeId=33, defaultValue=100) srcAttr2 = cacheHandler2.attribute(attributeId=1) tgtAttr2 = cacheHandler2.attribute(attributeId=2, maxAttributeId=333) cacheHandler2.attribute(attributeId=333, defaultValue=500) modifier = Modifier() modifier.state = State.offline modifier.context = Context.local modifier.sourceAttributeId = 1 modifier.operator = Operator.postPercent modifier.targetAttributeId = 2 modifier.location = Location.ship modifier.filterType = FilterType.all_ modifier.filterValue = None effect1 = cacheHandler1.effect(effectId=1, categoryId=EffectCategory.passive) effect1.modifiers = (modifier,) effect2 = cacheHandler1.effect(effectId=111, categoryId=EffectCategory.passive) effect2.modifiers = (modifier,) # Our holders from test environment fo not update undelying # item automatically when eos instance is switched, thus we # do it manually shipItem1 = cacheHandler1.type_(typeId=8, effects=(effect1,), attributes={srcAttr1.id: 10}) shipItem2 = cacheHandler2.type_(typeId=8, effects=(effect2,), attributes={srcAttr2.id: 20}) moduleItem1 = cacheHandler1.type_(typeId=4, attributes={tgtAttr1.id: 50}) moduleItem2 = cacheHandler2.type_(typeId=4, attributes={tgtAttr2.id: 75}) fit = Fit(cacheHandler1) ship = IndependentItem(shipItem1) module = ShipItem(moduleItem1) fit.ship = ship fit.items.add(module) self.assertAlmostEqual(module.attributes.get(tgtAttr1.id), 55) # As we have capped attr, this auxiliary map shouldn't be None self.assertIsNotNone(module.attributes._capMap) # Make an 'eos switch': remove holders from attributeCalculator for holder in (ship, module): disabledStates = set(filter(lambda s: s <= holder.state, State)) fit._linkTracker.disableStates(holder, disabledStates) fit._linkTracker.removeHolder(holder) # Refresh holders and replace eos fit.eos._cacheHandler = cacheHandler2 ship.attributes.clear() ship.item = shipItem2 module.attributes.clear() module.item = moduleItem2 # When we cleared holders, auxiliary map for capped attrs should be None. # Using data in this map, attributes which depend on capping attribute will # be cleared. If we don't clear it, there're chances that in new data this # capping-capped attribute pair won't exist, thus if attribute with ID which # used to cap is changed, it will clear attribute which used to be capped - # and we do not want it within scope of new data. self.assertIsNone(module.attributes._capMap) # Add holders again, when new items are in holders for holder in (ship, module): fit._linkTracker.addHolder(holder) enabledStates = set(filter(lambda s: s <= holder.state, State)) fit._linkTracker.enableStates(holder, enabledStates) # Now we should have calculated value based on both updated attribs # if attribs weren't refreshed, we would use old value for modification # (10 instead of 20) self.assertAlmostEqual(module.attributes.get(tgtAttr2.id), 90) fit.ship = None fit.items.remove(module) self.assertLinkBuffersEmpty(fit)