Merge branch 'master' into development

Conflicts:
	eve.db
This commit is contained in:
blitzman
2017-01-22 21:10:06 -05:00
13 changed files with 129 additions and 59 deletions

View File

@@ -1,4 +1,4 @@
#===============================================================================
# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of eos.
@@ -15,7 +15,7 @@
#
# You should have received a copy of the GNU Lesser General Public License
# along with eos. If not, see <http://www.gnu.org/licenses/>.
#===============================================================================
# ===============================================================================
from eos.db.util import processEager, processWhere
from eos.db import saveddata_session, sd_lock
@@ -28,13 +28,18 @@ import eos.config
configVal = getattr(eos.config, "saveddataCache", None)
if configVal is True:
import weakref
itemCache = {}
queryCache = {}
def cachedQuery(type, amount, *keywords):
itemCache[type] = localItemCache = weakref.WeakValueDictionary()
queryCache[type] = typeQueryCache = {}
def deco(function):
localQueryCache = typeQueryCache[function] = {}
def setCache(cacheKey, args, kwargs):
items = function(*args, **kwargs)
IDs = set()
@@ -43,7 +48,7 @@ if configVal is True:
for item in stuff:
ID = getattr(item, "ID", None)
if ID is None:
#Some uncachable data, don't cache this query
# Some uncachable data, don't cache this query
del localQueryCache[cacheKey]
break
localItemCache[ID] = item
@@ -69,7 +74,7 @@ if configVal is True:
for ID in IDs:
data = localItemCache.get(ID)
if data is None:
#Fuck, some of our stuff isn't cached it seems.
# Fuck, some of our stuff isn't cached it seems.
items = setCache(cacheKey, args, kwargs)
break
items.append(data)
@@ -81,11 +86,14 @@ if configVal is True:
break
return items
return checkAndReturn
return deco
def removeCachedEntry(type, ID):
if not type in queryCache:
if type not in queryCache:
return
functionCache = queryCache[type]
for _, localCache in functionCache.iteritems():
@@ -110,11 +118,14 @@ else:
return function(*args, **kwargs)
return checkAndReturn
return deco
def removeCachedEntry(*args, **kwargs):
return
def sqlizeString(line):
# Escape backslashes first, as they will be as escape symbol in queries
# Then escape percent and underscore signs
@@ -122,6 +133,7 @@ def sqlizeString(line):
line = line.replace("\\", "\\\\").replace("%", "\\%").replace("_", "\\_").replace("*", "%")
return line
@cachedQuery(User, 1, "lookfor")
def getUser(lookfor, eager=None):
if isinstance(lookfor, int):
@@ -140,6 +152,7 @@ def getUser(lookfor, eager=None):
raise TypeError("Need integer or string as argument")
return user
@cachedQuery(Character, 1, "lookfor")
def getCharacter(lookfor, eager=None):
if isinstance(lookfor, int):
@@ -153,17 +166,20 @@ def getCharacter(lookfor, eager=None):
elif isinstance(lookfor, basestring):
eager = processEager(eager)
with sd_lock:
character = saveddata_session.query(Character).options(*eager).filter(Character.savedName == lookfor).first()
character = saveddata_session.query(Character).options(*eager).filter(
Character.savedName == lookfor).first()
else:
raise TypeError("Need integer or string as argument")
return character
def getCharacterList(eager=None):
eager = processEager(eager)
with sd_lock:
characters = saveddata_session.query(Character).options(*eager).all()
return characters
def getCharactersForUser(lookfor, eager=None):
if isinstance(lookfor, int):
eager = processEager(eager)
@@ -173,6 +189,7 @@ def getCharactersForUser(lookfor, eager=None):
raise TypeError("Need integer as argument")
return characters
@cachedQuery(Fit, 1, "lookfor")
def getFit(lookfor, eager=None):
if isinstance(lookfor, int):
@@ -214,6 +231,7 @@ def getFitsWithShip(shipID, ownerID=None, where=None, eager=None):
return fits
def getBoosterFits(ownerID=None, where=None, eager=None):
"""
Get all the fits that are flagged as a boosting ship
@@ -233,31 +251,41 @@ def getBoosterFits(ownerID=None, where=None, eager=None):
return fits
def countAllFits():
with sd_lock:
count = saveddata_session.query(Fit).count()
return count
def countFitsWithShip(shipID, ownerID=None, where=None, eager=None):
def countFitsWithShip(lookfor, ownerID=None, where=None, eager=None):
"""
Get all the fits using a certain ship.
If no user is passed, do this for all users.
"""
if isinstance(shipID, int):
if ownerID is not None and not isinstance(ownerID, int):
raise TypeError("OwnerID must be integer")
filter = Fit.shipID == shipID
if ownerID is not None:
filter = and_(filter, Fit.ownerID == ownerID)
if ownerID is not None and not isinstance(ownerID, int):
raise TypeError("OwnerID must be integer")
filter = processWhere(filter, where)
eager = processEager(eager)
with sd_lock:
count = saveddata_session.query(Fit).options(*eager).filter(filter).count()
if isinstance(lookfor, int):
filter = Fit.shipID == lookfor
elif isinstance(lookfor, list):
if len(lookfor) == 0:
return 0
filter = Fit.shipID.in_(lookfor)
else:
raise TypeError("ShipID must be integer")
raise TypeError("You must supply either an integer or ShipID must be integer")
if ownerID is not None:
filter = and_(filter, Fit.ownerID == ownerID)
filter = processWhere(filter, where)
eager = processEager(eager)
with sd_lock:
count = saveddata_session.query(Fit).options(*eager).filter(filter).count()
return count
def getFitList(eager=None):
eager = processEager(eager)
with sd_lock:
@@ -274,12 +302,14 @@ def getPrice(typeID):
raise TypeError("Need integer as argument")
return price
def clearPrices():
with sd_lock:
deleted_rows = saveddata_session.query(Price).delete()
commit()
return deleted_rows
def getMiscData(field):
if isinstance(field, basestring):
with sd_lock:
@@ -288,24 +318,28 @@ def getMiscData(field):
raise TypeError("Need string as argument")
return data
def getDamagePatternList(eager=None):
eager = processEager(eager)
with sd_lock:
patterns = saveddata_session.query(DamagePattern).options(*eager).all()
return patterns
def getTargetResistsList(eager=None):
eager = processEager(eager)
with sd_lock:
patterns = saveddata_session.query(TargetResists).options(*eager).all()
return patterns
def getImplantSetList(eager=None):
eager = processEager(eager)
with sd_lock:
sets = saveddata_session.query(ImplantSet).options(*eager).all()
return sets
@cachedQuery(DamagePattern, 1, "lookfor")
def getDamagePattern(lookfor, eager=None):
if isinstance(lookfor, int):
@@ -315,15 +349,18 @@ def getDamagePattern(lookfor, eager=None):
else:
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(DamagePattern.ID == lookfor).first()
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(
DamagePattern.ID == lookfor).first()
elif isinstance(lookfor, basestring):
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(DamagePattern.name == lookfor).first()
pattern = saveddata_session.query(DamagePattern).options(*eager).filter(
DamagePattern.name == lookfor).first()
else:
raise TypeError("Need integer or string as argument")
return pattern
@cachedQuery(TargetResists, 1, "lookfor")
def getTargetResists(lookfor, eager=None):
if isinstance(lookfor, int):
@@ -333,15 +370,18 @@ def getTargetResists(lookfor, eager=None):
else:
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(TargetResists).options(*eager).filter(TargetResists.ID == lookfor).first()
pattern = saveddata_session.query(TargetResists).options(*eager).filter(
TargetResists.ID == lookfor).first()
elif isinstance(lookfor, basestring):
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(TargetResists).options(*eager).filter(TargetResists.name == lookfor).first()
pattern = saveddata_session.query(TargetResists).options(*eager).filter(
TargetResists.name == lookfor).first()
else:
raise TypeError("Need integer or string as argument")
return pattern
@cachedQuery(ImplantSet, 1, "lookfor")
def getImplantSet(lookfor, eager=None):
if isinstance(lookfor, int):
@@ -351,7 +391,8 @@ def getImplantSet(lookfor, eager=None):
else:
eager = processEager(eager)
with sd_lock:
pattern = saveddata_session.query(ImplantSet).options(*eager).filter(TargetResists.ID == lookfor).first()
pattern = saveddata_session.query(ImplantSet).options(*eager).filter(
TargetResists.ID == lookfor).first()
elif isinstance(lookfor, basestring):
eager = processEager(eager)
with sd_lock:
@@ -360,13 +401,14 @@ def getImplantSet(lookfor, eager=None):
raise TypeError("Improper argument")
return pattern
def searchFits(nameLike, where=None, eager=None):
if not isinstance(nameLike, basestring):
raise TypeError("Need string as argument")
# Prepare our string for request
nameLike = u"%{0}%".format(sqlizeString(nameLike))
#Add any extra components to the search to our where clause
# Add any extra components to the search to our where clause
filter = processWhere(Fit.name.like(nameLike, escape="\\"), where)
eager = processEager(eager)
with sd_lock:
@@ -383,12 +425,14 @@ def getProjectedFits(fitID):
else:
raise TypeError("Need integer as argument")
def getCrestCharacters(eager=None):
eager = processEager(eager)
with sd_lock:
characters = saveddata_session.query(CrestChar).options(*eager).all()
return characters
@cachedQuery(CrestChar, 1, "lookfor")
def getCrestCharacter(lookfor, eager=None):
if isinstance(lookfor, int):
@@ -407,21 +451,25 @@ def getCrestCharacter(lookfor, eager=None):
raise TypeError("Need integer or string as argument")
return character
def getOverrides(itemID, eager=None):
if isinstance(itemID, int):
return saveddata_session.query(Override).filter(Override.itemID == itemID).all()
else:
raise TypeError("Need integer as argument")
def clearOverrides():
with sd_lock:
deleted_rows = saveddata_session.query(Override).delete()
commit()
return deleted_rows
def getAllOverrides(eager=None):
return saveddata_session.query(Override).all()
def removeInvalid(fits):
invalids = [f for f in fits if f.isInvalid]
@@ -432,14 +480,17 @@ def removeInvalid(fits):
return fits
def add(stuff):
with sd_lock:
saveddata_session.add(stuff)
def save(stuff):
add(stuff)
commit()
def remove(stuff):
removeCachedEntry(type(stuff), stuff.ID)
with sd_lock:

View File

@@ -172,10 +172,11 @@ class HandledModuleList(HandledList):
self[index] = mod
def freeSlot(self, slot):
for i in range(len(self) - 1, -1, -1):
for i in range(len(self)):
mod = self[i]
if mod.getModifiedItemAttr("subSystemSlot") == slot:
del self[i]
self.toDummy(i)
break
class HandledDroneCargoList(HandledList):

View File

@@ -4,5 +4,5 @@
# Ship: Rabisu
type = "passive"
def handler(fit, src, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "falloffEffectiveness", src.getModifiedItemAttr("eliteBonusLogistics1"), stackingPenalties=True, skill="Logistics Cruisers")
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "maxRange", src.getModifiedItemAttr("eliteBonusLogistics1"), stackingPenalties=True, skill="Logistics Cruisers")
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "falloffEffectiveness", src.getModifiedItemAttr("eliteBonusLogistics1"), skill="Logistics Cruisers")
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "maxRange", src.getModifiedItemAttr("eliteBonusLogistics1"), skill="Logistics Cruisers")

View File

@@ -4,5 +4,5 @@
# Ship: Rabisu
type = "passive"
def handler(fit, src, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "falloffEffectiveness", src.getModifiedItemAttr("roleBonusRepairRange"), stackingPenalties=True)
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "maxRange", src.getModifiedItemAttr("roleBonusRepairRange"), stackingPenalties=True)
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "falloffEffectiveness", src.getModifiedItemAttr("roleBonusRepairRange"))
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Remote Armor Repair Systems"), "maxRange", src.getModifiedItemAttr("roleBonusRepairRange"))

View File

@@ -6,5 +6,28 @@ type = "passive"
def handler(fit, skill, context):
fit.modules.filteredItemBoost(lambda mod: mod.item.group.name == "Burst Projectors",
"duration", skill.getModifiedItemAttr("projECMDurationBonus") * skill.level)
# We need to make sure that the attribute exists, otherwise we add attributes that don't belong. See #927
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Burst Projector Operation") and
mod.item.getAttribute("duration"),
"duration",
skill.getModifiedItemAttr("projECMDurationBonus") * skill.level)
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Burst Projector Operation") and
mod.item.getAttribute("durationECMJammerBurstProjector"),
"durationECMJammerBurstProjector",
skill.getModifiedItemAttr("projECMDurationBonus") * skill.level)
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Burst Projector Operation") and
mod.item.getAttribute("durationTargetIlluminationBurstProjector"),
"durationTargetIlluminationBurstProjector",
skill.getModifiedItemAttr("projECMDurationBonus") * skill.level)
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Burst Projector Operation") and
mod.item.getAttribute("durationSensorDampeningBurstProjector"),
"durationSensorDampeningBurstProjector",
skill.getModifiedItemAttr("projECMDurationBonus") * skill.level)
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill("Burst Projector Operation") and
mod.item.getAttribute("durationWeaponDisruptionBurstProjector"),
"durationWeaponDisruptionBurstProjector",
skill.getModifiedItemAttr("projECMDurationBonus") * skill.level)

View File

@@ -3,4 +3,5 @@ type = "passive"
def handler(fit, src, context):
fit.ship.increaseItemAttr("maxLockedTargets", src.getModifiedItemAttr("structureRigMaxTargetBonus"))
fit.extraAttributes.increase("maxTargetsLockedFromSkills", src.getModifiedItemAttr("structureRigMaxTargetBonus"))

View File

@@ -631,14 +631,6 @@ class Fit(object):
groups = ("Energy Weapon", "Hybrid Weapon")
self.modules.filteredItemBoost(lambda mod: mod.item.group.name in groups, "maxRange", value, stackingPenalties=True)
else:
# Run effect, and get proper bonuses applied
try:
self.register(thing)
effect.handler(self, thing, context)
except:
pass
del self.commandBonuses[warfareBuffID]
def calculateModifiedAttributes(self, targetFit=None, withBoosters=False, dirtyStorage=None):
@@ -754,7 +746,7 @@ class Fit(object):
self.__calculated = True
# Only apply projected fits if fit it not projected itself.
if not projected:
if not projected and not withBoosters:
for fit in self.projectedFits:
if fit.getProjectionInfo(self.ID).active:
fit.calculateModifiedAttributes(self, withBoosters=withBoosters, dirtyStorage=dirtyStorage)

View File

@@ -201,6 +201,11 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
else:
return self.__chargeCycles
@property
def modPosition(self):
if self.owner:
return self.owner.modules.index(self)
@property
def hpBeforeReload(self):
"""

