From e8b56b076bd94fdd450d4e038071c755fea275de Mon Sep 17 00:00:00 2001 From: blitzmann Date: Sun, 10 Jun 2018 01:10:53 -0400 Subject: [PATCH] Instantiate mutators when a mutated module is created / loaded from DB. Some bug fixes for a few things. --- eos/db/saveddata/module.py | 4 ++- eos/db/saveddata/mutator.py | 2 +- eos/modifiedAttributeDict.py | 2 +- eos/saveddata/module.py | 12 +++++++ eos/saveddata/mutator.py | 46 +++++++++++++++++++++--- gui/attribute_gauge.py | 2 +- gui/builtinItemStatsViews/itemMutator.py | 15 ++++---- 7 files changed, 69 insertions(+), 14 deletions(-) diff --git a/eos/db/saveddata/module.py b/eos/db/saveddata/module.py index ae503f120..220b208db 100644 --- a/eos/db/saveddata/module.py +++ b/eos/db/saveddata/module.py @@ -18,6 +18,7 @@ # =============================================================================== from sqlalchemy import Table, Column, Integer, ForeignKey, CheckConstraint, Boolean, DateTime +from sqlalchemy.orm.collections import attribute_mapped_collection from sqlalchemy.orm import relation, mapper import datetime @@ -47,6 +48,7 @@ mapper(Module, modules_table, "mutators": relation( Mutator, backref="module", - cascade="all,delete-orphan" + cascade="all,delete-orphan", + collection_class=attribute_mapped_collection('attrID') ) }) diff --git a/eos/db/saveddata/mutator.py b/eos/db/saveddata/mutator.py index e503a5b25..43ecff834 100644 --- a/eos/db/saveddata/mutator.py +++ b/eos/db/saveddata/mutator.py @@ -25,7 +25,7 @@ from eos.db import saveddata_meta from eos.saveddata.mutator import Mutator mutator_table = Table("mutators", saveddata_meta, - Column("moduleID", Integer, ForeignKey("modules.ID"), nullable=False, index=True), + Column("moduleID", Integer, ForeignKey("modules.ID"), primary_key=True, index=True), Column("attrID", Integer, primary_key=True, index=True), Column("value", Float, nullable=False), Column("created", DateTime, nullable=True, default=datetime.datetime.now), diff --git a/eos/modifiedAttributeDict.py b/eos/modifiedAttributeDict.py index 70968b1a9..ceb44148c 100644 --- a/eos/modifiedAttributeDict.py +++ b/eos/modifiedAttributeDict.py @@ -112,7 +112,7 @@ class ModifiedAttributeDict(collections.MutableMapping): @property def mutators(self): - return {x.attr.name: x for x in self.__mutators} + return {x.attr.name: x for x in self.__mutators.values()} @mutators.setter def mutators(self, val): diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index 2fe0044b9..5b4547c9f 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -27,6 +27,7 @@ from eos.effectHandlerHelpers import HandledItem, HandledCharge from eos.enum import Enum from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut from eos.saveddata.citadel import Citadel +from eos.saveddata.mutator import Mutator pyfalog = Logger(__name__) @@ -135,6 +136,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): self.__charge = eos.db.getItem(self.chargeID) self.build() + def build(self): """ Builds internal module variables from both init's """ @@ -157,12 +159,22 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): self.__itemModifiedAttributes.overrides = self.__item.overrides self.__hardpoint = self.__calculateHardpoint(self.__item) self.__slot = self.__calculateSlot(self.__item) + + # Instantiate / remove mutators if this is a mutated module + if self.__baseItem: + for x in self.mutaplasmid.attributes: + attr = self.item.attributes[x.name] + if attr.ID not in self.mutators: # create the mutator + self.mutators[attr.ID] = Mutator(self, attr, attr.value) + # @todo: remove attributes that are no longer part of the mutaplasmid. + self.__itemModifiedAttributes.mutators = self.mutators if self.__charge: self.__chargeModifiedAttributes.original = self.__charge.attributes self.__chargeModifiedAttributes.overrides = self.__charge.overrides + @classmethod def buildEmpty(cls, slot): empty = Module(None) diff --git a/eos/saveddata/mutator.py b/eos/saveddata/mutator.py index eddc97570..e071262b1 100644 --- a/eos/saveddata/mutator.py +++ b/eos/saveddata/mutator.py @@ -19,7 +19,7 @@ from logbook import Logger -from sqlalchemy.orm import reconstructor +from sqlalchemy.orm import validates, reconstructor import eos.db from eos.eqBase import EqBase @@ -28,8 +28,14 @@ pyfalog = Logger(__name__) class Mutator(EqBase): - def __init__(self, stuff, attr, value): - self.moduleID = stuff.ID + """ Mutators are the object that represent an attribute override on the module level, in conjunction with + mutaplasmids. Each mutated module, when created, is instantiated with a list of these objects, dictated by the + mutaplasmid that is used on the base module. + """ + + def __init__(self, module, attr, value): + self.module = module + self.moduleID = module.ID self.attrID = attr.ID self.__attr = attr self.value = value @@ -37,7 +43,6 @@ class Mutator(EqBase): @reconstructor def init(self): self.__attr = None - self.__item = None if self.attrID: self.__attr = eos.db.getAttributeInfo(self.attrID) @@ -45,6 +50,39 @@ class Mutator(EqBase): pyfalog.error("Attribute (id: {0}) does not exist", self.attrID) return + self.value = self.value # run the validator (to ensure we catch any changed min/max values CCP releases) + self.build() + + def build(self): + pass + + @validates("value") + def validator(self, key, val): + """ Validates values as properly falling within the range of the modules mutaplasmid """ + dynAttr = next(a for a in self.module.mutaplasmid.attributes if a.attributeID == self.attrID) + baseAttr = self.module.item.attributes[dynAttr.name] + + minValue = dynAttr.min * baseAttr.value + maxValue = dynAttr.max * baseAttr.value + + if minValue < val < maxValue: + # sweet, all good + returnVal = val + else: + # need to fudge the numbers a bit. Go with the value closest to base + returnVal = min(maxValue, max(minValue, val)) + + return returnVal + + @property + def isInvalid(self): + # @todo: need to test what happens: + # 1) if an attribute is removed from the EVE database + # 2) if a mutaplasmid does not have the attribute anymore + # 3) if a mutaplasmid does not exist (in eve or on the module's item) + # Can remove invalid ones in a SQLAlchemy collection class... eventually + return self.__attr is None + @property def attr(self): return self.__attr diff --git a/gui/attribute_gauge.py b/gui/attribute_gauge.py index 554ad40b1..b3a80ae2c 100644 --- a/gui/attribute_gauge.py +++ b/gui/attribute_gauge.py @@ -23,7 +23,7 @@ class AttributeGauge(wx.Window): self._bar_colour = None self._bar_gradient = None - self.leading_edge = True + self.leading_edge = leading_edge self._border_padding = 0 self._max_range = max_range diff --git a/gui/builtinItemStatsViews/itemMutator.py b/gui/builtinItemStatsViews/itemMutator.py index c66a46f3f..f5cecd756 100644 --- a/gui/builtinItemStatsViews/itemMutator.py +++ b/gui/builtinItemStatsViews/itemMutator.py @@ -36,13 +36,16 @@ class ItemMutator(wx.Panel): min = round(x.min, 2) max = round(x.max, 2) - value = stuff.itemModifiedAttributes.getOriginal(x.name) - slider = AttributeSlider(self, value, min, max, not x.highIsGood) - slider.SetValue(value) + base_value = stuff.item.attributes[x.name].value + + mutator = stuff.mutators[x.attributeID] + + slider = AttributeSlider(self, base_value, min, max, not x.highIsGood) + slider.SetValue(mutator.value) headingSizer = wx.BoxSizer(wx.HORIZONTAL) - minValue = round(value * min, 3) - maxValue = round(value * max, 3) + minValue = round(base_value * min, 3) + maxValue = round(base_value * max, 3) # create array for the two ranges min_t = [minValue, min, None] @@ -64,7 +67,7 @@ class ItemMutator(wx.Panel): worse_range = min_t print("{}: \nHigh is good: {}".format(x.displayName, x.highIsGood)) - print("Value {}".format(value)) + print("Value {}".format(base_value)) print(min_t) print(max_t)