Example #1
0
File: fit.py Project: meldi44/Pyfa
    def calculateModifiedAttributes(self, targetFit=None, withBoosters=False, dirtyStorage=None):
        timer = Timer(u'Fit: {}, {}'.format(self.ID, self.name), logger)
        logger.debug("Starting fit calculation on: %r, withBoosters: %s", self, withBoosters)

        shadow = False
        if targetFit:
            logger.debug("Applying projections to target: %r", targetFit)
            projectionInfo = self.getProjectionInfo(targetFit.ID)
            logger.debug("ProjectionInfo: %s", projectionInfo)
            if self == targetFit:
                copied = self  # original fit
                shadow = True
                self = copy.deepcopy(self)
                self.fleet = copied.fleet
                logger.debug("Handling self projection - making shadow copy of fit. %r => %r", copied, self)
                # we delete the fit because when we copy a fit, flush() is
                # called to properly handle projection updates. However, we do
                # not want to save this fit to the database, so simply remove it
                eos.db.saveddata_session.delete(self)

        if self.fleet is not None and withBoosters is True:
            logger.debug("Fleet is set, gathering gang boosts")
            self.gangBoosts = self.fleet.recalculateLinear(withBoosters=withBoosters)
            timer.checkpoint("Done calculating gang boosts for %r"%self)
        elif self.fleet is None:
            self.gangBoosts = None

        # If we're not explicitly asked to project fit onto something,
        # set self as target fit
        if targetFit is None:
            targetFit = self
            projected = False
        else:
            projected = True

        # If fit is calculated and we have nothing to do here, get out

        # A note on why projected fits don't get to return here. If we return
        # here, the projection afflictions will not be run as they are
        # intertwined into the regular fit calculations. So, even if the fit has
        # been calculated, we need to recalculate it again just to apply the
        # projections. This is in contract to gang boosts, which are only
        # calculated once, and their items are then looped and accessed with
        #     self.gangBoosts.iteritems()
        # We might be able to exit early in the fit calculations if we separate
        # projections from the normal fit calculations. But we must ensure that
        # projection have modifying stuff applied, such as gang boosts and other
        # local modules that may help
        if self.__calculated and not projected:
            logger.debug("Fit has already been calculated and is not projected, returning: %r", self)
            return

        # Mark fit as calculated
        self.__calculated = True

        for runTime in ("early", "normal", "late"):
            # Items that are unrestricted. These items are run on the local fit
            # first and then projected onto the target fit it one is designated
            u = [
                (self.character, self.ship),
                self.drones,
                self.boosters,
                self.appliedImplants,
                self.modules
            ]

            # Items that are restricted. These items are only run on the local
            # fit. They are NOT projected onto the target fit. # See issue 354
            r = [(self.mode,), self.projectedDrones, self.projectedModules]

            # chain unrestricted and restricted into one iterable
            c = chain.from_iterable(u+r)

            # We calculate gang bonuses first so that projected fits get them
            if self.gangBoosts is not None:
                self.__calculateGangBoosts(runTime)

            for item in c:
                # Registering the item about to affect the fit allows us to
                # track "Affected By" relations correctly
                if item is not None:
                    # apply effects locally
                    self.register(item)
                    item.calculateModifiedAttributes(self, runTime, False)

                    if projected is True and item not in chain.from_iterable(r):
                        # apply effects onto target fit
                        for _ in xrange(projectionInfo.amount):
                            targetFit.register(item, origin=self)
                            item.calculateModifiedAttributes(targetFit, runTime, True)

            timer.checkpoint('Done with runtime: %s'%runTime)

        # Only apply projected fits if fit it not projected itself.
        if not projected:
            for fit in self.projectedFits:
                if fit.getProjectionInfo(self.ID).active:
                    fit.calculateModifiedAttributes(self, withBoosters=withBoosters, dirtyStorage=dirtyStorage)

        timer.checkpoint('Done with fit calculation')

        if shadow:
            logger.debug("Delete shadow fit object")
            del self
