Fixes critical design issue when it comes to projected fits. Disabled some of the more advanced functionality (projection amount and active) to cope to development. Crash still happens occasionally when adding projected fit for unknown reasons - not 100% reproducable yet

This commit is contained in:
blitzmann
2015-07-09 17:53:41 -04:00
parent af9f64db5f
commit c17e03d8d0
5 changed files with 61 additions and 42 deletions

View File

@@ -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'),
}
)

View File

@@ -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')

View File

@@ -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:

View File

@@ -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:

View File

@@ -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()