diff --git a/eos/db/saveddata/fit.py b/eos/db/saveddata/fit.py index 4c03bdd32..6b4e44fb4 100644 --- a/eos/db/saveddata/fit.py +++ b/eos/db/saveddata/fit.py @@ -21,6 +21,7 @@ from sqlalchemy import * from sqlalchemy.orm import * from sqlalchemy.sql import and_ from sqlalchemy.ext.associationproxy import association_proxy +from sqlalchemy.orm.collections import attribute_mapped_collection from eos.db import saveddata_meta from eos.db.saveddata.module import modules_table @@ -51,25 +52,27 @@ projectedFits_table = Table("projectedFits", saveddata_meta, ) class ProjectedFit(object): - def __init__(self, source_item, dest_item, amount=1, active=True): - print "init projected item", source_item, dest_item, active, amount - self.source_item = source_item - self.dest_item = dest_item + def __init__(self, source_fit, k, amount=1, active=True): + print "init projected: ", k, source_fit.name, active, amount + self.sourceID = k + self.source_item = source_fit + self.victim_item = None self.amount = amount self.active = active - self.dest_item.projectionInfo = self + #self.dest_item.setProjectionInfo(self.source_item.ID, self) @reconstructor def init(self): print "db init" - print "\t source:",self.source_item - print "\t dest:", self.dest_item - self.dest_item.projectionInfo = self + print "\t source:", self.source_fit + print "\t dest:", self.victim_fit + #self.dest_item.setProjectionInfo(self.source_item.ID, self) + #print self.dest_item.ship.item.name, ">", self.source_item.ship.item.name,self Fit._Fit__projectedFits = association_proxy( - "projected_items", - "dest_item", - creator=lambda dest_item: ProjectedFit(None, dest_item) + "victimOf", # look at the victimOf association... + "source_fit", # .. and return the source fits + creator=lambda k, victim_fit: ProjectedFit(victim_fit, k) ) mapper(Fit, fits_table, @@ -128,15 +131,17 @@ mapper(Fit, fits_table, backref="fits"), "_Fit__damagePattern": relation(DamagePattern), "_Fit__targetResists": relation(TargetResists), - "dest_items": relationship( + "projectedOnto": relationship( ProjectedFit, - primaryjoin=projectedFits_table.c.victimID == fits_table.c.ID, - backref='dest_item', + primaryjoin=projectedFits_table.c.sourceID == fits_table.c.ID, + backref='source_fit', + collection_class=attribute_mapped_collection('victimID'), cascade='all, delete, delete-orphan'), - "projected_items": relationship( + "victimOf": relationship( ProjectedFit, - primaryjoin=fits_table.c.ID == projectedFits_table.c.sourceID, - backref='source_item', + primaryjoin=fits_table.c.ID == projectedFits_table.c.victimID, + backref='victim_fit', + collection_class=attribute_mapped_collection('sourceID'), cascade='all, delete, delete-orphan'), } ) diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 391f046b8..9c76dee23 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -119,7 +119,7 @@ class Fit(object): self.__capUsed = None self.__capRecharge = None self.__calculatedTargets = [] - self.__projectionInfo = None + self.__projectionMap = {} self.factorReload = False self.fleet = None self.boostsFits = set() @@ -208,15 +208,10 @@ class Fit(object): @property def projectedFits(self): - return self.__projectedFits + return self.__projectedFits.values() - @property - def projectionInfo(self): - return self.__projectionInfo - - @projectionInfo.setter - def projectionInfo(self, projectionInfo): - self.__projectionInfo = projectionInfo + def getProjectionInfo(self, fitID): + return self.projectedOnto.get(fitID, None) @property def projectedDrones(self): @@ -371,7 +366,11 @@ class Fit(object): # If we are in a root ship, add projected fits to clear list # Do not add projected fits if self is already projected - this can # cause infinite recursion in projection loop, eg A > B > C > A - if self.projectionInfo is None: + # @todo: since fits persist, we need to be sure that even if a fit has + # projection info (loaded as a projected fit), this still happens when + # we clear the fit if the fit is the root + #if self.projectionInfo is None: + if True: c = chain(c, self.projectedFits) for stuff in c: @@ -417,10 +416,13 @@ class Fit(object): timer = Timer('Fit: %d, %s'%(self.ID, self.name), logger) logger.debug("Starting fit calculation on: %d %s (%s)" % (self.ID, self.name, self.ship.item.name)) - + #print self.projectedFits if targetFit: - logger.debug("Applying projections to target: %d %s (%s)" % - (targetFit.ID, targetFit.name, targetFit.ship.item.name)) + logger.debug("Applying projections to target: %d %s (%s)", + targetFit.ID, targetFit.name, targetFit.ship.item.name) + projectionInfo = self.getProjectionInfo(targetFit.ID) + logger.debug("ProjectionInfo: amount=%s, active=%s, instance=%s", + projectionInfo.amount, projectionInfo.active, projectionInfo) refreshBoosts = False if withBoosters is True: @@ -489,7 +491,7 @@ class Fit(object): self.register(item) item.calculateModifiedAttributes(self, runTime, False) if projected is True: - for _ in xrange(self.projectionInfo.amount): + #for _ in xrange(projectionInfo.amount): targetFit.register(item) item.calculateModifiedAttributes(targetFit, runTime, True) @@ -498,7 +500,7 @@ class Fit(object): # Only apply projected fits if fit it not projected itself. if not projected: for fit in self.projectedFits: - if fit.projectionInfo.active: + #if fit.getProjectionInfo(self.ID).active: fit.calculateModifiedAttributes(self, withBoosters=withBoosters, dirtyStorage=dirtyStorage) timer.checkpoint('Done with fit calculation') diff --git a/gui/builtinViewColumns/baseName.py b/gui/builtinViewColumns/baseName.py index 0bd0e8c43..cf9222414 100644 --- a/gui/builtinViewColumns/baseName.py +++ b/gui/builtinViewColumns/baseName.py @@ -21,6 +21,8 @@ from gui import builtinViewColumns from gui.viewColumn import ViewColumn from gui import bitmapLoader +import gui.mainFrame + import wx from eos.types import Drone, Cargo, Fit, Module, Slot, Rack import service @@ -29,6 +31,7 @@ class BaseName(ViewColumn): name = "Base Name" def __init__(self, fittingView, params): ViewColumn.__init__(self, fittingView) + self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.columnText = "Name" self.shipImage = fittingView.imageList.GetImageIndex("ship_small", "icons") self.mask = wx.LIST_MASK_TEXT @@ -39,7 +42,8 @@ class BaseName(ViewColumn): elif isinstance(stuff, Cargo): return "%dx %s" % (stuff.amount, stuff.item.name) elif isinstance(stuff, Fit): - return "%dx %s (%s)" % (stuff.projectionInfo.amount, stuff.name, stuff.ship.item.name) + fitID = self.mainFrame.getActiveFit() + return "%dx %s (%s)" % (stuff.getProjectionInfo(fitID).amount, stuff.name, stuff.ship.item.name) elif isinstance(stuff, Rack): if service.Fit.getInstance().serviceFittingOptions["rackLabels"]: if stuff.slot == Slot.MODE: diff --git a/gui/builtinViewColumns/state.py b/gui/builtinViewColumns/state.py index 0925d2f2d..8110a85ad 100644 --- a/gui/builtinViewColumns/state.py +++ b/gui/builtinViewColumns/state.py @@ -19,6 +19,8 @@ from gui.viewColumn import ViewColumn from gui import bitmapLoader +import gui.mainFrame + import wx from eos.types import Drone, Module, Rack, Fit from eos.types import State as State_ @@ -27,6 +29,7 @@ class State(ViewColumn): name = "State" def __init__(self, fittingView, params): ViewColumn.__init__(self, fittingView) + self.mainFrame = gui.mainFrame.MainFrame.getInstance() self.resizable = False self.size = 16 self.maxsize = self.size @@ -56,9 +59,12 @@ class State(ViewColumn): else: return self.fittingView.imageList.GetImageIndex("state_%s_small" % State_.getName(stuff.state).lower(), "icons") elif isinstance(stuff, Fit): - if stuff.projectionInfo is None: + fitID = self.mainFrame.getActiveFit() + projectionInfo = stuff.getProjectionInfo(fitID) + + if projectionInfo is None: return -1 - if stuff.projectionInfo.active: + if projectionInfo.active: return generic_active return generic_inactive else: diff --git a/service/fit.py b/service/fit.py index dddc4ebfb..9effe43a6 100644 --- a/service/fit.py +++ b/service/fit.py @@ -325,7 +325,8 @@ class Fit(object): if isinstance(thing, eos.types.Fit): if thing.ID == fitID: return - fit.projectedFits.append(thing) + + fit.__projectedFits[thing.ID] = thing elif thing.category.name == "Drone": drone = None for d in fit.projectedDrones.find(thing): @@ -374,10 +375,10 @@ class Fit(object): def changeAmount(self, fitID, projected_fit, amount): """Change amount of projected fits""" fit = eos.db.getFit(fitID) - amount = min(20, max(1, amount)) # 1 <= a <= 5 - - if projected_fit.projectionInfo is not None: - projected_fit.projectionInfo.amount = amount + amount = min(20, max(1, amount)) # 1 <= a <= 20 + projectionInfo = projected_fit.getProjectionInfo(fitID) + if projectionInfo: + projectionInfo.amount = amount eos.db.commit() self.recalc(fit) @@ -389,7 +390,8 @@ class Fit(object): elif isinstance(thing, eos.types.Module): fit.projectedModules.remove(thing) else: - fit.projectedFits.remove(thing) + del fit.__projectedFits[thing.ID] + #fit.projectedFits.remove(thing) eos.db.commit() self.recalc(fit) @@ -937,7 +939,7 @@ class Fit(object): self.recalc(fit) def recalc(self, fit, withBoosters=False): - logger.debug("="*10+"recalc"+"="*10) + logger.debug("="*10+"recalc"+"="*10) if fit.factorReload is not self.serviceFittingOptions["useGlobalForceReload"]: fit.factorReload = self.serviceFittingOptions["useGlobalForceReload"] fit.clear()