BIN
eve.db

Binary file not shown.

View File

@@ -224,7 +224,7 @@ class FittingView(d.Display):
if row != -1 and row not in self.blanks:
data = wx.PyTextDataObject()
data.SetText("fitting:"+str(self.mods[row].position))
data.SetText("fitting:"+str(self.mods[row].modPosition))
dropSource = wx.DropSource(self)
dropSource.SetData(data)
@@ -356,7 +356,7 @@ class FittingView(d.Display):
if dstRow != -1 and dstRow not in self.blanks:
sFit = service.Fit.getInstance()
fitID = self.mainFrame.getActiveFit()
moduleChanged = sFit.changeModule(fitID, self.mods[dstRow].position, srcIdx)
moduleChanged = sFit.changeModule(fitID, self.mods[dstRow].modPosition, srcIdx)
if moduleChanged is None:
# the new module doesn't fit in specified slot, try to simply append it
wx.PostEvent(self.mainFrame, gui.marketBrowser.ItemSelected(itemID=srcIdx))
@@ -371,7 +371,7 @@ class FittingView(d.Display):
module = self.mods[dstRow]
sFit = service.Fit.getInstance()
sFit.moveCargoToModule(self.mainFrame.getActiveFit(), module.position, srcIdx, mstate.CmdDown() and module.isEmpty)
sFit.moveCargoToModule(self.mainFrame.getActiveFit(), module.modPosition, srcIdx, mstate.CmdDown() and module.isEmpty)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
@@ -389,6 +389,7 @@ class FittingView(d.Display):
dstRow, _ = self.HitTest((x, y))
if dstRow != -1 and dstRow not in self.blanks:
mod1 = fit.modules[srcIdx]
mod2 = self.mods[dstRow]
@@ -397,9 +398,9 @@ class FittingView(d.Display):
return
if clone and mod2.isEmpty:
sFit.cloneModule(self.mainFrame.getActiveFit(), mod1.position, mod2.position)
sFit.cloneModule(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition)
else:
sFit.swapModules(self.mainFrame.getActiveFit(), mod1.position, mod2.position)
sFit.swapModules(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition)
wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))

