diff --git a/eos/db/saveddata/fit.py b/eos/db/saveddata/fit.py index b355ba4f1..744a849a0 100644 --- a/eos/db/saveddata/fit.py +++ b/eos/db/saveddata/fit.py @@ -52,24 +52,24 @@ projectedFits_table = Table("projectedFits", saveddata_meta, ) class ProjectedFit(object): - def __init__(self, source_fit, k, amount=1, active=True): - #print "init projected: source fit: ", source_fit.name, source_fit, "key (fit ID)", key, "active:", active, "amount:",amount - self.sourceID = k + def __init__(self, sourceID, source_fit, amount=1, active=True): + self.sourceID = sourceID self.source_fit = source_fit - #self.victim_item = None self.amount = amount self.active = active @reconstructor def init(self): - print "db init" - print "\t source:", self.source_fit - print "\t dest:", self.victim_fit + if self.source_fit.isInvalid: + # Very rare for this to happen, but be prepared for it + eos.db.saveddata_session.delete(self.source_fit) + eos.db.saveddata_session.flush() + eos.db.saveddata_session.refresh(self.victim_fit) Fit._Fit__projectedFits = association_proxy( "victimOf", # look at the victimOf association... "source_fit", # .. and return the source fits - creator=lambda k, source_fit: ProjectedFit(source_fit, k) + creator=lambda sourceID, source_fit: ProjectedFit(sourceID, source_fit) ) mapper(Fit, fits_table, diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index e1f943d05..2ded319b7 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -207,8 +207,9 @@ class Fit(object): @property def projectedFits(self): - #print "get projected fits for :", self.name - return self.__projectedFits.values() + # only in extreme edge cases will the fit be invalid, but to be sure do + # not return them. By this time + return [fit for fit in self.__projectedFits.values() if not fit.isInvalid] def getProjectionInfo(self, fitID): print "get projection info for fitID: ", fitID @@ -331,7 +332,7 @@ class Fit(object): if map[key](val) == False: raise ValueError(str(val) + " is not a valid value for " + key) else: return val - def clear(self): + def clear(self, projected=False): self.__effectiveTank = None self.__weaponDPS = None self.__minerYield = None @@ -364,20 +365,18 @@ class Fit(object): (self.character, self.extraAttributes), ) - # 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 - # @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: if stuff is not None and stuff != self: stuff.clear() + # If this is the active fit that we are clearing, not a projected fit, + # then this will run and clear the projected ships and flag the next + # iteration to skip this part to prevent recursion. + if not projected: + for stuff in self.projectedFits: + if stuff is not None and stuff != self: + stuff.clear(projected=True) + #Methods to register and get the thing currently affecting the fit, #so we can correctly map "Affected By" def register(self, currModifier): @@ -417,15 +416,11 @@ 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 - #print self.__projectedFits - #print self.projectedFits if targetFit: 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) + projectionInfo = self.getProjectionInfo(targetFit.ID) + logger.debug("ProjectionInfo: %s", ', '.join("%s: %s" % item for item in vars(projectionInfo).items())) refreshBoosts = False if withBoosters is True: @@ -457,14 +452,7 @@ class Fit(object): if self.__calculated and not projected: logger.debug("Fit has already been calculated and is not projected, returning") return - print - print "******** projected fits ********" - print self.__projectedFits - print "******** projectedOnto ********" - print self.projectedOnto - print "******** victimOf ********" - print self.victimOf - print + # Mark fit as calculated self.__calculated = True @@ -492,7 +480,7 @@ class Fit(object): self.register(item) item.calculateModifiedAttributes(self, runTime, False) if projected is True: - #for _ in xrange(projectionInfo.amount): + for _ in xrange(projectionInfo.amount): targetFit.register(item) item.calculateModifiedAttributes(targetFit, runTime, True) @@ -501,7 +489,7 @@ class Fit(object): # Only apply projected fits if fit it not projected itself. if not projected: for fit in self.projectedFits: - #if fit.getProjectionInfo(self.ID).active: + if fit.getProjectionInfo(self.ID).active: fit.calculateModifiedAttributes(self, withBoosters=withBoosters, dirtyStorage=dirtyStorage) timer.checkpoint('Done with fit calculation') diff --git a/service/fit.py b/service/fit.py index 7b4f6e406..be7efa4c8 100644 --- a/service/fit.py +++ b/service/fit.py @@ -175,7 +175,7 @@ class Fit(object): fit = eos.db.getFit(fitID) sFleet = Fleet.getInstance() sFleet.removeAssociatedFleetData(fit) - self.removeProjectedData(fitID) + #self.removeProjectedData(fitID) eos.db.remove(fit) @@ -247,6 +247,7 @@ class Fit(object): fit.fleet = f if not projected: + print "Not projected, getting projected fits" for fitP in fit.projectedFits: self.getFit(fitP.ID, projected = True) self.recalc(fit, withBoosters=True) @@ -326,9 +327,12 @@ class Fit(object): if thing.ID == fitID: return + if thing in fit.projectedFits: + return + fit.__projectedFits[thing.ID] = thing - # this bit is required -- see GH issue + # this bit is required -- see GH issue # 83 eos.db.saveddata_session.flush() eos.db.saveddata_session.refresh(thing) elif thing.category.name == "Drone": @@ -369,9 +373,11 @@ class Fit(object): thing.state = self.__getProposedState(thing, click) if not thing.canHaveState(thing.state, fit): thing.state = State.OFFLINE - elif isinstance(thing, eos.types.Fit) and thing.projectionInfo is not None: + elif isinstance(thing, eos.types.Fit): print "toggle fit" - thing.projectionInfo.active = not thing.projectionInfo.active + projectionInfo = thing.getProjectionInfo(fitID) + if projectionInfo: + projectionInfo.active = not projectionInfo.active eos.db.commit() self.recalc(fit)