Example #2
0
    def calculateModifiedAttributes(self,
                                    targetFit=None,
                                    withBoosters=False,
                                    dirtyStorage=None):
        timer = Timer(u'Fit: {}, {}'.format(self.ID, self.name), logger)
        logger.debug("Starting fit calculation on: %r, withBoosters: %s", self,
                     withBoosters)

        shadow = False
        if targetFit:
            logger.debug("Applying projections to target: %r", targetFit)
            projectionInfo = self.getProjectionInfo(targetFit.ID)
            logger.debug("ProjectionInfo: %s", projectionInfo)
            if self == targetFit:
                copied = self  # original fit
                shadow = True
                self = copy.deepcopy(self)
                self.fleet = copied.fleet
                logger.debug(
                    "Handling self projection - making shadow copy of fit. %r => %r",
                    copied, self)
                # we delete the fit because when we copy a fit, flush() is
                # called to properly handle projection updates. However, we do
                # not want to save this fit to the database, so simply remove it
                eos.db.saveddata_session.delete(self)

        if self.fleet is not None and withBoosters is True:
            logger.debug("Fleet is set, gathering gang boosts")
            self.gangBoosts = self.fleet.recalculateLinear(
                withBoosters=withBoosters)

            timer.checkpoint("Done calculating gang boosts for %r" % self)
        elif self.fleet is None:
            self.gangBoosts = None

        # If we're not explicitly asked to project fit onto something,
        # set self as target fit
        if targetFit is None:
            targetFit = self
            projected = False
        else:
            projected = True

        # If fit is calculated and we have nothing to do here, get out

        # A note on why projected fits don't get to return here. If we return
        # here, the projection afflictions will not be run as they are
        # intertwined into the regular fit calculations. So, even if the fit has
        # been calculated, we need to recalculate it again just to apply the
        # projections. This is in contract to gang boosts, which are only
        # calculated once, and their items are then looped and accessed with
        #     self.gangBoosts.iteritems()
        # We might be able to exit early in the fit calculations if we separate
        # projections from the normal fit calculations. But we must ensure that
        # projection have modifying stuff applied, such as gang boosts and other
        # local modules that may help
        if self.__calculated and not projected:
            logger.debug(
                "Fit has already been calculated and is not projected, returning: %r",
                self)
            return

        for runTime in ("early", "normal", "late"):
            # Items that are unrestricted. These items are run on the local fit
            # first and then projected onto the target fit it one is designated
            u = [(self.character, self.ship), self.drones, self.fighters,
                 self.boosters, self.appliedImplants, self.modules]

            # Items that are restricted. These items are only run on the local
            # fit. They are NOT projected onto the target fit. # See issue 354
            r = [(self.mode, ), self.projectedDrones, self.projectedFighters,
                 self.projectedModules]

            # chain unrestricted and restricted into one iterable
            c = chain.from_iterable(u + r)

            # We calculate gang bonuses first so that projected fits get them
            if self.gangBoosts is not None:
                self.__calculateGangBoosts(runTime)

            for item in c:
                # Registering the item about to affect the fit allows us to
                # track "Affected By" relations correctly
                if item is not None:
                    if not self.__calculated:
                        # apply effects locally if this is first time running them on fit
                        self.register(item)
                        item.calculateModifiedAttributes(self, runTime, False)

                    if projected is True and item not in chain.from_iterable(
                            r):
                        # apply effects onto target fit
                        for _ in xrange(projectionInfo.amount):
                            targetFit.register(item, origin=self)
                            item.calculateModifiedAttributes(
                                targetFit, runTime, True)

            timer.checkpoint('Done with runtime: %s' % runTime)

        # Mark fit as calculated
        self.__calculated = True

        # Only apply projected fits if fit it not projected itself.
        if not projected:
            for fit in self.projectedFits:
                if fit.getProjectionInfo(self.ID).active:
                    fit.calculateModifiedAttributes(self,
                                                    withBoosters=withBoosters,
                                                    dirtyStorage=dirtyStorage)

        timer.checkpoint('Done with fit calculation')

        if shadow:
            logger.debug("Delete shadow fit object")
            del self