View File

@@ -34,6 +34,7 @@ Stage3Selected, EVT_SB_STAGE3_SEL = wx.lib.newevent.NewEvent()
SearchSelected, EVT_SB_SEARCH_SEL = wx.lib.newevent.NewEvent()
ImportSelected, EVT_SB_IMPORT_SEL = wx.lib.newevent.NewEvent()
class PFWidgetsContainer(PFListPane):
def __init__(self,parent):
PFListPane.__init__(self,parent)
@@ -685,7 +686,8 @@ class ShipBrowser(wx.Panel):
# set map & cache of fittings per category
for cat in self.categoryList:
self.categoryFitCache[cat.ID] = sFit.groupHasFits(cat.ID)
itemIDs = [x.ID for x in cat.items]
self.categoryFitCache[cat.ID] = sFit.countFitsWithShip(itemIDs) > 1
for ship in self.categoryList:
if self.filterShipsWithNoFits and not self.categoryFitCache[ship.ID]:

View File

@@ -141,19 +141,10 @@ class Fit(object):
def countAllFits(self):
return eos.db.countAllFits()
def countFitsWithShip(self, shipID):
count = eos.db.countFitsWithShip(shipID)
def countFitsWithShip(self, stuff):
count = eos.db.countFitsWithShip(stuff)
return count
def groupHasFits(self, groupID):
sMkt = Market.getInstance()
grp = sMkt.getGroup(groupID)
items = sMkt.getItemsByGroup(grp)
for item in items:
if self.countFitsWithShip(item.ID) > 0:
return True
return False
def getModule(self, fitID, pos):
fit = eos.db.getFit(fitID)
return fit.modules[pos]

View File

@@ -219,6 +219,8 @@ class Market():
"Victorieux Luxury Yacht": self.les_grp, # Worlds Collide prize \o/ chinese getting owned
"Imp": self.les_grp, # AT13 prize
"Fiend": self.les_grp, # AT13 prize
"Caedes": self.les_grp, # AT14 prize
"Rabisu": self.les_grp, # AT14 prize
}
self.ITEMS_FORCEGROUP_R = self.__makeRevDict(self.ITEMS_FORCEGROUP)
@@ -543,6 +545,7 @@ class Market():
def getGroupsByCategory(self, cat):
"""Get groups from given category"""
groups = set(filter(lambda grp: self.getPublicityByGroup(grp), cat.groups))
return groups
def getMarketGroupChildren(self, mg):