Compare commits
97 Commits
v2.9.4dev1
...
v2.9.5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
adf750fe44 | ||
|
|
250996e8ac | ||
|
|
56639a0812 | ||
|
|
7cf6ff04b6 | ||
|
|
5b575fdfe3 | ||
|
|
a8a5fabce7 | ||
|
|
f41d6dd2c1 | ||
|
|
09727c102a | ||
|
|
6580734dc7 | ||
|
|
ff34865067 | ||
|
|
bdd400fd51 | ||
|
|
1e8184a80b | ||
|
|
6a20f04c7f | ||
|
|
d81acc1f9c | ||
|
|
bc84c20cb2 | ||
|
|
d5c5e2698e | ||
|
|
16a78e689e | ||
|
|
066f29660d | ||
|
|
bba0df5f50 | ||
|
|
45452ca680 | ||
|
|
4fbbc18f9f | ||
|
|
22ec280ec2 | ||
|
|
89c06b5201 | ||
|
|
86d5f72988 | ||
|
|
c3e055a4c9 | ||
|
|
e48631956d | ||
|
|
2964f3b009 | ||
|
|
527c66dca4 | ||
|
|
24909f0523 | ||
|
|
ed7494b3a4 | ||
|
|
8fae275e5a | ||
|
|
a09a2a5f4b | ||
|
|
2adc150811 | ||
|
|
f5cad33b6c | ||
|
|
338cf45f65 | ||
|
|
359c60bafb | ||
|
|
f808b73a5d | ||
|
|
8dd87cde58 | ||
|
|
1ec78d9beb | ||
|
|
9c710285f2 | ||
|
|
90f745a18f | ||
|
|
af446579ab | ||
|
|
bcc11bd172 | ||
|
|
0c31f756a8 | ||
|
|
16fdd5a5e6 | ||
|
|
ec1a2c66ee | ||
|
|
c3f41d68e6 | ||
|
|
2f8701b4b2 | ||
|
|
9b2d5410d6 | ||
|
|
1d8c9d2c40 | ||
|
|
8c0817245f | ||
|
|
2a04e60ae0 | ||
|
|
fb5eb220fd | ||
|
|
512f48ebdd | ||
|
|
09db7d26a7 | ||
|
|
690cf5eca1 | ||
|
|
1aee4c59c4 | ||
|
|
f1384074b5 | ||
|
|
203bed06d6 | ||
|
|
0b00e28863 | ||
|
|
d74d331642 | ||
|
|
f075fbdc63 | ||
|
|
d59b6696ca | ||
|
|
eedf6f9a39 | ||
|
|
1cca5729fc | ||
|
|
a7b01ece22 | ||
|
|
d17e6d08d8 | ||
|
|
b29aaa9e20 | ||
|
|
71ae59b2b5 | ||
|
|
51294f6cbc | ||
|
|
0439ace886 | ||
|
|
c85c735f9a | ||
|
|
c65b582497 | ||
|
|
7f2ac83e17 | ||
|
|
5ef2a40d1e | ||
|
|
5b52da737a | ||
|
|
51e8713cd6 | ||
|
|
c9b60f2c65 | ||
|
|
d777999af4 | ||
|
|
74444d56c4 | ||
|
|
a433c9638a | ||
|
|
672141cffc | ||
|
|
ac132cbb92 | ||
|
|
d9535b08b1 | ||
|
|
d93544b3bc | ||
|
|
2320c3cb57 | ||
|
|
bd5710c676 | ||
|
|
49f1412d91 | ||
|
|
54eea7d702 | ||
|
|
e26bcb2e5e | ||
|
|
7305c0a017 | ||
|
|
7d37b9e0e0 | ||
|
|
87f28db730 | ||
|
|
56d9a8b626 | ||
|
|
cb8f76c582 | ||
|
|
af0b7b92c7 | ||
|
|
9418b7a709 |
@@ -24,10 +24,8 @@ $ brew install Caskroom/cask/pyfa
|
||||
### Linux Distro-specific Packages
|
||||
The following is a list of pyfa packages available for certain distributions. Please note that these packages are maintained by third-parties and are not evaluated by the pyfa developers.
|
||||
|
||||
* Debian/Ubuntu/derivatives: https://github.com/AdamMajer/Pyfa/releases
|
||||
* Arch: https://aur.archlinux.org/packages/pyfa/
|
||||
* openSUSE: https://build.opensuse.org/package/show/home:rmk2/pyfa
|
||||
* FreeBSD: http://www.freshports.org/games/pyfa/ (see [#484](https://github.com/pyfa-org/Pyfa/issues/484) for instructions)
|
||||
* Gentoo: https://github.com/ZeroPointEnergy/gentoo-pyfa-overlay
|
||||
|
||||
### Dependencies
|
||||
If you wish to help with development or simply need to run pyfa through a Python interpreter, the following software is required:
|
||||
|
||||
@@ -35810,3 +35810,25 @@ class Effect7228(BaseEffect):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Medium Precursor Weapon'),
|
||||
'maxRange', ship.getModifiedItemAttr('eliteBonusHeavyGunship2'),
|
||||
skill='Heavy Assault Cruisers')
|
||||
|
||||
|
||||
class Effect7230(BaseEffect):
|
||||
|
||||
type = 'passive'
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, ship, context):
|
||||
fit.drones.filteredItemBoost(lambda mod: mod.item.requiresSkill('Drones'),
|
||||
'trackingSpeed', ship.getModifiedItemAttr('shipBonusGC2'),
|
||||
skill='Gallente Cruiser')
|
||||
|
||||
|
||||
class Effect7231(BaseEffect):
|
||||
|
||||
type = 'passive'
|
||||
|
||||
@staticmethod
|
||||
def handler(fit, ship, context):
|
||||
fit.modules.filteredItemBoost(lambda mod: mod.item.requiresSkill('Repair Systems'),
|
||||
'armorDamageAmount', ship.getModifiedItemAttr('shipBonusGC3'),
|
||||
skill='Gallente Cruiser')
|
||||
|
||||
@@ -243,6 +243,20 @@ class Item(EqBase):
|
||||
self.__overrides = None
|
||||
self.__priceObj = None
|
||||
|
||||
def getShortName(self, charLimit=12):
|
||||
if len(self.name) <= charLimit:
|
||||
return self.name
|
||||
splitName = self.name.strip().split(' ')
|
||||
if len(splitName) == 1:
|
||||
return self.name
|
||||
shortName = ''
|
||||
for word in splitName:
|
||||
try:
|
||||
shortName += word[0].capitalize()
|
||||
except IndexError:
|
||||
pass
|
||||
return shortName
|
||||
|
||||
@property
|
||||
def attributes(self):
|
||||
if not self.__moved:
|
||||
|
||||
@@ -17,105 +17,60 @@
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
import itertools
|
||||
|
||||
import math
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
|
||||
class Graph(object):
|
||||
class Graph(metaclass=ABCMeta):
|
||||
|
||||
def __init__(self, fit, function, data=None):
|
||||
self.fit = fit
|
||||
self.data = {}
|
||||
if data is not None:
|
||||
for name, d in data.items():
|
||||
self.setData(Data(name, d))
|
||||
def __init__(self):
|
||||
self._cache = {}
|
||||
|
||||
self.function = function
|
||||
@abstractmethod
|
||||
def getPlotPoints(self, fit, extraData, xRange, xAmount):
|
||||
raise NotImplementedError
|
||||
|
||||
def clearData(self):
|
||||
self.data.clear()
|
||||
def getYForX(self, fit, extraData, x):
|
||||
raise NotImplementedError
|
||||
|
||||
def setData(self, data):
|
||||
self.data[data.name] = data
|
||||
|
||||
def getIterator(self):
|
||||
pointNames = []
|
||||
pointIterators = []
|
||||
for data in self.data.values():
|
||||
pointNames.append(data.name)
|
||||
pointIterators.append(data)
|
||||
|
||||
return self._iterator(pointNames, pointIterators)
|
||||
|
||||
def _iterator(self, pointNames, pointIterators):
|
||||
for pointValues in itertools.product(*pointIterators):
|
||||
point = {}
|
||||
for i in range(len(pointValues)):
|
||||
point[pointNames[i]] = pointValues[i]
|
||||
|
||||
yield point, self.function(point)
|
||||
|
||||
|
||||
class Data(object):
|
||||
def __init__(self, name, dataString, step=None):
|
||||
self.name = name
|
||||
self.step = step
|
||||
self.data = self.parseString(dataString)
|
||||
|
||||
def parseString(self, dataString):
|
||||
if not isinstance(dataString, str):
|
||||
return Constant(dataString),
|
||||
|
||||
dataList = []
|
||||
for data in dataString.split(";"):
|
||||
if isinstance(data, str) and "-" in data:
|
||||
# Dealing with a range
|
||||
dataList.append(Range(data, self.step))
|
||||
else:
|
||||
dataList.append(Constant(data))
|
||||
|
||||
return dataList
|
||||
|
||||
def __iter__(self):
|
||||
for data in self.data:
|
||||
for value in data:
|
||||
yield value
|
||||
|
||||
def isConstant(self):
|
||||
return len(self.data) == 1 and self.data[0].isConstant()
|
||||
|
||||
|
||||
class Constant(object):
|
||||
def __init__(self, const):
|
||||
if isinstance(const, str):
|
||||
self.value = None if const == "" else float(const)
|
||||
def _xIter(self, fit, extraData, xRange, xAmount):
|
||||
rangeLow, rangeHigh = self._limitXRange(xRange, fit, extraData)
|
||||
# Amount is amount of ranges between points here, not amount of points
|
||||
step = (rangeHigh - rangeLow) / xAmount
|
||||
if step == 0:
|
||||
yield xRange[0]
|
||||
else:
|
||||
self.value = const
|
||||
current = rangeLow
|
||||
# Take extra half step to make sure end of range is always included
|
||||
# despite any possible float errors
|
||||
while current <= (rangeHigh + step / 2):
|
||||
yield current
|
||||
current += step
|
||||
|
||||
def __iter__(self):
|
||||
yield self.value
|
||||
def _limitXRange(self, xRange, fit, extraData):
|
||||
rangeLow, rangeHigh = sorted(xRange)
|
||||
limitLow, limitHigh = self._getXLimits(fit, extraData)
|
||||
rangeLow = max(limitLow, rangeLow)
|
||||
rangeHigh = min(limitHigh, rangeHigh)
|
||||
return rangeLow, rangeHigh
|
||||
|
||||
@staticmethod
|
||||
def isConstant():
|
||||
return True
|
||||
def _getXLimits(self, fit, extraData):
|
||||
return -math.inf, math.inf
|
||||
|
||||
def clearCache(self, key=None):
|
||||
if key is None:
|
||||
self._cache.clear()
|
||||
elif key in self._cache:
|
||||
del self._cache[key]
|
||||
|
||||
|
||||
class Range(object):
|
||||
def __init__(self, string, step):
|
||||
start, end = string.split("-")
|
||||
self.start = float(start)
|
||||
self.end = float(end)
|
||||
self.step = step
|
||||
class SmoothGraph(Graph, metaclass=ABCMeta):
|
||||
|
||||
def __iter__(self):
|
||||
current = start = self.start
|
||||
end = self.end
|
||||
step = self.step or (end - start) / 50.0
|
||||
i = 1
|
||||
while current < end:
|
||||
current = start + i * step
|
||||
i += 1
|
||||
yield current
|
||||
|
||||
@staticmethod
|
||||
def isConstant():
|
||||
return False
|
||||
def getPlotPoints(self, fit, extraData, xRange, xAmount):
|
||||
xs = []
|
||||
ys = []
|
||||
for x in self._xIter(fit, extraData, xRange, xAmount):
|
||||
xs.append(x)
|
||||
ys.append(self.getYForX(fit, extraData, x))
|
||||
return xs, ys
|
||||
|
||||
15
eos/graph/fitCapAmountVsTime.py
Normal file
15
eos/graph/fitCapAmountVsTime.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import math
|
||||
|
||||
from eos.graph import SmoothGraph
|
||||
|
||||
|
||||
class FitCapAmountVsTimeGraph(SmoothGraph):
|
||||
|
||||
def getYForX(self, fit, extraData, time):
|
||||
if time < 0:
|
||||
return 0
|
||||
maxCap = fit.ship.getModifiedItemAttr('capacitorCapacity')
|
||||
regenTime = fit.ship.getModifiedItemAttr('rechargeRate') / 1000
|
||||
# https://wiki.eveuniversity.org/Capacitor#Capacitor_recharge_rate
|
||||
cap = maxCap * (1 + math.exp(5 * -time / regenTime) * -1) ** 2
|
||||
return cap
|
||||
14
eos/graph/fitCapRegenVsCapPerc.py
Normal file
14
eos/graph/fitCapRegenVsCapPerc.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import math
|
||||
|
||||
from eos.graph import SmoothGraph
|
||||
|
||||
|
||||
class FitCapRegenVsCapPercGraph(SmoothGraph):
|
||||
|
||||
def getYForX(self, fit, extraData, perc):
|
||||
maxCap = fit.ship.getModifiedItemAttr('capacitorCapacity')
|
||||
regenTime = fit.ship.getModifiedItemAttr('rechargeRate') / 1000
|
||||
currentCap = maxCap * perc / 100
|
||||
# https://wiki.eveuniversity.org/Capacitor#Capacitor_recharge_rate
|
||||
regen = 10 * maxCap / regenTime * (math.sqrt(currentCap / maxCap) - currentCap / maxCap)
|
||||
return regen
|
||||
17
eos/graph/fitDistanceVsTime.py
Normal file
17
eos/graph/fitDistanceVsTime.py
Normal file
@@ -0,0 +1,17 @@
|
||||
import math
|
||||
|
||||
from eos.graph import SmoothGraph
|
||||
|
||||
|
||||
class FitDistanceVsTimeGraph(SmoothGraph):
|
||||
|
||||
def getYForX(self, fit, extraData, time):
|
||||
maxSpeed = fit.ship.getModifiedItemAttr('maxVelocity')
|
||||
mass = fit.ship.getModifiedItemAttr('mass')
|
||||
agility = fit.ship.getModifiedItemAttr('agility')
|
||||
# Definite integral of:
|
||||
# https://wiki.eveuniversity.org/Acceleration#Mathematics_and_formulae
|
||||
distance_t = maxSpeed * time + (maxSpeed * agility * mass * math.exp((-time * 1000000) / (agility * mass)) / 1000000)
|
||||
distance_0 = maxSpeed * 0 + (maxSpeed * agility * mass * math.exp((-0 * 1000000) / (agility * mass)) / 1000000)
|
||||
distance = distance_t - distance_0
|
||||
return distance
|
||||
@@ -1,43 +0,0 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# 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 logbook import Logger
|
||||
|
||||
from eos.graph import Graph
|
||||
from eos.utils.spoolSupport import SpoolType, SpoolOptions
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class FitDmgTimeGraph(Graph):
|
||||
|
||||
defaults = {"time": 0}
|
||||
|
||||
def __init__(self, fit, data=None):
|
||||
Graph.__init__(self, fit, self.calcDps, data if data is not None else self.defaults)
|
||||
self.fit = fit
|
||||
|
||||
def calcDps(self, data):
|
||||
fit = self.fit
|
||||
time = data["time"]
|
||||
dmg = 0
|
||||
for i in range(round(time) + 1):
|
||||
dmg += fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.TIME, i, True)).total
|
||||
return dmg
|
||||
151
eos/graph/fitDmgVsTime.py
Normal file
151
eos/graph/fitDmgVsTime.py
Normal file
@@ -0,0 +1,151 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# 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.graph import Graph
|
||||
from eos.utils.spoolSupport import SpoolType, SpoolOptions
|
||||
from gui.utils.numberFormatter import roundToPrec
|
||||
|
||||
|
||||
class FitDmgVsTimeGraph(Graph):
|
||||
|
||||
def getPlotPoints(self, fit, extraData, xRange, xAmount):
|
||||
# We deliberately ignore xAmount here to build graph which will reflect
|
||||
# all steps of building up the damage
|
||||
minX, maxX = self._limitXRange(xRange, fit, extraData)
|
||||
if fit.ID not in self._cache:
|
||||
self.__generateCache(fit, maxX)
|
||||
currentY = None
|
||||
xs = []
|
||||
ys = []
|
||||
cache = self._cache[fit.ID]
|
||||
for time in sorted(cache):
|
||||
prevY = currentY
|
||||
currentX = time / 1000
|
||||
currentY = roundToPrec(cache[time], 6)
|
||||
if currentX < minX:
|
||||
continue
|
||||
# First set of data points
|
||||
if not xs:
|
||||
# Start at exactly requested time, at last known value
|
||||
initialY = prevY or 0
|
||||
xs.append(minX)
|
||||
ys.append(initialY)
|
||||
# If current time is bigger then starting, extend plot to that time with old value
|
||||
if currentX > minX:
|
||||
xs.append(currentX)
|
||||
ys.append(initialY)
|
||||
# If new value is different, extend it with new point to the new value
|
||||
if currentY != prevY:
|
||||
xs.append(currentX)
|
||||
ys.append(currentY)
|
||||
continue
|
||||
# Last data point
|
||||
if currentX >= maxX:
|
||||
xs.append(maxX)
|
||||
ys.append(prevY)
|
||||
break
|
||||
# Anything in-between
|
||||
if currentY != prevY:
|
||||
if prevY is not None:
|
||||
xs.append(currentX)
|
||||
ys.append(prevY)
|
||||
xs.append(currentX)
|
||||
ys.append(currentY)
|
||||
return xs, ys
|
||||
|
||||
def getYForX(self, fit, extraData, x):
|
||||
time = x * 1000
|
||||
cache = self._cache[fit.ID]
|
||||
closestTime = max((t for t in cache if t <= time), default=None)
|
||||
if closestTime is None:
|
||||
return 0
|
||||
return roundToPrec(cache[closestTime], 6)
|
||||
|
||||
def _getXLimits(self, fit, extraData):
|
||||
return 0, 2500
|
||||
|
||||
def __generateCache(self, fit, maxTime):
|
||||
cache = self._cache[fit.ID] = {}
|
||||
|
||||
def addDmg(addedTime, addedDmg):
|
||||
if addedDmg == 0:
|
||||
return
|
||||
if addedTime not in cache:
|
||||
prevTime = max((t for t in cache if t < addedTime), default=None)
|
||||
if prevTime is None:
|
||||
cache[addedTime] = 0
|
||||
else:
|
||||
cache[addedTime] = cache[prevTime]
|
||||
for time in (t for t in cache if t >= addedTime):
|
||||
cache[time] += addedDmg
|
||||
|
||||
# We'll handle calculations in milliseconds
|
||||
maxTime = maxTime * 1000
|
||||
for mod in fit.modules:
|
||||
if not mod.isDealingDamage():
|
||||
continue
|
||||
cycleParams = mod.getCycleParameters(reloadOverride=True)
|
||||
if cycleParams is None:
|
||||
continue
|
||||
currentTime = 0
|
||||
nonstopCycles = 0
|
||||
for cycleTime, inactiveTime in cycleParams.iterCycles():
|
||||
volleyParams = mod.getVolleyParameters(spoolOptions=SpoolOptions(SpoolType.CYCLES, nonstopCycles, True))
|
||||
for volleyTime, volley in volleyParams.items():
|
||||
addDmg(currentTime + volleyTime, volley.total)
|
||||
if inactiveTime == 0:
|
||||
nonstopCycles += 1
|
||||
else:
|
||||
nonstopCycles = 0
|
||||
if currentTime > maxTime:
|
||||
break
|
||||
currentTime += cycleTime + inactiveTime
|
||||
for drone in fit.drones:
|
||||
if not drone.isDealingDamage():
|
||||
continue
|
||||
cycleParams = drone.getCycleParameters(reloadOverride=True)
|
||||
if cycleParams is None:
|
||||
continue
|
||||
currentTime = 0
|
||||
volleyParams = drone.getVolleyParameters()
|
||||
for cycleTime, inactiveTime in cycleParams.iterCycles():
|
||||
for volleyTime, volley in volleyParams.items():
|
||||
addDmg(currentTime + volleyTime, volley.total)
|
||||
if currentTime > maxTime:
|
||||
break
|
||||
currentTime += cycleTime + inactiveTime
|
||||
for fighter in fit.fighters:
|
||||
if not fighter.isDealingDamage():
|
||||
continue
|
||||
cycleParams = fighter.getCycleParametersPerEffectOptimizedDps(reloadOverride=True)
|
||||
if cycleParams is None:
|
||||
continue
|
||||
volleyParams = fighter.getVolleyParametersPerEffect()
|
||||
for effectID, abilityCycleParams in cycleParams.items():
|
||||
if effectID not in volleyParams:
|
||||
continue
|
||||
currentTime = 0
|
||||
abilityVolleyParams = volleyParams[effectID]
|
||||
for cycleTime, inactiveTime in abilityCycleParams.iterCycles():
|
||||
for volleyTime, volley in abilityVolleyParams.items():
|
||||
addDmg(currentTime + volleyTime, volley.total)
|
||||
if currentTime > maxTime:
|
||||
break
|
||||
currentTime += cycleTime + inactiveTime
|
||||
@@ -1,42 +0,0 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# 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 logbook import Logger
|
||||
|
||||
from eos.graph import Graph
|
||||
from eos.utils.spoolSupport import SpoolType, SpoolOptions
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class FitDpsTimeGraph(Graph):
|
||||
|
||||
defaults = {"time": 0}
|
||||
|
||||
def __init__(self, fit, data=None):
|
||||
Graph.__init__(self, fit, self.calcDps, data if data is not None else self.defaults)
|
||||
self.fit = fit
|
||||
|
||||
def calcDps(self, data):
|
||||
fit = self.fit
|
||||
time = data["time"]
|
||||
dps = fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.TIME, time, True)).total
|
||||
return dps
|
||||
|
||||
@@ -17,80 +17,62 @@
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from math import exp, log, radians, sin
|
||||
|
||||
from math import exp, log, radians, sin, inf
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
from eos.const import FittingHardpoint, FittingModuleState
|
||||
from eos.graph import Graph
|
||||
from eos.graph import SmoothGraph
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class FitDpsRangeGraph(Graph):
|
||||
class FitDpsVsRangeGraph(SmoothGraph):
|
||||
|
||||
defaults = {
|
||||
"angle" : 0,
|
||||
"distance" : 0,
|
||||
"signatureRadius": None,
|
||||
"velocity" : 0
|
||||
}
|
||||
|
||||
def __init__(self, fit, data=None):
|
||||
Graph.__init__(self, fit, self.calcDps, data if data is not None else self.defaults)
|
||||
self.fit = fit
|
||||
|
||||
def calcDps(self, data):
|
||||
ew = {'signatureRadius': [], 'velocity': []}
|
||||
fit = self.fit
|
||||
def getYForX(self, fit, extraData, distance):
|
||||
tgtSpeed = extraData['speed']
|
||||
tgtSigRad = extraData['signatureRadius'] if extraData['signatureRadius'] is not None else inf
|
||||
angle = extraData['angle']
|
||||
tgtSigRadMods = []
|
||||
tgtSpeedMods = []
|
||||
total = 0
|
||||
distance = data["distance"] * 1000
|
||||
abssort = lambda _val: -abs(_val - 1)
|
||||
distance = distance * 1000
|
||||
|
||||
for mod in fit.modules:
|
||||
if not mod.isEmpty and mod.state >= FittingModuleState.ACTIVE:
|
||||
if "remoteTargetPaintFalloff" in mod.item.effects or "structureModuleEffectTargetPainter" in mod.item.effects:
|
||||
ew['signatureRadius'].append(
|
||||
1 + (mod.getModifiedItemAttr("signatureRadiusBonus") / 100) * self.calculateModuleMultiplier(
|
||||
mod, data))
|
||||
tgtSigRadMods.append(
|
||||
1 + (mod.getModifiedItemAttr("signatureRadiusBonus") / 100)
|
||||
* self.calculateModuleMultiplier(mod, distance))
|
||||
if "remoteWebifierFalloff" in mod.item.effects or "structureModuleEffectStasisWebifier" in mod.item.effects:
|
||||
if distance <= mod.getModifiedItemAttr("maxRange"):
|
||||
ew['velocity'].append(1 + (mod.getModifiedItemAttr("speedFactor") / 100))
|
||||
tgtSpeedMods.append(1 + (mod.getModifiedItemAttr("speedFactor") / 100))
|
||||
elif mod.getModifiedItemAttr("falloffEffectiveness") > 0:
|
||||
# I am affected by falloff
|
||||
ew['velocity'].append(
|
||||
1 + (mod.getModifiedItemAttr("speedFactor") / 100) * self.calculateModuleMultiplier(mod,
|
||||
data))
|
||||
tgtSpeedMods.append(
|
||||
1 + (mod.getModifiedItemAttr("speedFactor") / 100) *
|
||||
self.calculateModuleMultiplier(mod, distance))
|
||||
|
||||
ew['signatureRadius'].sort(key=abssort)
|
||||
ew['velocity'].sort(key=abssort)
|
||||
|
||||
for attr, values in ew.items():
|
||||
val = data[attr]
|
||||
try:
|
||||
for i in range(len(values)):
|
||||
bonus = values[i]
|
||||
val *= 1 + (bonus - 1) * exp(- i ** 2 / 7.1289)
|
||||
data[attr] = val
|
||||
except Exception as e:
|
||||
pyfalog.critical("Caught exception in calcDPS.")
|
||||
pyfalog.critical(e)
|
||||
tgtSpeed = self.penalizeModChain(tgtSpeed, tgtSpeedMods)
|
||||
tgtSigRad = self.penalizeModChain(tgtSigRad, tgtSigRadMods)
|
||||
attRad = fit.ship.getModifiedItemAttr('radius', 0)
|
||||
|
||||
for mod in fit.modules:
|
||||
dps = mod.getDps(targetResists=fit.targetResists).total
|
||||
if mod.hardpoint == FittingHardpoint.TURRET:
|
||||
if mod.state >= FittingModuleState.ACTIVE:
|
||||
total += dps * self.calculateTurretMultiplier(mod, data)
|
||||
total += dps * self.calculateTurretMultiplier(fit, mod, distance, angle, tgtSpeed, tgtSigRad)
|
||||
|
||||
elif mod.hardpoint == FittingHardpoint.MISSILE:
|
||||
if mod.state >= FittingModuleState.ACTIVE and mod.maxRange is not None and mod.maxRange >= distance:
|
||||
total += dps * self.calculateMissileMultiplier(mod, data)
|
||||
if mod.state >= FittingModuleState.ACTIVE and mod.maxRange is not None and (mod.maxRange - attRad) >= distance:
|
||||
total += dps * self.calculateMissileMultiplier(mod, tgtSpeed, tgtSigRad)
|
||||
|
||||
if distance <= fit.extraAttributes["droneControlRange"]:
|
||||
if distance <= fit.extraAttributes['droneControlRange']:
|
||||
for drone in fit.drones:
|
||||
multiplier = 1 if drone.getModifiedItemAttr("maxVelocity") > 1 else self.calculateTurretMultiplier(
|
||||
drone, data)
|
||||
multiplier = 1 if drone.getModifiedItemAttr('maxVelocity') > 1 else self.calculateTurretMultiplier(
|
||||
fit, drone, distance, angle, tgtSpeed, tgtSigRad)
|
||||
dps = drone.getDps(targetResists=fit.targetResists).total
|
||||
total += dps * multiplier
|
||||
|
||||
@@ -103,69 +85,62 @@ class FitDpsRangeGraph(Graph):
|
||||
if ability.dealsDamage and ability.active:
|
||||
if ability.effectID not in fighterDpsMap:
|
||||
continue
|
||||
multiplier = self.calculateFighterMissileMultiplier(ability, data)
|
||||
multiplier = self.calculateFighterMissileMultiplier(tgtSpeed, tgtSigRad, ability)
|
||||
dps = fighterDpsMap[ability.effectID].total
|
||||
total += dps * multiplier
|
||||
|
||||
return total
|
||||
|
||||
@staticmethod
|
||||
def calculateMissileMultiplier(mod, data):
|
||||
targetSigRad = data["signatureRadius"]
|
||||
targetVelocity = data["velocity"]
|
||||
explosionRadius = mod.getModifiedChargeAttr("aoeCloudSize")
|
||||
targetSigRad = explosionRadius if targetSigRad is None else targetSigRad
|
||||
explosionVelocity = mod.getModifiedChargeAttr("aoeVelocity")
|
||||
damageReductionFactor = mod.getModifiedChargeAttr("aoeDamageReductionFactor")
|
||||
def calculateMissileMultiplier(mod, tgtSpeed, tgtSigRad):
|
||||
explosionRadius = mod.getModifiedChargeAttr('aoeCloudSize')
|
||||
explosionVelocity = mod.getModifiedChargeAttr('aoeVelocity')
|
||||
damageReductionFactor = mod.getModifiedChargeAttr('aoeDamageReductionFactor')
|
||||
|
||||
sigRadiusFactor = targetSigRad / explosionRadius
|
||||
if targetVelocity:
|
||||
velocityFactor = (explosionVelocity / explosionRadius * targetSigRad / targetVelocity) ** damageReductionFactor
|
||||
sigRadiusFactor = tgtSigRad / explosionRadius
|
||||
if tgtSpeed:
|
||||
velocityFactor = (explosionVelocity / explosionRadius * tgtSigRad / tgtSpeed) ** damageReductionFactor
|
||||
else:
|
||||
velocityFactor = 1
|
||||
|
||||
return min(sigRadiusFactor, velocityFactor, 1)
|
||||
|
||||
def calculateTurretMultiplier(self, mod, data):
|
||||
@classmethod
|
||||
def calculateTurretMultiplier(cls, fit, mod, distance, angle, tgtSpeed, tgtSigRad):
|
||||
# Source for most of turret calculation info: http://wiki.eveonline.com/en/wiki/Falloff
|
||||
chanceToHit = self.calculateTurretChanceToHit(mod, data)
|
||||
chanceToHit = cls.calculateTurretChanceToHit(fit, mod, distance, angle, tgtSpeed, tgtSigRad)
|
||||
if chanceToHit > 0.01:
|
||||
# AvgDPS = Base Damage * [ ( ChanceToHit^2 + ChanceToHit + 0.0499 ) / 2 ]
|
||||
multiplier = (chanceToHit ** 2 + chanceToHit + 0.0499) / 2
|
||||
else:
|
||||
# All hits are wreckings
|
||||
multiplier = chanceToHit * 3
|
||||
dmgScaling = mod.getModifiedItemAttr("turretDamageScalingRadius")
|
||||
dmgScaling = mod.getModifiedItemAttr('turretDamageScalingRadius')
|
||||
if dmgScaling:
|
||||
targetSigRad = data["signatureRadius"]
|
||||
multiplier = min(1, (float(targetSigRad) / dmgScaling) ** 2)
|
||||
multiplier = min(1, (float(tgtSigRad) / dmgScaling) ** 2)
|
||||
return multiplier
|
||||
|
||||
@staticmethod
|
||||
def calculateFighterMissileMultiplier(ability, data):
|
||||
def calculateFighterMissileMultiplier(tgtSpeed, tgtSigRad, ability):
|
||||
prefix = ability.attrPrefix
|
||||
|
||||
targetSigRad = data["signatureRadius"]
|
||||
targetVelocity = data["velocity"]
|
||||
explosionRadius = ability.fighter.getModifiedItemAttr("{}ExplosionRadius".format(prefix))
|
||||
explosionVelocity = ability.fighter.getModifiedItemAttr("{}ExplosionVelocity".format(prefix))
|
||||
damageReductionFactor = ability.fighter.getModifiedItemAttr("{}ReductionFactor".format(prefix), None)
|
||||
explosionRadius = ability.fighter.getModifiedItemAttr('{}ExplosionRadius'.format(prefix))
|
||||
explosionVelocity = ability.fighter.getModifiedItemAttr('{}ExplosionVelocity'.format(prefix))
|
||||
damageReductionFactor = ability.fighter.getModifiedItemAttr('{}ReductionFactor'.format(prefix), None)
|
||||
|
||||
# the following conditionals are because CCP can't keep a decent naming convention, as if fighter implementation
|
||||
# wasn't already fucked.
|
||||
if damageReductionFactor is None:
|
||||
damageReductionFactor = ability.fighter.getModifiedItemAttr("{}DamageReductionFactor".format(prefix))
|
||||
damageReductionFactor = ability.fighter.getModifiedItemAttr('{}DamageReductionFactor'.format(prefix))
|
||||
|
||||
damageReductionSensitivity = ability.fighter.getModifiedItemAttr("{}ReductionSensitivity".format(prefix), None)
|
||||
damageReductionSensitivity = ability.fighter.getModifiedItemAttr('{}ReductionSensitivity'.format(prefix), None)
|
||||
if damageReductionSensitivity is None:
|
||||
damageReductionSensitivity = ability.fighter.getModifiedItemAttr(
|
||||
"{}DamageReductionSensitivity".format(prefix))
|
||||
damageReductionSensitivity = ability.fighter.getModifiedItemAttr('{}DamageReductionSensitivity'.format(prefix))
|
||||
|
||||
targetSigRad = explosionRadius if targetSigRad is None else targetSigRad
|
||||
sigRadiusFactor = targetSigRad / explosionRadius
|
||||
sigRadiusFactor = tgtSigRad / explosionRadius
|
||||
|
||||
if targetVelocity:
|
||||
velocityFactor = (explosionVelocity / explosionRadius * targetSigRad / targetVelocity) ** (
|
||||
if tgtSpeed:
|
||||
velocityFactor = (explosionVelocity / explosionRadius * tgtSigRad / tgtSpeed) ** (
|
||||
log(damageReductionFactor) / log(damageReductionSensitivity))
|
||||
else:
|
||||
velocityFactor = 1
|
||||
@@ -173,28 +148,47 @@ class FitDpsRangeGraph(Graph):
|
||||
return min(sigRadiusFactor, velocityFactor, 1)
|
||||
|
||||
@staticmethod
|
||||
def calculateTurretChanceToHit(mod, data):
|
||||
distance = data["distance"] * 1000
|
||||
tracking = mod.getModifiedItemAttr("trackingSpeed")
|
||||
def calculateTurretChanceToHit(fit, mod, distance, angle, tgtSpeed, tgtSigRad):
|
||||
tracking = mod.getModifiedItemAttr('trackingSpeed')
|
||||
turretOptimal = mod.maxRange
|
||||
turretFalloff = mod.falloff
|
||||
turretSigRes = mod.getModifiedItemAttr("optimalSigRadius")
|
||||
targetSigRad = data["signatureRadius"]
|
||||
targetSigRad = turretSigRes if targetSigRad is None else targetSigRad
|
||||
transversal = sin(radians(data["angle"])) * data["velocity"]
|
||||
trackingEq = (((transversal / (distance * tracking)) *
|
||||
(turretSigRes / targetSigRad)) ** 2)
|
||||
turretSigRes = mod.getModifiedItemAttr('optimalSigRadius')
|
||||
transversal = sin(radians(angle)) * tgtSpeed
|
||||
|
||||
# Angular velocity is calculated using range from ship center to target center.
|
||||
# We do not know target radius but we know attacker radius
|
||||
angDistance = distance + fit.ship.getModifiedItemAttr('radius', 0)
|
||||
if angDistance == 0 and transversal == 0:
|
||||
angularVelocity = 0
|
||||
elif angDistance == 0 and transversal != 0:
|
||||
angularVelocity = inf
|
||||
else:
|
||||
angularVelocity = transversal / angDistance
|
||||
trackingEq = (((angularVelocity / tracking) *
|
||||
(turretSigRes / tgtSigRad)) ** 2)
|
||||
rangeEq = ((max(0, distance - turretOptimal)) / turretFalloff) ** 2
|
||||
|
||||
return 0.5 ** (trackingEq + rangeEq)
|
||||
|
||||
@staticmethod
|
||||
def calculateModuleMultiplier(mod, data):
|
||||
def calculateModuleMultiplier(mod, distance):
|
||||
# Simplified formula, we make some assumptions about the module
|
||||
# This is basically the calculateTurretChanceToHit without tracking values
|
||||
distance = data["distance"] * 1000
|
||||
turretOptimal = mod.maxRange
|
||||
turretFalloff = mod.falloff
|
||||
rangeEq = ((max(0, distance - turretOptimal)) / turretFalloff) ** 2
|
||||
|
||||
return 0.5 ** rangeEq
|
||||
|
||||
@staticmethod
|
||||
def penalizeModChain(value, mods):
|
||||
mods.sort(key=lambda v: -abs(v - 1))
|
||||
try:
|
||||
for i in range(len(mods)):
|
||||
bonus = mods[i]
|
||||
value *= 1 + (bonus - 1) * exp(- i ** 2 / 7.1289)
|
||||
return value
|
||||
except Exception as e:
|
||||
pyfalog.critical('Caught exception when penalizing modifier chain.')
|
||||
pyfalog.critical(e)
|
||||
return value
|
||||
165
eos/graph/fitDpsVsTime.py
Normal file
165
eos/graph/fitDpsVsTime.py
Normal file
@@ -0,0 +1,165 @@
|
||||
# ===============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of eos.
|
||||
#
|
||||
# eos is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# eos is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# 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 itertools import chain
|
||||
|
||||
from eos.graph import Graph
|
||||
from eos.utils.spoolSupport import SpoolType, SpoolOptions
|
||||
from gui.utils.numberFormatter import roundToPrec
|
||||
|
||||
|
||||
class FitDpsVsTimeGraph(Graph):
|
||||
|
||||
def getPlotPoints(self, fit, extraData, xRange, xAmount):
|
||||
# We deliberately ignore xAmount here to build graph which will reflect
|
||||
# all steps of building up the damage
|
||||
minX, maxX = self._limitXRange(xRange, fit, extraData)
|
||||
if fit.ID not in self._cache:
|
||||
self.__generateCache(fit, maxX)
|
||||
currentY = None
|
||||
prevY = None
|
||||
xs = []
|
||||
ys = []
|
||||
cache = self._cache[fit.ID]
|
||||
for time in sorted(cache):
|
||||
prevY = currentY
|
||||
currentX = time / 1000
|
||||
currentY = roundToPrec(cache[time], 6)
|
||||
if currentX < minX:
|
||||
continue
|
||||
# First set of data points
|
||||
if not xs:
|
||||
# Start at exactly requested time, at last known value
|
||||
initialY = prevY or 0
|
||||
xs.append(minX)
|
||||
ys.append(initialY)
|
||||
# If current time is bigger then starting, extend plot to that time with old value
|
||||
if currentX > minX:
|
||||
xs.append(currentX)
|
||||
ys.append(initialY)
|
||||
# If new value is different, extend it with new point to the new value
|
||||
if currentY != prevY:
|
||||
xs.append(currentX)
|
||||
ys.append(currentY)
|
||||
continue
|
||||
# Last data point
|
||||
if currentX >= maxX:
|
||||
xs.append(maxX)
|
||||
ys.append(prevY)
|
||||
break
|
||||
# Anything in-between
|
||||
if currentY != prevY:
|
||||
if prevY is not None:
|
||||
xs.append(currentX)
|
||||
ys.append(prevY)
|
||||
xs.append(currentX)
|
||||
ys.append(currentY)
|
||||
if max(xs) < maxX:
|
||||
xs.append(maxX)
|
||||
ys.append(currentY or 0)
|
||||
return xs, ys
|
||||
|
||||
def getYForX(self, fit, extraData, x):
|
||||
time = x * 1000
|
||||
cache = self._cache[fit.ID]
|
||||
closestTime = max((t for t in cache if t <= time), default=None)
|
||||
if closestTime is None:
|
||||
return 0
|
||||
return roundToPrec(cache[closestTime], 6)
|
||||
|
||||
def _getXLimits(self, fit, extraData):
|
||||
return 0, 2500
|
||||
|
||||
def __generateCache(self, fit, maxTime):
|
||||
cache = []
|
||||
|
||||
def addDmg(addedTimeStart, addedTimeFinish, addedDmg):
|
||||
if addedDmg == 0:
|
||||
return
|
||||
addedDps = 1000 * addedDmg / (addedTimeFinish - addedTimeStart)
|
||||
cache.append((addedTimeStart, addedTimeFinish, addedDps))
|
||||
|
||||
# We'll handle calculations in milliseconds
|
||||
maxTime = maxTime * 1000
|
||||
for mod in fit.modules:
|
||||
if not mod.isDealingDamage():
|
||||
continue
|
||||
cycleParams = mod.getCycleParameters(reloadOverride=True)
|
||||
if cycleParams is None:
|
||||
continue
|
||||
currentTime = 0
|
||||
nonstopCycles = 0
|
||||
for cycleTime, inactiveTime in cycleParams.iterCycles():
|
||||
cycleDamage = 0
|
||||
volleyParams = mod.getVolleyParameters(spoolOptions=SpoolOptions(SpoolType.CYCLES, nonstopCycles, True))
|
||||
for volleyTime, volley in volleyParams.items():
|
||||
cycleDamage += volley.total
|
||||
addDmg(currentTime, currentTime + cycleTime, cycleDamage)
|
||||
currentTime += cycleTime + inactiveTime
|
||||
if inactiveTime > 0:
|
||||
nonstopCycles = 0
|
||||
else:
|
||||
nonstopCycles += 1
|
||||
if currentTime > maxTime:
|
||||
break
|
||||
for drone in fit.drones:
|
||||
if not drone.isDealingDamage():
|
||||
continue
|
||||
cycleParams = drone.getCycleParameters(reloadOverride=True)
|
||||
if cycleParams is None:
|
||||
continue
|
||||
currentTime = 0
|
||||
for cycleTime, inactiveTime in cycleParams.iterCycles():
|
||||
cycleDamage = 0
|
||||
volleyParams = drone.getVolleyParameters()
|
||||
for volleyTime, volley in volleyParams.items():
|
||||
cycleDamage += volley.total
|
||||
addDmg(currentTime, currentTime + cycleTime, cycleDamage)
|
||||
currentTime += cycleTime + inactiveTime
|
||||
if currentTime > maxTime:
|
||||
break
|
||||
for fighter in fit.fighters:
|
||||
if not fighter.isDealingDamage():
|
||||
continue
|
||||
cycleParams = fighter.getCycleParametersPerEffectOptimizedDps(reloadOverride=True)
|
||||
if cycleParams is None:
|
||||
continue
|
||||
volleyParams = fighter.getVolleyParametersPerEffect()
|
||||
for effectID, abilityCycleParams in cycleParams.items():
|
||||
if effectID not in volleyParams:
|
||||
continue
|
||||
abilityVolleyParams = volleyParams[effectID]
|
||||
currentTime = 0
|
||||
for cycleTime, inactiveTime in abilityCycleParams.iterCycles():
|
||||
cycleDamage = 0
|
||||
for volleyTime, volley in abilityVolleyParams.items():
|
||||
cycleDamage += volley.total
|
||||
addDmg(currentTime, currentTime + cycleTime, cycleDamage)
|
||||
currentTime += cycleTime + inactiveTime
|
||||
if currentTime > maxTime:
|
||||
break
|
||||
|
||||
# Post-process cache
|
||||
finalCache = {}
|
||||
for time in sorted(set(chain((i[0] for i in cache), (i[1] for i in cache)))):
|
||||
entries = (e for e in cache if e[0] <= time < e[1])
|
||||
dps = sum(e[2] for e in entries)
|
||||
finalCache[time] = dps
|
||||
self._cache[fit.ID] = finalCache
|
||||
27
eos/graph/fitShieldAmountVsTime.py
Normal file
27
eos/graph/fitShieldAmountVsTime.py
Normal file
@@ -0,0 +1,27 @@
|
||||
import math
|
||||
from logbook import Logger
|
||||
|
||||
from eos.graph import SmoothGraph
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class FitShieldAmountVsTimeGraph(SmoothGraph):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
import gui.mainFrame
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def getYForX(self, fit, extraData, time):
|
||||
if time < 0:
|
||||
return 0
|
||||
maxShield = fit.ship.getModifiedItemAttr('shieldCapacity')
|
||||
regenTime = fit.ship.getModifiedItemAttr('shieldRechargeRate') / 1000
|
||||
# https://wiki.eveuniversity.org/Capacitor#Capacitor_recharge_rate (shield is similar to cap)
|
||||
shield = maxShield * (1 + math.exp(5 * -time / regenTime) * -1) ** 2
|
||||
useEhp = self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective
|
||||
if fit.damagePattern is not None and useEhp:
|
||||
shield = fit.damagePattern.effectivify(fit, shield, 'shield')
|
||||
return shield
|
||||
22
eos/graph/fitShieldRegenVsShieldPerc.py
Normal file
22
eos/graph/fitShieldRegenVsShieldPerc.py
Normal file
@@ -0,0 +1,22 @@
|
||||
import math
|
||||
|
||||
from eos.graph import SmoothGraph
|
||||
|
||||
|
||||
class FitShieldRegenVsShieldPercGraph(SmoothGraph):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
import gui.mainFrame
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def getYForX(self, fit, extraData, perc):
|
||||
maxShield = fit.ship.getModifiedItemAttr('shieldCapacity')
|
||||
regenTime = fit.ship.getModifiedItemAttr('shieldRechargeRate') / 1000
|
||||
currentShield = maxShield * perc / 100
|
||||
# https://wiki.eveuniversity.org/Capacitor#Capacitor_recharge_rate (shield is similar to cap)
|
||||
regen = 10 * maxShield / regenTime * (math.sqrt(currentShield / maxShield) - currentShield / maxShield)
|
||||
useEhp = self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective
|
||||
if fit.damagePattern is not None and useEhp:
|
||||
regen = fit.damagePattern.effectivify(fit, regen, 'shield')
|
||||
return regen
|
||||
14
eos/graph/fitSpeedVsTime.py
Normal file
14
eos/graph/fitSpeedVsTime.py
Normal file
@@ -0,0 +1,14 @@
|
||||
import math
|
||||
|
||||
from eos.graph import SmoothGraph
|
||||
|
||||
|
||||
class FitSpeedVsTimeGraph(SmoothGraph):
|
||||
|
||||
def getYForX(self, fit, extraData, time):
|
||||
maxSpeed = fit.ship.getModifiedItemAttr('maxVelocity')
|
||||
mass = fit.ship.getModifiedItemAttr('mass')
|
||||
agility = fit.ship.getModifiedItemAttr('agility')
|
||||
# https://wiki.eveuniversity.org/Acceleration#Mathematics_and_formulae
|
||||
speed = maxSpeed * (1 - math.exp((-time * 1000000) / (agility * mass)))
|
||||
return speed
|
||||
98
eos/graph/fitWarpTimeVsDistance.py
Normal file
98
eos/graph/fitWarpTimeVsDistance.py
Normal file
@@ -0,0 +1,98 @@
|
||||
import math
|
||||
|
||||
from eos.const import FittingModuleState
|
||||
from eos.graph import SmoothGraph
|
||||
|
||||
|
||||
AU_METERS = 149597870700
|
||||
|
||||
|
||||
class FitWarpTimeVsDistanceGraph(SmoothGraph):
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.subwarpSpeed = None
|
||||
|
||||
def getYForX(self, fit, extraData, distance):
|
||||
if distance == 0:
|
||||
return 0
|
||||
if fit.ID not in self._cache:
|
||||
self.__generateCache(fit)
|
||||
maxWarpSpeed = fit.warpSpeed
|
||||
subwarpSpeed = self._cache[fit.ID]['cleanSubwarpSpeed']
|
||||
time = calculate_time_in_warp(maxWarpSpeed, subwarpSpeed, distance * AU_METERS)
|
||||
return time
|
||||
|
||||
def _getXLimits(self, fit, extraData):
|
||||
return 0, fit.maxWarpDistance
|
||||
|
||||
def __generateCache(self, fit):
|
||||
modStates = {}
|
||||
for mod in fit.modules:
|
||||
if mod.item is not None and mod.item.group.name in ('Propulsion Module', 'Mass Entanglers', 'Cloaking Device') and mod.state >= FittingModuleState.ACTIVE:
|
||||
modStates[mod] = mod.state
|
||||
mod.state = FittingModuleState.ONLINE
|
||||
projFitStates = {}
|
||||
for projFit in fit.projectedFits:
|
||||
projectionInfo = projFit.getProjectionInfo(fit.ID)
|
||||
if projectionInfo is not None and projectionInfo.active:
|
||||
projFitStates[projectionInfo] = projectionInfo.active
|
||||
projectionInfo.active = False
|
||||
projModStates = {}
|
||||
for mod in fit.projectedModules:
|
||||
if not mod.isExclusiveSystemEffect and mod.state >= FittingModuleState.ACTIVE:
|
||||
projModStates[mod] = mod.state
|
||||
mod.state = FittingModuleState.ONLINE
|
||||
projDroneStates = {}
|
||||
for drone in fit.projectedDrones:
|
||||
if drone.amountActive > 0:
|
||||
projDroneStates[drone] = drone.amountActive
|
||||
drone.amountActive = 0
|
||||
projFighterStates = {}
|
||||
for fighter in fit.projectedFighters:
|
||||
if fighter.active:
|
||||
projFighterStates[fighter] = fighter.active
|
||||
fighter.active = False
|
||||
fit.calculateModifiedAttributes()
|
||||
self._cache[fit.ID] = {'cleanSubwarpSpeed': fit.ship.getModifiedItemAttr('maxVelocity')}
|
||||
for projInfo, state in projFitStates.items():
|
||||
projInfo.active = state
|
||||
for mod, state in modStates.items():
|
||||
mod.state = state
|
||||
for mod, state in projModStates.items():
|
||||
mod.state = state
|
||||
for drone, amountActive in projDroneStates.items():
|
||||
drone.amountActive = amountActive
|
||||
for fighter, state in projFighterStates.items():
|
||||
fighter.active = state
|
||||
fit.calculateModifiedAttributes()
|
||||
|
||||
|
||||
# Taken from https://wiki.eveuniversity.org/Warp_time_calculation#Implementation
|
||||
# with minor modifications
|
||||
# Warp speed in AU/s, subwarp speed in m/s, distance in m
|
||||
def calculate_time_in_warp(max_warp_speed, max_subwarp_speed, warp_dist):
|
||||
|
||||
k_accel = max_warp_speed
|
||||
k_decel = min(max_warp_speed / 3, 2)
|
||||
|
||||
warp_dropout_speed = max_subwarp_speed / 2
|
||||
max_ms_warp_speed = max_warp_speed * AU_METERS
|
||||
|
||||
accel_dist = AU_METERS
|
||||
decel_dist = max_ms_warp_speed / k_decel
|
||||
|
||||
minimum_dist = accel_dist + decel_dist
|
||||
|
||||
cruise_time = 0
|
||||
|
||||
if minimum_dist > warp_dist:
|
||||
max_ms_warp_speed = warp_dist * k_accel * k_decel / (k_accel + k_decel)
|
||||
else:
|
||||
cruise_time = (warp_dist - minimum_dist) / max_ms_warp_speed
|
||||
|
||||
accel_time = math.log(max_ms_warp_speed / k_accel) / k_accel
|
||||
decel_time = math.log(max_ms_warp_speed / warp_dropout_speed) / k_decel
|
||||
|
||||
total_time = cruise_time + accel_time + decel_time
|
||||
return total_time
|
||||
@@ -17,13 +17,14 @@
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
import math
|
||||
from logbook import Logger
|
||||
|
||||
from sqlalchemy.orm import validates, reconstructor
|
||||
from sqlalchemy.orm import reconstructor, validates
|
||||
|
||||
import eos.db
|
||||
from eos.effectHandlerHelpers import HandledItem, HandledCharge
|
||||
from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut
|
||||
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
||||
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
|
||||
from eos.utils.cycles import CycleInfo
|
||||
from eos.utils.stats import DmgTypes
|
||||
|
||||
|
||||
@@ -104,7 +105,16 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
|
||||
@property
|
||||
def cycleTime(self):
|
||||
return max(self.getModifiedItemAttr("duration", 0), 0)
|
||||
if self.hasAmmo:
|
||||
cycleTime = self.getModifiedItemAttr("missileLaunchDuration", 0)
|
||||
else:
|
||||
for attr in ("speed", "duration"):
|
||||
cycleTime = self.getModifiedItemAttr(attr, None)
|
||||
if cycleTime is not None:
|
||||
break
|
||||
if cycleTime is None:
|
||||
return 0
|
||||
return max(cycleTime, 0)
|
||||
|
||||
@property
|
||||
def dealsDamage(self):
|
||||
@@ -121,9 +131,16 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
def hasAmmo(self):
|
||||
return self.charge is not None
|
||||
|
||||
def getVolley(self, targetResists=None):
|
||||
def isDealingDamage(self):
|
||||
volleyParams = self.getVolleyParameters()
|
||||
for volley in volleyParams.values():
|
||||
if volley.total > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def getVolleyParameters(self, targetResists=None):
|
||||
if not self.dealsDamage or self.amountActive <= 0:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
return {0: DmgTypes(0, 0, 0, 0)}
|
||||
if self.__baseVolley is None:
|
||||
dmgGetter = self.getModifiedChargeAttr if self.hasAmmo else self.getModifiedItemAttr
|
||||
dmgMult = self.amountActive * (self.getModifiedItemAttr("damageMultiplier", 1))
|
||||
@@ -137,15 +154,19 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
thermal=self.__baseVolley.thermal * (1 - getattr(targetResists, "thermalAmount", 0)),
|
||||
kinetic=self.__baseVolley.kinetic * (1 - getattr(targetResists, "kineticAmount", 0)),
|
||||
explosive=self.__baseVolley.explosive * (1 - getattr(targetResists, "explosiveAmount", 0)))
|
||||
return volley
|
||||
return {0: volley}
|
||||
|
||||
def getVolley(self, targetResists=None):
|
||||
return self.getVolleyParameters(targetResists=targetResists)[0]
|
||||
|
||||
def getDps(self, targetResists=None):
|
||||
volley = self.getVolley(targetResists=targetResists)
|
||||
if not volley:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
cycleAttr = "missileLaunchDuration" if self.hasAmmo else "speed"
|
||||
cycleTime = self.getModifiedItemAttr(cycleAttr)
|
||||
dpsFactor = 1 / (cycleTime / 1000)
|
||||
cycleParams = self.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
dpsFactor = 1 / (cycleParams.averageTime / 1000)
|
||||
dps = DmgTypes(
|
||||
em=volley.em * dpsFactor,
|
||||
thermal=volley.thermal * dpsFactor,
|
||||
@@ -153,6 +174,12 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
explosive=volley.explosive * dpsFactor)
|
||||
return dps
|
||||
|
||||
def getCycleParameters(self, reloadOverride=None):
|
||||
cycleTime = self.cycleTime
|
||||
if cycleTime == 0:
|
||||
return None
|
||||
return CycleInfo(self.cycleTime, 0, math.inf)
|
||||
|
||||
def getRemoteReps(self, ignoreState=False):
|
||||
if self.amountActive <= 0 and not ignoreState:
|
||||
return (None, 0)
|
||||
@@ -174,7 +201,12 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
rrAmount = 0
|
||||
if rrAmount:
|
||||
droneAmount = self.amount if ignoreState else self.amountActive
|
||||
rrAmount *= droneAmount / (self.cycleTime / 1000)
|
||||
cycleParams = self.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
rrType = None
|
||||
rrAmount = 0
|
||||
else:
|
||||
rrAmount *= droneAmount / (cycleParams.averageTime / 1000)
|
||||
self.__baseRemoteReps = (rrType, rrAmount)
|
||||
return self.__baseRemoteReps
|
||||
|
||||
@@ -182,12 +214,14 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
def miningStats(self):
|
||||
if self.__miningyield is None:
|
||||
if self.mines is True and self.amountActive > 0:
|
||||
attr = "duration"
|
||||
getter = self.getModifiedItemAttr
|
||||
|
||||
cycleTime = self.getModifiedItemAttr(attr)
|
||||
volley = sum([getter(d) for d in self.MINING_ATTRIBUTES]) * self.amountActive
|
||||
self.__miningyield = volley / (cycleTime / 1000.0)
|
||||
cycleParams = self.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
self.__miningyield = 0
|
||||
else:
|
||||
cycleTime = cycleParams.averageTime
|
||||
volley = sum([getter(d) for d in self.MINING_ATTRIBUTES]) * self.amountActive
|
||||
self.__miningyield = volley / (cycleTime / 1000.0)
|
||||
else:
|
||||
self.__miningyield = 0
|
||||
|
||||
|
||||
@@ -17,16 +17,19 @@
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
import math
|
||||
from logbook import Logger
|
||||
|
||||
from sqlalchemy.orm import validates, reconstructor
|
||||
from sqlalchemy.orm import reconstructor, validates
|
||||
|
||||
import eos.db
|
||||
from eos.effectHandlerHelpers import HandledItem, HandledCharge
|
||||
from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut
|
||||
from eos.saveddata.fighterAbility import FighterAbility
|
||||
from eos.utils.stats import DmgTypes
|
||||
from eos.const import FittingSlot
|
||||
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
||||
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
|
||||
from eos.saveddata.fighterAbility import FighterAbility
|
||||
from eos.utils.cycles import CycleInfo, CycleSequence
|
||||
from eos.utils.stats import DmgTypes
|
||||
from eos.utils.float import floatUnerr
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
@@ -172,28 +175,45 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
def hasAmmo(self):
|
||||
return self.charge is not None
|
||||
|
||||
def getVolley(self, targetResists=None):
|
||||
def isDealingDamage(self):
|
||||
volleyParams = self.getVolleyParametersPerEffect()
|
||||
for effectData in volleyParams.values():
|
||||
for volley in effectData.values():
|
||||
if volley.total > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def getVolleyParametersPerEffect(self, targetResists=None):
|
||||
if not self.active or self.amountActive <= 0:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
return {}
|
||||
if self.__baseVolley is None:
|
||||
em = 0
|
||||
therm = 0
|
||||
kin = 0
|
||||
exp = 0
|
||||
self.__baseVolley = {}
|
||||
for ability in self.abilities:
|
||||
# Not passing resists here as we want to calculate and store base volley
|
||||
abilityVolley = ability.getVolley()
|
||||
em += abilityVolley.em
|
||||
therm += abilityVolley.thermal
|
||||
kin += abilityVolley.kinetic
|
||||
exp += abilityVolley.explosive
|
||||
self.__baseVolley = DmgTypes(em, therm, kin, exp)
|
||||
volley = DmgTypes(
|
||||
em=self.__baseVolley.em * (1 - getattr(targetResists, "emAmount", 0)),
|
||||
thermal=self.__baseVolley.thermal * (1 - getattr(targetResists, "thermalAmount", 0)),
|
||||
kinetic=self.__baseVolley.kinetic * (1 - getattr(targetResists, "kineticAmount", 0)),
|
||||
explosive=self.__baseVolley.explosive * (1 - getattr(targetResists, "explosiveAmount", 0)))
|
||||
return volley
|
||||
self.__baseVolley[ability.effectID] = {0: ability.getVolley()}
|
||||
adjustedVolley = {}
|
||||
for effectID, effectData in self.__baseVolley.items():
|
||||
adjustedVolley[effectID] = {}
|
||||
for volleyTime, volleyValue in effectData.items():
|
||||
adjustedVolley[effectID][volleyTime] = DmgTypes(
|
||||
em=volleyValue.em * (1 - getattr(targetResists, "emAmount", 0)),
|
||||
thermal=volleyValue.thermal * (1 - getattr(targetResists, "thermalAmount", 0)),
|
||||
kinetic=volleyValue.kinetic * (1 - getattr(targetResists, "kineticAmount", 0)),
|
||||
explosive=volleyValue.explosive * (1 - getattr(targetResists, "explosiveAmount", 0)))
|
||||
return adjustedVolley
|
||||
|
||||
def getVolley(self, targetResists=None):
|
||||
volleyParams = self.getVolleyParametersPerEffect(targetResists=targetResists)
|
||||
em = 0
|
||||
therm = 0
|
||||
kin = 0
|
||||
exp = 0
|
||||
for volleyData in volleyParams.values():
|
||||
em += volleyData[0].em
|
||||
therm += volleyData[0].thermal
|
||||
kin += volleyData[0].kinetic
|
||||
exp += volleyData[0].explosive
|
||||
return DmgTypes(em, therm, kin, exp)
|
||||
|
||||
def getDps(self, targetResists=None):
|
||||
em = 0
|
||||
@@ -207,44 +227,81 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
explosive += dps.explosive
|
||||
return DmgTypes(em=em, thermal=thermal, kinetic=kinetic, explosive=explosive)
|
||||
|
||||
def getUptime(self):
|
||||
if not self.owner.factorReload:
|
||||
return 1
|
||||
activeTimes = []
|
||||
reloadTimes = []
|
||||
for ability in self.abilities:
|
||||
if ability.numShots > 0:
|
||||
activeTimes.append(ability.numShots * ability.cycleTime)
|
||||
reloadTimes.append(ability.reloadTime)
|
||||
if not activeTimes:
|
||||
return 1
|
||||
shortestActive = sorted(activeTimes)[0]
|
||||
longestReload = sorted(reloadTimes, reverse=True)[0]
|
||||
uptime = shortestActive / (shortestActive + longestReload)
|
||||
return uptime
|
||||
|
||||
def getDpsPerEffect(self, targetResists=None):
|
||||
if not self.active or self.amountActive <= 0:
|
||||
return {}
|
||||
uptime = self.getUptime()
|
||||
if uptime == 1:
|
||||
return {a.effectID: a.getDps(targetResists=targetResists) for a in self.abilities}
|
||||
# Decide if it's better to keep steady dps up and never reload or reload from time to time
|
||||
dpsMapSteady = {}
|
||||
dpsMapPeakAdjusted = {}
|
||||
cycleParams = self.getCycleParametersPerEffectOptimizedDps(targetResists=targetResists)
|
||||
dpsMap = {}
|
||||
for ability in self.abilities:
|
||||
abilityDps = ability.getDps(targetResists=targetResists)
|
||||
dpsMapPeakAdjusted[ability.effectID] = DmgTypes(
|
||||
em=abilityDps.em * uptime,
|
||||
thermal=abilityDps.thermal * uptime,
|
||||
kinetic=abilityDps.kinetic * uptime,
|
||||
explosive=abilityDps.explosive * uptime)
|
||||
# Infinite use - add to steady dps
|
||||
if ability.numShots == 0:
|
||||
dpsMapSteady[ability.effectID] = abilityDps
|
||||
totalSteady = sum(i.total for i in dpsMapSteady.values())
|
||||
totalPeakAdjusted = sum(i.total for i in dpsMapPeakAdjusted.values())
|
||||
return dpsMapSteady if totalSteady >= totalPeakAdjusted else dpsMapPeakAdjusted
|
||||
if ability.effectID in cycleParams:
|
||||
cycleTime = cycleParams[ability.effectID].averageTime
|
||||
dpsMap[ability.effectID] = ability.getDps(targetResists=targetResists, cycleTimeOverride=cycleTime)
|
||||
return dpsMap
|
||||
|
||||
def getCycleParametersPerEffectOptimizedDps(self, targetResists=None, reloadOverride=None):
|
||||
cycleParamsInfinite = self.getCycleParametersPerEffectInfinite()
|
||||
cycleParamsReload = self.getCycleParametersPerEffect(reloadOverride=reloadOverride)
|
||||
dpsMapOnlyInfinite = {}
|
||||
dpsMapAllWithReloads = {}
|
||||
# Decide if it's better to keep steady dps up and never reload or reload from time to time
|
||||
for ability in self.abilities:
|
||||
if ability.effectID in cycleParamsInfinite:
|
||||
cycleTime = cycleParamsInfinite[ability.effectID].averageTime
|
||||
dpsMapOnlyInfinite[ability.effectID] = ability.getDps(targetResists=targetResists, cycleTimeOverride=cycleTime)
|
||||
if ability.effectID in cycleParamsReload:
|
||||
cycleTime = cycleParamsReload[ability.effectID].averageTime
|
||||
dpsMapAllWithReloads[ability.effectID] = ability.getDps(targetResists=targetResists, cycleTimeOverride=cycleTime)
|
||||
totalOnlyInfinite = sum(i.total for i in dpsMapOnlyInfinite.values())
|
||||
totalAllWithReloads = sum(i.total for i in dpsMapAllWithReloads.values())
|
||||
return cycleParamsInfinite if totalOnlyInfinite >= totalAllWithReloads else cycleParamsReload
|
||||
|
||||
def getCycleParametersPerEffectInfinite(self):
|
||||
return {a.effectID: CycleInfo(a.cycleTime, 0, math.inf) for a in self.abilities if a.numShots == 0 and a.cycleTime > 0}
|
||||
|
||||
def getCycleParametersPerEffect(self, reloadOverride=None):
|
||||
factorReload = reloadOverride if reloadOverride is not None else self.owner.factorReload
|
||||
# Assume it can cycle infinitely
|
||||
if not factorReload:
|
||||
return {a.effectID: CycleInfo(a.cycleTime, 0, math.inf) for a in self.abilities if a.cycleTime > 0}
|
||||
limitedAbilities = [a for a in self.abilities if a.numShots > 0 and a.cycleTime > 0]
|
||||
if len(limitedAbilities) == 0:
|
||||
return {a.effectID: CycleInfo(a.cycleTime, 0, math.inf) for a in self.abilities if a.cycleTime > 0}
|
||||
validAbilities = [a for a in self.abilities if a.cycleTime > 0]
|
||||
if len(validAbilities) == 0:
|
||||
return {}
|
||||
mostLimitedAbility = min(limitedAbilities, key=lambda a: a.cycleTime * a.numShots)
|
||||
durationToRefuel = mostLimitedAbility.cycleTime * mostLimitedAbility.numShots
|
||||
# find out how many shots various abilities will do until reload, and how much time
|
||||
# "extra" cycle will last (None for no extra cycle)
|
||||
cyclesUntilRefuel = {mostLimitedAbility.effectID: (mostLimitedAbility.numShots, None)}
|
||||
for ability in (a for a in validAbilities if a is not mostLimitedAbility):
|
||||
fullCycles = int(floatUnerr(durationToRefuel / ability.cycleTime))
|
||||
extraShotTime = floatUnerr(durationToRefuel - (fullCycles * ability.cycleTime))
|
||||
if extraShotTime == 0:
|
||||
extraShotTime = None
|
||||
cyclesUntilRefuel[ability.effectID] = (fullCycles, extraShotTime)
|
||||
refuelTimes = {}
|
||||
for ability in validAbilities:
|
||||
spentShots, extraShotTime = cyclesUntilRefuel[ability.effectID]
|
||||
if extraShotTime is not None:
|
||||
spentShots += 1
|
||||
refuelTimes[ability.effectID] = ability.getReloadTime(spentShots)
|
||||
refuelTime = max(refuelTimes.values())
|
||||
cycleParams = {}
|
||||
for ability in validAbilities:
|
||||
regularShots, extraShotTime = cyclesUntilRefuel[ability.effectID]
|
||||
sequence = []
|
||||
if extraShotTime is not None:
|
||||
if regularShots > 0:
|
||||
sequence.append(CycleInfo(ability.cycleTime, 0, regularShots))
|
||||
sequence.append(CycleInfo(extraShotTime, refuelTime, 1))
|
||||
else:
|
||||
regularShotsNonReload = regularShots - 1
|
||||
if regularShotsNonReload > 0:
|
||||
sequence.append(CycleInfo(ability.cycleTime, 0, regularShotsNonReload))
|
||||
sequence.append(CycleInfo(ability.cycleTime, refuelTime, 1))
|
||||
cycleParams[ability.effectID] = CycleSequence(sequence, math.inf)
|
||||
return cycleParams
|
||||
|
||||
@property
|
||||
def maxRange(self):
|
||||
|
||||
@@ -95,8 +95,15 @@ class FighterAbility(object):
|
||||
|
||||
@property
|
||||
def reloadTime(self):
|
||||
return self.getReloadTime()
|
||||
|
||||
def getReloadTime(self, spentShots=None):
|
||||
if spentShots is not None:
|
||||
spentShots = max(self.numShots, spentShots)
|
||||
else:
|
||||
spentShots = self.numShots
|
||||
rearm_time = (self.REARM_TIME_MAPPING[self.fighter.getModifiedItemAttr("fighterSquadronRole")] or 0 if self.hasCharges else 0)
|
||||
return self.fighter.getModifiedItemAttr("fighterRefuelingTime") + rearm_time * self.numShots
|
||||
return self.fighter.getModifiedItemAttr("fighterRefuelingTime") + rearm_time * spentShots
|
||||
|
||||
@property
|
||||
def numShots(self):
|
||||
@@ -128,11 +135,12 @@ class FighterAbility(object):
|
||||
explosive=exp * dmgMult * (1 - getattr(targetResists, "explosiveAmount", 0)))
|
||||
return volley
|
||||
|
||||
def getDps(self, targetResists=None):
|
||||
def getDps(self, targetResists=None, cycleTimeOverride=None):
|
||||
volley = self.getVolley(targetResists=targetResists)
|
||||
if not volley:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
dpsFactor = 1 / (self.cycleTime / 1000)
|
||||
cycleTime = cycleTimeOverride if cycleTimeOverride is not None else self.cycleTime
|
||||
dpsFactor = 1 / (cycleTime / 1000)
|
||||
dps = DmgTypes(
|
||||
em=volley.em * dpsFactor,
|
||||
thermal=volley.thermal * dpsFactor,
|
||||
|
||||
@@ -17,21 +17,22 @@
|
||||
# along with eos. If not, see <http://www.gnu.org/licenses/>.
|
||||
# ===============================================================================
|
||||
|
||||
from math import floor
|
||||
|
||||
from logbook import Logger
|
||||
import math
|
||||
from sqlalchemy.orm import reconstructor, validates
|
||||
|
||||
import eos.db
|
||||
from eos.const import FittingModuleState, FittingHardpoint, FittingSlot
|
||||
from eos.const import FittingHardpoint, FittingModuleState, FittingSlot
|
||||
from eos.effectHandlerHelpers import HandledCharge, HandledItem
|
||||
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
|
||||
from eos.saveddata.citadel import Citadel
|
||||
from eos.saveddata.mutator import Mutator
|
||||
from eos.utils.cycles import CycleInfo, CycleSequence
|
||||
from eos.utils.float import floatUnerr
|
||||
from eos.utils.spoolSupport import calculateSpoolup, resolveSpoolOptions
|
||||
from eos.utils.stats import DmgTypes
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
ProjectedMap = {
|
||||
@@ -287,7 +288,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
# numcycles = math.floor(module_capacity / (module_volume * module_chargerate))
|
||||
chargeRate = self.getModifiedItemAttr("chargeRate")
|
||||
numCharges = self.numCharges
|
||||
numShots = floor(numCharges / chargeRate)
|
||||
numShots = math.floor(numCharges / chargeRate)
|
||||
else:
|
||||
numShots = None
|
||||
return numShots
|
||||
@@ -300,7 +301,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
chance = self.getModifiedChargeAttr("crystalVolatilityChance")
|
||||
damage = self.getModifiedChargeAttr("crystalVolatilityDamage")
|
||||
crystals = self.numCharges
|
||||
numShots = floor((crystals * hp) / (damage * chance))
|
||||
numShots = math.floor((crystals * hp) / (damage * chance))
|
||||
else:
|
||||
# Set 0 (infinite) for permanent crystals like t1 laser crystals
|
||||
numShots = 0
|
||||
@@ -400,8 +401,12 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
volley = self.getModifiedItemAttr("specialtyMiningAmount") or self.getModifiedItemAttr(
|
||||
"miningAmount") or 0
|
||||
if volley:
|
||||
cycleTime = self.cycleTime
|
||||
self.__miningyield = volley / (cycleTime / 1000.0)
|
||||
cycleParams = self.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
self.__miningyield = 0
|
||||
else:
|
||||
cycleTime = cycleParams.averageTime
|
||||
self.__miningyield = volley / (cycleTime / 1000.0)
|
||||
else:
|
||||
self.__miningyield = 0
|
||||
else:
|
||||
@@ -409,42 +414,71 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
|
||||
return self.__miningyield
|
||||
|
||||
def getVolley(self, spoolOptions=None, targetResists=None, ignoreState=False):
|
||||
def isDealingDamage(self, ignoreState=False):
|
||||
volleyParams = self.getVolleyParameters(ignoreState=ignoreState)
|
||||
for volley in volleyParams.values():
|
||||
if volley.total > 0:
|
||||
return True
|
||||
return False
|
||||
|
||||
def getVolleyParameters(self, spoolOptions=None, targetResists=None, ignoreState=False):
|
||||
if self.isEmpty or (self.state < FittingModuleState.ACTIVE and not ignoreState):
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
return {0: DmgTypes(0, 0, 0, 0)}
|
||||
if self.__baseVolley is None:
|
||||
self.__baseVolley = {}
|
||||
dmgGetter = self.getModifiedChargeAttr if self.charge else self.getModifiedItemAttr
|
||||
dmgMult = self.getModifiedItemAttr("damageMultiplier", 1)
|
||||
self.__baseVolley = DmgTypes(
|
||||
em=(dmgGetter("emDamage", 0)) * dmgMult,
|
||||
thermal=(dmgGetter("thermalDamage", 0)) * dmgMult,
|
||||
kinetic=(dmgGetter("kineticDamage", 0)) * dmgMult,
|
||||
explosive=(dmgGetter("explosiveDamage", 0)) * dmgMult)
|
||||
dmgDelay = self.getModifiedItemAttr("damageDelayDuration", 0) or self.getModifiedItemAttr("doomsdayWarningDuration", 0)
|
||||
dmgDuration = self.getModifiedItemAttr("doomsdayDamageDuration", 0)
|
||||
dmgSubcycle = self.getModifiedItemAttr("doomsdayDamageCycleTime", 0)
|
||||
if dmgDuration != 0 and dmgSubcycle != 0:
|
||||
subcycles = math.floor(floatUnerr(dmgDuration / dmgSubcycle))
|
||||
else:
|
||||
subcycles = 1
|
||||
for i in range(subcycles):
|
||||
self.__baseVolley[dmgDelay + dmgSubcycle * i] = DmgTypes(
|
||||
em=(dmgGetter("emDamage", 0)) * dmgMult,
|
||||
thermal=(dmgGetter("thermalDamage", 0)) * dmgMult,
|
||||
kinetic=(dmgGetter("kineticDamage", 0)) * dmgMult,
|
||||
explosive=(dmgGetter("explosiveDamage", 0)) * dmgMult)
|
||||
spoolType, spoolAmount = resolveSpoolOptions(spoolOptions, self)
|
||||
spoolBoost = calculateSpoolup(
|
||||
self.getModifiedItemAttr("damageMultiplierBonusMax", 0),
|
||||
self.getModifiedItemAttr("damageMultiplierBonusPerCycle", 0),
|
||||
self.rawCycleTime / 1000, spoolType, spoolAmount)[0]
|
||||
spoolMultiplier = 1 + spoolBoost
|
||||
volley = DmgTypes(
|
||||
em=self.__baseVolley.em * spoolMultiplier * (1 - getattr(targetResists, "emAmount", 0)),
|
||||
thermal=self.__baseVolley.thermal * spoolMultiplier * (1 - getattr(targetResists, "thermalAmount", 0)),
|
||||
kinetic=self.__baseVolley.kinetic * spoolMultiplier * (1 - getattr(targetResists, "kineticAmount", 0)),
|
||||
explosive=self.__baseVolley.explosive * spoolMultiplier * (1 - getattr(targetResists, "explosiveAmount", 0)))
|
||||
return volley
|
||||
adjustedVolley = {}
|
||||
for volleyTime, volleyValue in self.__baseVolley.items():
|
||||
adjustedVolley[volleyTime] = DmgTypes(
|
||||
em=volleyValue.em * spoolMultiplier * (1 - getattr(targetResists, "emAmount", 0)),
|
||||
thermal=volleyValue.thermal * spoolMultiplier * (1 - getattr(targetResists, "thermalAmount", 0)),
|
||||
kinetic=volleyValue.kinetic * spoolMultiplier * (1 - getattr(targetResists, "kineticAmount", 0)),
|
||||
explosive=volleyValue.explosive * spoolMultiplier * (1 - getattr(targetResists, "explosiveAmount", 0)))
|
||||
return adjustedVolley
|
||||
|
||||
def getVolley(self, spoolOptions=None, targetResists=None, ignoreState=False):
|
||||
volleyParams = self.getVolleyParameters(spoolOptions=spoolOptions, targetResists=targetResists, ignoreState=ignoreState)
|
||||
if len(volleyParams) == 0:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
return volleyParams[min(volleyParams)]
|
||||
|
||||
def getDps(self, spoolOptions=None, targetResists=None, ignoreState=False):
|
||||
volley = self.getVolley(spoolOptions=spoolOptions, targetResists=targetResists, ignoreState=ignoreState)
|
||||
if not volley:
|
||||
return DmgTypes(0, 0, 0, 0)
|
||||
# Some weapons repeat multiple times in one cycle (bosonic doomsdays). Get the number of times it fires off
|
||||
volleysPerCycle = max(self.getModifiedItemAttr("doomsdayDamageDuration", 1) / self.getModifiedItemAttr("doomsdayDamageCycleTime", 1), 1)
|
||||
dpsFactor = volleysPerCycle / (self.cycleTime / 1000)
|
||||
dmgDuringCycle = DmgTypes(0, 0, 0, 0)
|
||||
cycleParams = self.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
return dmgDuringCycle
|
||||
volleyParams = self.getVolleyParameters(spoolOptions=spoolOptions, targetResists=targetResists, ignoreState=ignoreState)
|
||||
avgCycleTime = cycleParams.averageTime
|
||||
if len(volleyParams) == 0 or avgCycleTime == 0:
|
||||
return dmgDuringCycle
|
||||
for volleyValue in volleyParams.values():
|
||||
dmgDuringCycle += volleyValue
|
||||
dpsFactor = 1 / (avgCycleTime / 1000)
|
||||
dps = DmgTypes(
|
||||
em=volley.em * dpsFactor,
|
||||
thermal=volley.thermal * dpsFactor,
|
||||
kinetic=volley.kinetic * dpsFactor,
|
||||
explosive=volley.explosive * dpsFactor)
|
||||
em=dmgDuringCycle.em * dpsFactor,
|
||||
thermal=dmgDuringCycle.thermal * dpsFactor,
|
||||
kinetic=dmgDuringCycle.kinetic * dpsFactor,
|
||||
explosive=dmgDuringCycle.explosive * dpsFactor)
|
||||
return dps
|
||||
|
||||
def getRemoteReps(self, spoolOptions=None, ignoreState=False):
|
||||
@@ -474,7 +508,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
else:
|
||||
return None, 0
|
||||
if rrAmount:
|
||||
rrAmount *= 1 / (self.cycleTime / 1000)
|
||||
cycleParams = self.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
return None, 0
|
||||
rrAmount *= 1 / (cycleParams.averageTime / 1000)
|
||||
if module.item.group.name == "Ancillary Remote Armor Repairer" and module.charge:
|
||||
rrAmount *= module.getModifiedItemAttr("chargedArmorDamageMultiplier", 1)
|
||||
|
||||
@@ -819,49 +856,61 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
except:
|
||||
effect.handler(fit, self, context)
|
||||
|
||||
@property
|
||||
def cycleTime(self):
|
||||
def getCycleParameters(self, reloadOverride=None):
|
||||
"""Copied from new eos as well"""
|
||||
# Determine if we'll take into account reload time or not
|
||||
factorReload = self.owner.factorReload if self.forceReload is None else self.forceReload
|
||||
|
||||
numShots = self.numShots
|
||||
speed = self.rawCycleTime
|
||||
|
||||
if factorReload and self.charge:
|
||||
raw_reload_time = self.reloadTime
|
||||
if reloadOverride is not None:
|
||||
factorReload = reloadOverride
|
||||
else:
|
||||
raw_reload_time = 0.0
|
||||
factorReload = self.owner.factorReload if self.forceReload is None else self.forceReload
|
||||
|
||||
# Module can only fire one shot at a time, think bomb launchers or defender launchers
|
||||
if self.disallowRepeatingAction:
|
||||
if numShots > 0:
|
||||
"""
|
||||
The actual mechanics behind this is complex. Behavior will be (for 3 ammo):
|
||||
fire, reactivation delay, fire, reactivation delay, fire, max(reactivation delay, reload)
|
||||
so your effective reload time depends on where you are at in the cycle.
|
||||
cycles_until_reload = self.numShots
|
||||
if cycles_until_reload == 0:
|
||||
cycles_until_reload = math.inf
|
||||
|
||||
We can't do that, so instead we'll average it out.
|
||||
|
||||
Currently would apply to bomb launchers and defender missiles
|
||||
"""
|
||||
effective_reload_time = ((self.reactivationDelay * (numShots - 1)) + max(raw_reload_time, self.reactivationDelay, 0))
|
||||
else:
|
||||
"""
|
||||
Applies to MJD/MJFG
|
||||
"""
|
||||
effective_reload_time = max(raw_reload_time, self.reactivationDelay, 0)
|
||||
speed = speed + effective_reload_time
|
||||
active_time = self.rawCycleTime
|
||||
if active_time == 0:
|
||||
return None
|
||||
forced_inactive_time = self.reactivationDelay
|
||||
reload_time = self.reloadTime
|
||||
# Effects which cannot be reloaded have the same processing whether
|
||||
# caller wants to take reload time into account or not
|
||||
if reload_time is None and cycles_until_reload < math.inf:
|
||||
final_cycles = 1
|
||||
early_cycles = cycles_until_reload - final_cycles
|
||||
# Single cycle until effect cannot run anymore
|
||||
if early_cycles == 0:
|
||||
return CycleInfo(active_time, 0, 1)
|
||||
# Multiple cycles with the same parameters
|
||||
if forced_inactive_time == 0:
|
||||
return CycleInfo(active_time, 0, cycles_until_reload)
|
||||
# Multiple cycles with different parameters
|
||||
return CycleSequence((
|
||||
CycleInfo(active_time, forced_inactive_time, early_cycles),
|
||||
CycleInfo(active_time, 0, final_cycles)
|
||||
), 1)
|
||||
# Module cycles the same way all the time in 3 cases:
|
||||
# 1) caller doesn't want to take into account reload time
|
||||
# 2) effect does not have to reload anything to keep running
|
||||
# 3) effect has enough time to reload during inactivity periods
|
||||
if (
|
||||
not factorReload or
|
||||
cycles_until_reload == math.inf or
|
||||
forced_inactive_time >= reload_time
|
||||
):
|
||||
return CycleInfo(active_time, forced_inactive_time, math.inf)
|
||||
# We've got to take reload into consideration
|
||||
else:
|
||||
"""
|
||||
Currently no other modules would have a reactivation delay, so for sanities sake don't try and account for it.
|
||||
Okay, technically cloaks do, but they also have 0 cycle time and cap usage so why do you care?
|
||||
"""
|
||||
effective_reload_time = raw_reload_time
|
||||
|
||||
if numShots > 0 and self.charge:
|
||||
speed = (speed * numShots + effective_reload_time) / numShots
|
||||
|
||||
return speed
|
||||
final_cycles = 1
|
||||
early_cycles = cycles_until_reload - final_cycles
|
||||
# If effect has to reload after each its cycle, then its parameters
|
||||
# are the same all the time
|
||||
if early_cycles == 0:
|
||||
return CycleInfo(active_time, reload_time, math.inf)
|
||||
return CycleSequence((
|
||||
CycleInfo(active_time, forced_inactive_time, early_cycles),
|
||||
CycleInfo(active_time, reload_time, final_cycles)
|
||||
), math.inf)
|
||||
|
||||
@property
|
||||
def rawCycleTime(self):
|
||||
@@ -887,7 +936,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
|
||||
def capUse(self):
|
||||
capNeed = self.getModifiedItemAttr("capacitorNeed")
|
||||
if capNeed and self.state >= FittingModuleState.ACTIVE:
|
||||
cycleTime = self.cycleTime
|
||||
cycleParams = self.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
return 0
|
||||
cycleTime = cycleParams.averageTime
|
||||
if cycleTime > 0:
|
||||
capUsed = capNeed / (cycleTime / 1000.0)
|
||||
return capUsed
|
||||
|
||||
68
eos/utils/cycles.py
Normal file
68
eos/utils/cycles.py
Normal file
@@ -0,0 +1,68 @@
|
||||
# Borrowed from new eos
|
||||
|
||||
|
||||
from utils.repr import makeReprStr
|
||||
|
||||
|
||||
class CycleInfo:
|
||||
|
||||
def __init__(self, activeTime, inactiveTime, quantity):
|
||||
self.activeTime = activeTime
|
||||
self.inactiveTime = inactiveTime
|
||||
self.quantity = quantity
|
||||
|
||||
@property
|
||||
def averageTime(self):
|
||||
return self.activeTime + self.inactiveTime
|
||||
|
||||
def iterCycles(self):
|
||||
i = 0
|
||||
while i < self.quantity:
|
||||
yield self.activeTime, self.inactiveTime
|
||||
i += 1
|
||||
|
||||
def _getCycleQuantity(self):
|
||||
return self.quantity
|
||||
|
||||
def _getTime(self):
|
||||
return (self.activeTime + self.inactiveTime) * self.quantity
|
||||
|
||||
def __repr__(self):
|
||||
spec = ['activeTime', 'inactiveTime', 'quantity']
|
||||
return makeReprStr(self, spec)
|
||||
|
||||
|
||||
class CycleSequence:
|
||||
|
||||
def __init__(self, sequence, quantity):
|
||||
self.sequence = sequence
|
||||
self.quantity = quantity
|
||||
|
||||
@property
|
||||
def averageTime(self):
|
||||
"""Get average time between cycles."""
|
||||
return self._getTime() / self._getCycleQuantity()
|
||||
|
||||
def iterCycles(self):
|
||||
i = 0
|
||||
while i < self.quantity:
|
||||
for cycleInfo in self.sequence:
|
||||
for cycleTime, inactiveTime in cycleInfo.iterCycles():
|
||||
yield cycleTime, inactiveTime
|
||||
i += 1
|
||||
|
||||
def _getCycleQuantity(self):
|
||||
quantity = 0
|
||||
for item in self.sequence:
|
||||
quantity += item._getCycleQuantity()
|
||||
return quantity
|
||||
|
||||
def _getTime(self):
|
||||
time = 0
|
||||
for item in self.sequence:
|
||||
time += item._getTime()
|
||||
return time
|
||||
|
||||
def __repr__(self):
|
||||
spec = ['sequence', 'quantity']
|
||||
return makeReprStr(self, spec)
|
||||
@@ -25,7 +25,6 @@ import gui.display as d
|
||||
import gui.fitCommands as cmd
|
||||
import gui.globalEvents as GE
|
||||
from gui.builtinContextMenus.commandFitAdd import AddCommandFit
|
||||
from gui.builtinShipBrowser.events import EVT_FIT_REMOVED
|
||||
from gui.builtinViewColumns.state import State
|
||||
from gui.contextMenu import ContextMenu
|
||||
from gui.utils.staticHelpers import DragDropHelper
|
||||
@@ -71,7 +70,7 @@ class CommandView(d.Display):
|
||||
self.lastFitId = None
|
||||
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, AddCommandFit.fitChanged)
|
||||
self.mainFrame.Bind(EVT_FIT_REMOVED, AddCommandFit.populateFits)
|
||||
self.mainFrame.Bind(GE.FIT_REMOVED, self.OnFitRemoved)
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
|
||||
self.Bind(wx.EVT_LEFT_DOWN, self.click)
|
||||
self.Bind(wx.EVT_LEFT_DCLICK, self.onLeftDoubleClick)
|
||||
@@ -83,6 +82,13 @@ class CommandView(d.Display):
|
||||
|
||||
self.SetDropTarget(CommandViewDrop(self.handleListDrag))
|
||||
|
||||
def OnFitRemoved(self, event):
|
||||
event.Skip()
|
||||
AddCommandFit.populateFits(event)
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
fit = Fit.getInstance().getFit(fitID)
|
||||
self.refreshContents(fit)
|
||||
|
||||
@staticmethod
|
||||
def handleListDrag(x, y, data):
|
||||
"""
|
||||
@@ -132,12 +138,6 @@ class CommandView(d.Display):
|
||||
event.Skip()
|
||||
return
|
||||
|
||||
stuff = []
|
||||
if fit is not None:
|
||||
self.fits = fit.commandFits[:]
|
||||
self.fits.sort(key=self.fitSort)
|
||||
stuff.extend(self.fits)
|
||||
|
||||
if event.fitID != self.lastFitId:
|
||||
self.lastFitId = event.fitID
|
||||
|
||||
@@ -148,13 +148,20 @@ class CommandView(d.Display):
|
||||
|
||||
self.unselectAll()
|
||||
|
||||
if not stuff:
|
||||
stuff = [DummyEntry("Drag a fit to this area")]
|
||||
|
||||
self.update(stuff)
|
||||
self.refreshContents(fit)
|
||||
|
||||
event.Skip()
|
||||
|
||||
def refreshContents(self, fit):
|
||||
stuff = []
|
||||
if fit is not None:
|
||||
self.fits = fit.commandFits[:]
|
||||
self.fits.sort(key=self.fitSort)
|
||||
stuff.extend(self.fits)
|
||||
if not stuff:
|
||||
stuff = [DummyEntry("Drag a fit to this area")]
|
||||
self.update(stuff)
|
||||
|
||||
def click(self, event):
|
||||
mainRow, _ = self.HitTest(event.Position)
|
||||
if mainRow != -1:
|
||||
|
||||
@@ -82,6 +82,7 @@ class ProjectedView(d.Display):
|
||||
self.lastFitId = None
|
||||
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
|
||||
self.mainFrame.Bind(GE.FIT_REMOVED, self.OnFitRemoved)
|
||||
self.Bind(wx.EVT_LEFT_DOWN, self.click)
|
||||
self.Bind(wx.EVT_RIGHT_DOWN, self.click)
|
||||
self.Bind(wx.EVT_LEFT_DCLICK, self.onLeftDoubleClick)
|
||||
@@ -93,6 +94,12 @@ class ProjectedView(d.Display):
|
||||
|
||||
self.SetDropTarget(ProjectedViewDrop(self.handleListDrag))
|
||||
|
||||
def OnFitRemoved(self, event):
|
||||
event.Skip()
|
||||
fitID = self.mainFrame.getActiveFit()
|
||||
fit = Fit.getInstance().getFit(fitID)
|
||||
self.refreshContents(fit)
|
||||
|
||||
def handleListDrag(self, x, y, data):
|
||||
"""
|
||||
Handles dragging of items from various pyfa displays which support it
|
||||
@@ -174,6 +181,23 @@ class ProjectedView(d.Display):
|
||||
event.Skip()
|
||||
return
|
||||
|
||||
|
||||
|
||||
if event.fitID != self.lastFitId:
|
||||
self.lastFitId = event.fitID
|
||||
|
||||
item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)
|
||||
|
||||
if item != -1:
|
||||
self.EnsureVisible(item)
|
||||
|
||||
self.unselectAll()
|
||||
|
||||
self.refreshContents(fit)
|
||||
|
||||
event.Skip()
|
||||
|
||||
def refreshContents(self, fit):
|
||||
stuff = []
|
||||
if fit is not None:
|
||||
self.originalFits = fit.projectedFits
|
||||
@@ -194,24 +218,10 @@ class ProjectedView(d.Display):
|
||||
stuff.extend(self.modules)
|
||||
stuff.extend(self.drones)
|
||||
stuff.extend(self.fighters)
|
||||
|
||||
if event.fitID != self.lastFitId:
|
||||
self.lastFitId = event.fitID
|
||||
|
||||
item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)
|
||||
|
||||
if item != -1:
|
||||
self.EnsureVisible(item)
|
||||
|
||||
self.unselectAll()
|
||||
|
||||
if not stuff:
|
||||
stuff = [DummyEntry('Drag an item or fit, or use right-click menu for wormhole effects')]
|
||||
|
||||
self.update(stuff)
|
||||
|
||||
event.Skip()
|
||||
|
||||
def get(self, row):
|
||||
if row == -1:
|
||||
return None
|
||||
|
||||
@@ -83,8 +83,9 @@ class ChangeItemToVariation(ContextMenuCombined):
|
||||
else:
|
||||
bindmenu = m
|
||||
|
||||
# Do not show abyssal items
|
||||
items = list(i for i in self.mainVariations if i.metaGroup is None or i.metaGroup.ID != 15)
|
||||
# Sort items by metalevel, and group within that metalevel
|
||||
items = list(self.mainVariations)
|
||||
# Sort all items by name first
|
||||
items.sort(key=lambda x: x.name)
|
||||
# Do not do any extra sorting for implants
|
||||
|
||||
@@ -230,7 +230,7 @@ class ChangeModuleAmmo(ContextMenuCombined):
|
||||
fit = sFit.getFit(fitID)
|
||||
mstate = wx.GetMouseState()
|
||||
# Switch in selection or all modules, depending on modifier key state and settings
|
||||
switchAll = sFit.serviceFittingOptions['ammoChangeAll'] is not mstate.GetModifiers() in (wx.MOD_ALT, wx.MOD_CONTROL)
|
||||
switchAll = sFit.serviceFittingOptions['ammoChangeAll'] is not (mstate.GetModifiers() in (wx.MOD_ALT, wx.MOD_CONTROL))
|
||||
if switchAll:
|
||||
if self.srcContext == 'fittingModule':
|
||||
command = cmd.GuiChangeLocalModuleChargesCommand
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
__all__ = [
|
||||
"fitDpsRange",
|
||||
"fitDpsTime",
|
||||
"fitDmgTime"
|
||||
]
|
||||
# noinspection PyUnresolvedReferences
|
||||
from gui.builtinGraphs import ( # noqa: E402,F401
|
||||
fitDpsVsRange,
|
||||
fitDmgVsTime,
|
||||
fitShieldRegenVsShieldPerc,
|
||||
fitShieldAmountVsTime,
|
||||
fitCapRegenVsCapPerc,
|
||||
fitCapAmountVsTime,
|
||||
fitMobilityVsTime,
|
||||
fitWarpTimeVsDistance
|
||||
)
|
||||
|
||||
44
gui/builtinGraphs/fitCapAmountVsTime.py
Normal file
44
gui/builtinGraphs/fitCapAmountVsTime.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from eos.graph.fitCapAmountVsTime import FitCapAmountVsTimeGraph as EosGraph
|
||||
from gui.graph import Graph, XDef, YDef
|
||||
|
||||
|
||||
class FitCapAmountVsTimeGraph(Graph):
|
||||
|
||||
name = 'Cap Amount vs Time'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.eosGraph = EosGraph()
|
||||
|
||||
@property
|
||||
def xDef(self):
|
||||
return XDef(inputDefault='0-300', inputLabel='Time (seconds)', inputIconID=1392, axisLabel='Time, s')
|
||||
|
||||
@property
|
||||
def yDefs(self):
|
||||
return OrderedDict([('capAmount', YDef(switchLabel='Cap amount', axisLabel='Cap amount, GJ', eosGraph='eosGraph'))])
|
||||
|
||||
|
||||
FitCapAmountVsTimeGraph.register()
|
||||
44
gui/builtinGraphs/fitCapRegenVsCapPerc.py
Normal file
44
gui/builtinGraphs/fitCapRegenVsCapPerc.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from eos.graph.fitCapRegenVsCapPerc import FitCapRegenVsCapPercGraph as EosGraph
|
||||
from gui.graph import Graph, XDef, YDef
|
||||
|
||||
|
||||
class FitCapRegenVsCapPercGraph(Graph):
|
||||
|
||||
name = 'Cap Regen vs Cap Amount'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.eosGraph = EosGraph()
|
||||
|
||||
@property
|
||||
def xDef(self):
|
||||
return XDef(inputDefault='0-100', inputLabel='Cap amount (percent)', inputIconID=1668, axisLabel='Cap amount, %')
|
||||
|
||||
@property
|
||||
def yDefs(self):
|
||||
return OrderedDict([('capRegen', YDef(switchLabel='Cap regen', axisLabel='Cap regen, GJ/s', eosGraph='eosGraph'))])
|
||||
|
||||
|
||||
FitCapRegenVsCapPercGraph.register()
|
||||
@@ -1,82 +0,0 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
import gui.mainFrame
|
||||
from eos.graph import Data
|
||||
from eos.graph.fitDmgTime import FitDmgTimeGraph as EosFitDmgTimeGraph
|
||||
from gui.bitmap_loader import BitmapLoader
|
||||
from gui.graph import Graph
|
||||
from service.attribute import Attribute
|
||||
|
||||
|
||||
class FitDmgTimeGraph(Graph):
|
||||
|
||||
propertyLabelMap = {"time": "Time (seconds)"}
|
||||
|
||||
defaults = EosFitDmgTimeGraph.defaults.copy()
|
||||
|
||||
def __init__(self):
|
||||
Graph.__init__(self)
|
||||
self.defaults["time"] = "0-300"
|
||||
self.name = "Damage over time"
|
||||
self.fitDmgTime = None
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def getFields(self):
|
||||
return self.defaults
|
||||
|
||||
def getLabels(self):
|
||||
return self.propertyLabelMap
|
||||
|
||||
def getIcons(self):
|
||||
iconFile = Attribute.getInstance().getAttributeInfo('duration').iconID
|
||||
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
|
||||
return {"time": bitmap}
|
||||
|
||||
def getPoints(self, fit, fields):
|
||||
fitDmgTime = getattr(self, "fitDmgTime", None)
|
||||
if fitDmgTime is None or fitDmgTime.fit != fit:
|
||||
fitDmgTime = self.fitDmgTime = EosFitDmgTimeGraph(fit)
|
||||
|
||||
fitDmgTime.clearData()
|
||||
variable = None
|
||||
for fieldName, value in fields.items():
|
||||
d = Data(fieldName, value)
|
||||
if not d.isConstant():
|
||||
if variable is None:
|
||||
variable = fieldName
|
||||
else:
|
||||
# We can't handle more then one variable atm, OOPS FUCK OUT
|
||||
return False, "Can only handle 1 variable"
|
||||
|
||||
fitDmgTime.setData(d)
|
||||
|
||||
if variable is None:
|
||||
return False, "No variable"
|
||||
|
||||
x = []
|
||||
y = []
|
||||
for point, val in fitDmgTime.getIterator():
|
||||
x.append(point[variable])
|
||||
y.append(val)
|
||||
|
||||
return x, y
|
||||
|
||||
|
||||
FitDmgTimeGraph.register()
|
||||
48
gui/builtinGraphs/fitDmgVsTime.py
Normal file
48
gui/builtinGraphs/fitDmgVsTime.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from eos.graph.fitDmgVsTime import FitDmgVsTimeGraph as EosGraphDmg
|
||||
from eos.graph.fitDpsVsTime import FitDpsVsTimeGraph as EosGraphDps
|
||||
from gui.graph import Graph, XDef, YDef
|
||||
|
||||
|
||||
class FitDmgVsTimeGraph(Graph):
|
||||
|
||||
name = 'Damage vs Time'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.eosGraphDmg = EosGraphDmg()
|
||||
self.eosGraphDps = EosGraphDps()
|
||||
|
||||
@property
|
||||
def xDef(self):
|
||||
return XDef(inputDefault='0-80', inputLabel='Time (seconds)', inputIconID=1392, axisLabel='Time, s')
|
||||
|
||||
@property
|
||||
def yDefs(self):
|
||||
return OrderedDict([
|
||||
('damage', YDef(switchLabel='Damage inflicted', axisLabel='Damage', eosGraph='eosGraphDmg')),
|
||||
('dps', YDef(switchLabel='DPS', axisLabel='DPS', eosGraph='eosGraphDps'))])
|
||||
|
||||
|
||||
FitDmgVsTimeGraph.register()
|
||||
@@ -1,96 +0,0 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
import gui.mainFrame
|
||||
from eos.graph import Data
|
||||
from eos.graph.fitDpsRange import FitDpsRangeGraph as EosFitDpsRangeGraph
|
||||
from gui.bitmap_loader import BitmapLoader
|
||||
from gui.graph import Graph
|
||||
from service.attribute import Attribute
|
||||
|
||||
|
||||
class FitDpsRangeGraph(Graph):
|
||||
|
||||
propertyAttributeMap = {"angle": "maxVelocity",
|
||||
"distance": "maxRange",
|
||||
"signatureRadius": "signatureRadius",
|
||||
"velocity": "maxVelocity"}
|
||||
|
||||
propertyLabelMap = {"angle": "Target Angle (degrees)",
|
||||
"distance": "Distance to Target (km)",
|
||||
"signatureRadius": "Target Signature Radius (m)",
|
||||
"velocity": "Target Velocity (m/s)"}
|
||||
|
||||
defaults = EosFitDpsRangeGraph.defaults.copy()
|
||||
|
||||
def __init__(self):
|
||||
Graph.__init__(self)
|
||||
self.defaults["distance"] = "0-100"
|
||||
self.name = "DPS over range"
|
||||
self.fitDpsRange = None
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def getFields(self):
|
||||
return self.defaults
|
||||
|
||||
def getLabels(self):
|
||||
return self.propertyLabelMap
|
||||
|
||||
def getIcons(self):
|
||||
icons = {}
|
||||
sAttr = Attribute.getInstance()
|
||||
for key, attrName in self.propertyAttributeMap.items():
|
||||
iconFile = sAttr.getAttributeInfo(attrName).iconID
|
||||
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
|
||||
if bitmap:
|
||||
icons[key] = bitmap
|
||||
|
||||
return icons
|
||||
|
||||
def getPoints(self, fit, fields):
|
||||
fitDpsRange = getattr(self, "fitDpsRange", None)
|
||||
if fitDpsRange is None or fitDpsRange.fit != fit:
|
||||
fitDpsRange = self.fitDpsRange = EosFitDpsRangeGraph(fit)
|
||||
|
||||
fitDpsRange.clearData()
|
||||
variable = None
|
||||
for fieldName, value in fields.items():
|
||||
d = Data(fieldName, value)
|
||||
if not d.isConstant():
|
||||
if variable is None:
|
||||
variable = fieldName
|
||||
else:
|
||||
# We can't handle more then one variable atm, OOPS FUCK OUT
|
||||
return False, "Can only handle 1 variable"
|
||||
|
||||
fitDpsRange.setData(d)
|
||||
|
||||
if variable is None:
|
||||
return False, "No variable"
|
||||
|
||||
x = []
|
||||
y = []
|
||||
for point, val in fitDpsRange.getIterator():
|
||||
x.append(point[variable])
|
||||
y.append(val)
|
||||
|
||||
return x, y
|
||||
|
||||
|
||||
FitDpsRangeGraph.register()
|
||||
@@ -1,82 +0,0 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
import gui.mainFrame
|
||||
from eos.graph import Data
|
||||
from eos.graph.fitDpsTime import FitDpsTimeGraph as EosFitDpsTimeGraph
|
||||
from gui.bitmap_loader import BitmapLoader
|
||||
from gui.graph import Graph
|
||||
from service.attribute import Attribute
|
||||
|
||||
|
||||
class FitDpsTimeGraph(Graph):
|
||||
|
||||
propertyLabelMap = {"time": "Time (seconds)"}
|
||||
|
||||
defaults = EosFitDpsTimeGraph.defaults.copy()
|
||||
|
||||
def __init__(self):
|
||||
Graph.__init__(self)
|
||||
self.defaults["time"] = "0-300"
|
||||
self.name = "DPS over time"
|
||||
self.fitDpsTime = None
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
def getFields(self):
|
||||
return self.defaults
|
||||
|
||||
def getLabels(self):
|
||||
return self.propertyLabelMap
|
||||
|
||||
def getIcons(self):
|
||||
iconFile = Attribute.getInstance().getAttributeInfo('duration').iconID
|
||||
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
|
||||
return {"time": bitmap}
|
||||
|
||||
def getPoints(self, fit, fields):
|
||||
fitDpsTime = getattr(self, "fitDpsTime", None)
|
||||
if fitDpsTime is None or fitDpsTime.fit != fit:
|
||||
fitDpsTime = self.fitDpsTime = EosFitDpsTimeGraph(fit)
|
||||
|
||||
fitDpsTime.clearData()
|
||||
variable = None
|
||||
for fieldName, value in fields.items():
|
||||
d = Data(fieldName, value)
|
||||
if not d.isConstant():
|
||||
if variable is None:
|
||||
variable = fieldName
|
||||
else:
|
||||
# We can't handle more then one variable atm, OOPS FUCK OUT
|
||||
return False, "Can only handle 1 variable"
|
||||
|
||||
fitDpsTime.setData(d)
|
||||
|
||||
if variable is None:
|
||||
return False, "No variable"
|
||||
|
||||
x = []
|
||||
y = []
|
||||
for point, val in fitDpsTime.getIterator():
|
||||
x.append(point[variable])
|
||||
y.append(val)
|
||||
|
||||
return x, y
|
||||
|
||||
|
||||
FitDpsTimeGraph.register()
|
||||
59
gui/builtinGraphs/fitDpsVsRange.py
Normal file
59
gui/builtinGraphs/fitDpsVsRange.py
Normal file
@@ -0,0 +1,59 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from eos.graph.fitDpsVsRange import FitDpsVsRangeGraph as EosGraph
|
||||
from gui.graph import Graph, XDef, YDef, ExtraInput
|
||||
|
||||
|
||||
class FitDpsVsRangeGraph(Graph):
|
||||
|
||||
name = 'DPS vs Range'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.eosGraph = EosGraph()
|
||||
|
||||
@property
|
||||
def xDef(self):
|
||||
return XDef(inputDefault='0-100', inputLabel='Distance to target (km)', inputIconID=1391, axisLabel='Distance to target, km')
|
||||
|
||||
@property
|
||||
def yDefs(self):
|
||||
return OrderedDict([('dps', YDef(switchLabel='DPS', axisLabel='DPS', eosGraph='eosGraph'))])
|
||||
|
||||
@property
|
||||
def extraInputs(self):
|
||||
return OrderedDict([
|
||||
('speed', ExtraInput(inputDefault=0, inputLabel='Target speed (m/s)', inputIconID=1389)),
|
||||
('signatureRadius', ExtraInput(inputDefault=None, inputLabel='Target signature radius (m)', inputIconID=1390)),
|
||||
('angle', ExtraInput(inputDefault=0, inputLabel='Target angle (degrees)', inputIconID=1389))])
|
||||
|
||||
@property
|
||||
def hasTargets(self):
|
||||
return True
|
||||
|
||||
@property
|
||||
def hasVectors(self):
|
||||
return True
|
||||
|
||||
|
||||
FitDpsVsRangeGraph.register()
|
||||
48
gui/builtinGraphs/fitMobilityVsTime.py
Normal file
48
gui/builtinGraphs/fitMobilityVsTime.py
Normal file
@@ -0,0 +1,48 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from eos.graph.fitDistanceVsTime import FitDistanceVsTimeGraph as EosGraphDistance
|
||||
from eos.graph.fitSpeedVsTime import FitSpeedVsTimeGraph as EosGraphSpeed
|
||||
from gui.graph import Graph, XDef, YDef
|
||||
|
||||
|
||||
class FitMobilityVsTimeGraph(Graph):
|
||||
|
||||
name = 'Mobility vs Time'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.eosGraphSpeed = EosGraphSpeed()
|
||||
self.eosGraphDistance = EosGraphDistance()
|
||||
|
||||
@property
|
||||
def xDef(self):
|
||||
return XDef(inputDefault='0-80', inputLabel='Time (seconds)', inputIconID=1392, axisLabel='Time, s')
|
||||
|
||||
@property
|
||||
def yDefs(self):
|
||||
return OrderedDict([
|
||||
('speed', YDef(switchLabel='Speed', axisLabel='Speed, m/s', eosGraph='eosGraphSpeed')),
|
||||
('distance', YDef(switchLabel='Distance', axisLabel='Distance, m', eosGraph='eosGraphDistance'))])
|
||||
|
||||
|
||||
FitMobilityVsTimeGraph.register()
|
||||
50
gui/builtinGraphs/fitShieldAmountVsTime.py
Normal file
50
gui/builtinGraphs/fitShieldAmountVsTime.py
Normal file
@@ -0,0 +1,50 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
import gui.mainFrame
|
||||
from eos.graph.fitShieldAmountVsTime import FitShieldAmountVsTimeGraph as EosGraph
|
||||
from gui.graph import Graph, XDef, YDef
|
||||
|
||||
|
||||
class FitShieldAmountVsTimeGraph(Graph):
|
||||
|
||||
name = 'Shield Amount vs Time'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.eosGraph = EosGraph()
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
@property
|
||||
def xDef(self):
|
||||
return XDef(inputDefault='0-300', inputLabel='Time (seconds)', inputIconID=1392, axisLabel='Time, s')
|
||||
|
||||
@property
|
||||
def yDefs(self):
|
||||
axisLabel = 'Shield amount, {}'.format('EHP' if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective else 'HP')
|
||||
return OrderedDict([('shieldAmount', YDef(switchLabel='Shield amount', axisLabel=axisLabel, eosGraph='eosGraph'))])
|
||||
|
||||
def redrawOnEffectiveChange(self):
|
||||
return True
|
||||
|
||||
|
||||
FitShieldAmountVsTimeGraph.register()
|
||||
51
gui/builtinGraphs/fitShieldRegenVsShieldPerc.py
Normal file
51
gui/builtinGraphs/fitShieldRegenVsShieldPerc.py
Normal file
@@ -0,0 +1,51 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
import gui.mainFrame
|
||||
from eos.graph.fitShieldRegenVsShieldPerc import FitShieldRegenVsShieldPercGraph as EosGraph
|
||||
from gui.graph import Graph, XDef, YDef
|
||||
|
||||
|
||||
class FitShieldRegenVsShieldPercGraph(Graph):
|
||||
|
||||
name = 'Shield Regen vs Shield Amount'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.eosGraph = EosGraph()
|
||||
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
|
||||
|
||||
@property
|
||||
def xDef(self):
|
||||
return XDef(inputDefault='0-100', inputLabel='Shield amount (percent)', inputIconID=1384, axisLabel='Shield amount, %')
|
||||
|
||||
@property
|
||||
def yDefs(self):
|
||||
axisLabel = 'Shield regen, {}/s'.format('EHP' if self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective else 'HP')
|
||||
return OrderedDict([('shieldRegen', YDef(switchLabel='Shield regen', axisLabel=axisLabel, eosGraph='eosGraph'))])
|
||||
|
||||
@property
|
||||
def redrawOnEffectiveChange(self):
|
||||
return True
|
||||
|
||||
|
||||
FitShieldRegenVsShieldPercGraph.register()
|
||||
44
gui/builtinGraphs/fitWarpTimeVsDistance.py
Normal file
44
gui/builtinGraphs/fitWarpTimeVsDistance.py
Normal file
@@ -0,0 +1,44 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2010 Diego Duclos
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
from eos.graph.fitWarpTimeVsDistance import FitWarpTimeVsDistanceGraph as EosGraph
|
||||
from gui.graph import Graph, XDef, YDef
|
||||
|
||||
|
||||
class FitWarpTimeVsDistanceGraph(Graph):
|
||||
|
||||
name = 'Warp Time vs Distance'
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
self.eosGraph = EosGraph()
|
||||
|
||||
@property
|
||||
def xDef(self):
|
||||
return XDef(inputDefault='0-50', inputLabel='Distance (AU)', inputIconID=1391, axisLabel='Warp distance, AU')
|
||||
|
||||
@property
|
||||
def yDefs(self):
|
||||
return OrderedDict([('time', YDef(switchLabel='Warp time', axisLabel='Warp time, s', eosGraph='eosGraph'))])
|
||||
|
||||
|
||||
FitWarpTimeVsDistanceGraph.register()
|
||||
@@ -61,7 +61,7 @@ class ItemView(Display):
|
||||
def delaySearch(self, evt):
|
||||
sFit = Fit.getInstance()
|
||||
self.searchTimer.Stop()
|
||||
self.searchTimer.Start(sFit.serviceFittingOptions["marketSearchDelay"], True) # 150ms
|
||||
self.searchTimer.Start(sFit.serviceFittingOptions["marketSearchDelay"], True)
|
||||
|
||||
def startDrag(self, event):
|
||||
row = self.GetFirstSelected()
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
import wx.lib.newevent
|
||||
|
||||
FitRenamed, EVT_FIT_RENAMED = wx.lib.newevent.NewEvent()
|
||||
FitSelected, EVT_FIT_SELECTED = wx.lib.newevent.NewEvent()
|
||||
FitRemoved, EVT_FIT_REMOVED = wx.lib.newevent.NewEvent()
|
||||
FitSelected, EVT_FIT_SELECTED = wx.lib.newevent.NewEvent()\
|
||||
|
||||
BoosterListUpdated, BOOSTER_LIST_UPDATED = wx.lib.newevent.NewEvent()
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import config
|
||||
import gui.builtinShipBrowser.sfBrowserItem as SFItem
|
||||
import gui.fitCommands as cmd
|
||||
import gui.mainFrame
|
||||
import gui.globalEvents as GE
|
||||
import gui.utils.color as colorUtils
|
||||
import gui.utils.draw as drawUtils
|
||||
import gui.utils.fonts as fonts
|
||||
@@ -17,7 +18,7 @@ from gui.bitmap_loader import BitmapLoader
|
||||
from gui.builtinShipBrowser.events import EVT_FIT_RENAMED
|
||||
from gui.builtinShipBrowser.pfBitmapFrame import PFBitmapFrame
|
||||
from service.fit import Fit
|
||||
from .events import BoosterListUpdated, FitRemoved, FitSelected, ImportSelected, SearchSelected, Stage3Selected
|
||||
from .events import BoosterListUpdated, FitSelected, ImportSelected, SearchSelected, Stage3Selected
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
@@ -291,7 +292,9 @@ class FitItem(SFItem.SFBrowserItem):
|
||||
event.Skip()
|
||||
|
||||
def editCheckEsc(self, event):
|
||||
if event.GetKeyCode() == wx.WXK_ESCAPE:
|
||||
keycode = event.GetKeyCode()
|
||||
mstate = wx.GetMouseState()
|
||||
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
|
||||
self.RestoreEditButton()
|
||||
else:
|
||||
event.Skip()
|
||||
@@ -377,9 +380,8 @@ class FitItem(SFItem.SFBrowserItem):
|
||||
break
|
||||
|
||||
sFit.deleteFit(self.fitID)
|
||||
|
||||
# Notify other areas that a fit has been deleted
|
||||
wx.PostEvent(self.mainFrame, FitRemoved(fitID=self.fitID))
|
||||
wx.PostEvent(self.mainFrame, GE.FitRemoved(fitID=self.fitID))
|
||||
|
||||
# todo: would a simple RefreshList() work here instead of posting that a stage has been selected?
|
||||
if self.shipBrowser.GetActiveStage() == 5:
|
||||
|
||||
@@ -105,7 +105,9 @@ class NavigationPanel(SFItem.SFBrowserItem):
|
||||
self.BrowserSearchBox.Show(False)
|
||||
|
||||
def OnBrowserSearchBoxKeyPress(self, event):
|
||||
if event.GetKeyCode() == wx.WXK_ESCAPE:
|
||||
keycode = event.GetKeyCode()
|
||||
mstate = wx.GetMouseState()
|
||||
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
|
||||
self.BrowserSearchBox.Show(False)
|
||||
elif event.RawControlDown() and event.GetKeyCode() == wx.WXK_BACK:
|
||||
HandleCtrlBackspace(self.BrowserSearchBox)
|
||||
|
||||
@@ -149,7 +149,7 @@ class PFListPane(wx.ScrolledWindow):
|
||||
self._wList[i].SetSize((cwidth, iheight))
|
||||
if doRefresh is True:
|
||||
self._wList[i].Refresh()
|
||||
self.itemsHeight = max(self.itemsHeight, iheight - 1)
|
||||
self.itemsHeight = iheight
|
||||
|
||||
# This is needed as under GTK wx does not emit scroll up/scroll down
|
||||
# events, see issue #1909 for more info
|
||||
|
||||
@@ -175,7 +175,9 @@ class ShipItem(SFItem.SFBrowserItem):
|
||||
self.Refresh()
|
||||
|
||||
def editCheckEsc(self, event):
|
||||
if event.GetKeyCode() == wx.WXK_ESCAPE:
|
||||
keycode = event.GetKeyCode()
|
||||
mstate = wx.GetMouseState()
|
||||
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
|
||||
self.tcFitName.Show(False)
|
||||
else:
|
||||
event.Skip()
|
||||
|
||||
@@ -114,10 +114,14 @@ class CapacitorViewFull(StatsView):
|
||||
("label%sCapacitorRecharge", lambda: fit.capRecharge, 3, 0, 0),
|
||||
("label%sCapacitorDischarge", lambda: fit.capUsed, 3, 0, 0),
|
||||
)
|
||||
if fit:
|
||||
if fit is not None:
|
||||
neut_resist = fit.ship.getModifiedItemAttr("energyWarfareResistance", 0)
|
||||
cap_recharge = fit.capRecharge
|
||||
cap_use = fit.capUsed
|
||||
else:
|
||||
neut_resist = 0
|
||||
cap_recharge = 0
|
||||
cap_use = 0
|
||||
|
||||
panel = "Full"
|
||||
for labelName, value, prec, lowest, highest in stats:
|
||||
@@ -131,10 +135,11 @@ class CapacitorViewFull(StatsView):
|
||||
label.SetLabel(formatAmount(value, prec, lowest, highest))
|
||||
label.SetToolTip(wx.ToolTip("%.1f" % value))
|
||||
|
||||
if labelName == "label%sCapacitorDischarge":
|
||||
if neut_resist:
|
||||
neut_resist = 100 - (neut_resist * 100)
|
||||
label_tooltip = "Neut Resistance: {0:.0f}%".format(neut_resist)
|
||||
if labelName in ("label%sCapacitorRecharge", "label%sCapacitorDischarge"):
|
||||
neut_resist_preformat = 100 - (neut_resist * 100) if neut_resist else neut_resist
|
||||
label_tooltip = "Capacitor delta: {}\nNeut resistance: {}%".format(
|
||||
formatAmount(cap_recharge - cap_use, 3, 0, 3, forceSign=True),
|
||||
formatAmount(neut_resist_preformat, 3, 0, 3))
|
||||
label.SetToolTip(wx.ToolTip(label_tooltip))
|
||||
|
||||
capState = fit.capState if fit is not None else 0
|
||||
|
||||
@@ -106,9 +106,11 @@ class Miscellanea(ViewColumn):
|
||||
pass
|
||||
elif itemGroup in ("Energy Weapon", "Hybrid Weapon", "Projectile Weapon", "Combat Drone", "Fighter Drone"):
|
||||
trackingSpeed = stuff.getModifiedItemAttr("trackingSpeed")
|
||||
if not trackingSpeed:
|
||||
optimalSig = stuff.getModifiedItemAttr("optimalSigRadius")
|
||||
if not trackingSpeed or not optimalSig:
|
||||
return "", None
|
||||
text = "{0}".format(formatAmount(trackingSpeed, 3, 0, 3))
|
||||
normalizedTracking = trackingSpeed * 40000 / optimalSig
|
||||
text = "{0}".format(formatAmount(normalizedTracking, 3, 0, 3))
|
||||
tooltip = "Tracking speed"
|
||||
return text, tooltip
|
||||
elif itemGroup == "Precursor Weapon":
|
||||
@@ -140,7 +142,10 @@ class Miscellanea(ViewColumn):
|
||||
return "+ " + ", ".join(info), "Slot Modifiers"
|
||||
elif itemGroup == "Energy Neutralizer":
|
||||
neutAmount = stuff.getModifiedItemAttr("energyNeutralizerAmount")
|
||||
cycleTime = stuff.cycleTime
|
||||
cycleParams = stuff.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
return "", None
|
||||
cycleTime = cycleParams.averageTime
|
||||
if not neutAmount or not cycleTime:
|
||||
return "", None
|
||||
capPerSec = float(-neutAmount) * 1000 / cycleTime
|
||||
@@ -149,7 +154,10 @@ class Miscellanea(ViewColumn):
|
||||
return text, tooltip
|
||||
elif itemGroup == "Energy Nosferatu":
|
||||
neutAmount = stuff.getModifiedItemAttr("powerTransferAmount")
|
||||
cycleTime = stuff.cycleTime
|
||||
cycleParams = stuff.getCycleParameters()
|
||||
if cycleParams is None:
|
||||
return "", None
|
||||
cycleTime = cycleParams.averageTime
|
||||
if not neutAmount or not cycleTime:
|
||||
return "", None
|
||||
capPerSec = float(-neutAmount) * 1000 / cycleTime
|
||||
|
||||
@@ -34,7 +34,7 @@ from eos.saveddata.module import Module, Rack
|
||||
from eos.const import FittingSlot
|
||||
from gui.bitmap_loader import BitmapLoader
|
||||
from gui.builtinMarketBrowser.events import ITEM_SELECTED
|
||||
from gui.builtinShipBrowser.events import EVT_FIT_REMOVED, EVT_FIT_RENAMED, EVT_FIT_SELECTED, FitSelected
|
||||
from gui.builtinShipBrowser.events import EVT_FIT_RENAMED, EVT_FIT_SELECTED, FitSelected
|
||||
from gui.builtinViewColumns.state import State
|
||||
from gui.chrome_tabs import EVT_NOTEBOOK_PAGE_CHANGED
|
||||
from gui.contextMenu import ContextMenu
|
||||
@@ -148,7 +148,7 @@ class FittingView(d.Display):
|
||||
self.parent = parent
|
||||
self.mainFrame.Bind(GE.FIT_CHANGED, self.fitChanged)
|
||||
self.mainFrame.Bind(EVT_FIT_RENAMED, self.fitRenamed)
|
||||
self.mainFrame.Bind(EVT_FIT_REMOVED, self.fitRemoved)
|
||||
self.mainFrame.Bind(GE.FIT_REMOVED, self.fitRemoved)
|
||||
self.mainFrame.Bind(ITEM_SELECTED, self.appendItem)
|
||||
self.font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT)
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
# =============================================================================
|
||||
|
||||
import re
|
||||
import traceback
|
||||
|
||||
import roman
|
||||
# noinspection PyPackageRequirements
|
||||
@@ -31,6 +32,7 @@ from logbook import Logger
|
||||
from wx.dataview import TreeListCtrl
|
||||
from wx.lib.agw.floatspin import FloatSpin
|
||||
|
||||
import config
|
||||
import gui.globalEvents as GE
|
||||
from gui.bitmap_loader import BitmapLoader
|
||||
from gui.builtinViews.entityEditor import BaseValidator, EntityEditor, TextEntryValidatedDialog
|
||||
@@ -256,7 +258,8 @@ class CharacterEditor(wx.Frame):
|
||||
|
||||
def kbEvent(self, event):
|
||||
keycode = event.GetKeyCode()
|
||||
if keycode == wx.WXK_ESCAPE:
|
||||
mstate = wx.GetMouseState()
|
||||
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
|
||||
self.closeWindow()
|
||||
return
|
||||
event.Skip()
|
||||
@@ -875,9 +878,11 @@ class APIView(wx.Panel):
|
||||
|
||||
def __fetchCallback(self, e=None):
|
||||
if e:
|
||||
exc_type, exc_obj, exc_trace = e
|
||||
pyfalog.warn("Error fetching skill information for character")
|
||||
pyfalog.warn(exc_obj)
|
||||
pyfalog.warn("Error fetching skill information for character for __fetchCallback")
|
||||
exc_type, exc_value, exc_trace = e
|
||||
if config.debug:
|
||||
exc_value = ''.join(traceback.format_exception(exc_type, exc_value, exc_trace))
|
||||
pyfalog.warn(exc_value)
|
||||
|
||||
wx.MessageBox(
|
||||
"Error fetching skill information",
|
||||
|
||||
@@ -17,17 +17,21 @@
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
import traceback
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import wx
|
||||
from gui.bitmap_loader import BitmapLoader
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
import config
|
||||
import gui.globalEvents as GE
|
||||
import gui.mainFrame
|
||||
from gui.bitmap_loader import BitmapLoader
|
||||
from gui.utils.clipboard import toClipboard
|
||||
from service.character import Character
|
||||
from service.fit import Fit
|
||||
from gui.utils.clipboard import toClipboard
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
@@ -159,9 +163,11 @@ class CharacterSelection(wx.Panel):
|
||||
if e is None:
|
||||
self.refreshCharacterList()
|
||||
else:
|
||||
exc_type, exc_obj, exc_trace = e
|
||||
pyfalog.warn("Error fetching skill information for character")
|
||||
pyfalog.warn(exc_obj)
|
||||
pyfalog.warn("Error fetching skill information for character for refreshAPICallback")
|
||||
exc_type, exc_value, exc_trace = e
|
||||
if config.debug:
|
||||
exc_value = ''.join(traceback.format_exception(exc_type, exc_value, exc_trace))
|
||||
pyfalog.warn(exc_value)
|
||||
|
||||
wx.MessageBox(
|
||||
"Error fetching skill information",
|
||||
|
||||
@@ -24,7 +24,7 @@ class EveFittings(wx.Frame):
|
||||
|
||||
def __init__(self, parent):
|
||||
wx.Frame.__init__(self, parent, id=wx.ID_ANY, title="Browse EVE Fittings", pos=wx.DefaultPosition,
|
||||
size=wx.Size(550, 450), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
|
||||
size=wx.Size(750, 450), style=wx.DEFAULT_FRAME_STYLE | wx.TAB_TRAVERSAL)
|
||||
|
||||
self.SetBackgroundColour(wx.SystemSettings.GetColour(wx.SYS_COLOUR_BTNFACE))
|
||||
|
||||
@@ -49,7 +49,8 @@ class EveFittings(wx.Frame):
|
||||
|
||||
self.fitTree = FittingsTreeView(self)
|
||||
browserSizer.Add(self.fitTree, 1, wx.ALL | wx.EXPAND, 5)
|
||||
contentSizer.Add(browserSizer, 1, wx.EXPAND, 0)
|
||||
browserSizer.SetItemMinSize(0, 200, 0)
|
||||
contentSizer.Add(browserSizer, 0, wx.EXPAND, 0)
|
||||
fitSizer = wx.BoxSizer(wx.VERTICAL)
|
||||
|
||||
self.fitView = FitView(self)
|
||||
@@ -96,7 +97,8 @@ class EveFittings(wx.Frame):
|
||||
|
||||
def kbEvent(self, event):
|
||||
keycode = event.GetKeyCode()
|
||||
if keycode == wx.WXK_ESCAPE:
|
||||
mstate = wx.GetMouseState()
|
||||
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
|
||||
self.closeWindow()
|
||||
return
|
||||
event.Skip()
|
||||
@@ -250,7 +252,8 @@ class ExportToEve(wx.Frame):
|
||||
|
||||
def kbEvent(self, event):
|
||||
keycode = event.GetKeyCode()
|
||||
if keycode == wx.WXK_ESCAPE:
|
||||
mstate = wx.GetMouseState()
|
||||
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
|
||||
self.closeWindow()
|
||||
return
|
||||
event.Skip()
|
||||
@@ -353,7 +356,8 @@ class SsoCharacterMgmt(wx.Dialog):
|
||||
|
||||
def kbEvent(self, event):
|
||||
keycode = event.GetKeyCode()
|
||||
if keycode == wx.WXK_ESCAPE:
|
||||
mstate = wx.GetMouseState()
|
||||
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
|
||||
self.closeWindow()
|
||||
return
|
||||
event.Skip()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -10,12 +9,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddBoosterCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, boosterInfo, position=None, commit=True):
|
||||
def __init__(self, fitID, boosterInfo, position=None):
|
||||
wx.Command.__init__(self, True, 'Add Booster')
|
||||
self.fitID = fitID
|
||||
self.newBoosterInfo = boosterInfo
|
||||
self.newPosition = position
|
||||
self.commit = commit
|
||||
self.oldBoosterInfo = None
|
||||
self.oldPosition = None
|
||||
|
||||
@@ -40,8 +38,7 @@ class CalcAddBoosterCommand(wx.Command):
|
||||
cmd = CalcAddBoosterCommand(
|
||||
fitID=self.fitID,
|
||||
boosterInfo=self.oldBoosterInfo,
|
||||
position=self.oldPosition,
|
||||
commit=self.commit)
|
||||
position=self.oldPosition)
|
||||
cmd.Do()
|
||||
return False
|
||||
else:
|
||||
@@ -51,21 +48,18 @@ class CalcAddBoosterCommand(wx.Command):
|
||||
cmd = CalcAddBoosterCommand(
|
||||
fitID=self.fitID,
|
||||
boosterInfo=self.oldBoosterInfo,
|
||||
position=self.oldPosition,
|
||||
commit=self.commit)
|
||||
position=self.oldPosition)
|
||||
cmd.Do()
|
||||
return False
|
||||
self.newPosition = fit.boosters.index(newBooster)
|
||||
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
pyfalog.debug('Undo addition of booster {} to fit {}'.format(self.newBoosterInfo, self.fitID))
|
||||
if self.oldBoosterInfo is not None and self.oldPosition is not None:
|
||||
cmd = CalcAddBoosterCommand(fitID=self.fitID, boosterInfo=self.oldBoosterInfo, position=self.oldPosition, commit=self.commit)
|
||||
cmd = CalcAddBoosterCommand(fitID=self.fitID, boosterInfo=self.oldBoosterInfo, position=self.oldPosition)
|
||||
return cmd.Do()
|
||||
from .remove import CalcRemoveBoosterCommand
|
||||
cmd = CalcRemoveBoosterCommand(fitID=self.fitID, position=self.newPosition, commit=self.commit)
|
||||
cmd = CalcRemoveBoosterCommand(fitID=self.fitID, position=self.newPosition)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import BoosterInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -11,11 +10,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveBoosterCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, position, commit=True):
|
||||
def __init__(self, fitID, position):
|
||||
wx.Command.__init__(self, True, 'Remove Booster')
|
||||
self.fitID = fitID
|
||||
self.position = position
|
||||
self.commit = commit
|
||||
self.savedBoosterInfo = None
|
||||
|
||||
def Do(self):
|
||||
@@ -24,8 +22,6 @@ class CalcRemoveBoosterCommand(wx.Command):
|
||||
booster = fit.boosters[self.position]
|
||||
self.savedBoosterInfo = BoosterInfo.fromBooster(booster)
|
||||
fit.boosters.remove(booster)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -34,6 +30,5 @@ class CalcRemoveBoosterCommand(wx.Command):
|
||||
cmd = CalcAddBoosterCommand(
|
||||
fitID=self.fitID,
|
||||
boosterInfo=self.savedBoosterInfo,
|
||||
position=self.position,
|
||||
commit=self.commit)
|
||||
position=self.position)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -28,7 +27,6 @@ class CalcToggleBoosterSideEffectStateCommand(wx.Command):
|
||||
return False
|
||||
self.savedState = sideEffect.active
|
||||
sideEffect.active = not sideEffect.active if self.forceState is None else self.forceState
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -41,7 +40,6 @@ class CalcToggleBoosterStatesCommand(wx.Command):
|
||||
booster = fit.boosters[position]
|
||||
if not booster.active:
|
||||
booster.active = True
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -10,11 +9,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddCargoCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, cargoInfo, commit=True):
|
||||
def __init__(self, fitID, cargoInfo):
|
||||
wx.Command.__init__(self, True, 'Add Cargo')
|
||||
self.fitID = fitID
|
||||
self.cargoInfo = cargoInfo
|
||||
self.commit = commit
|
||||
|
||||
def Do(self):
|
||||
pyfalog.debug('Doing addition of cargo {} to fit {}'.format(self.cargoInfo, self.fitID))
|
||||
@@ -27,15 +25,11 @@ class CalcAddCargoCommand(wx.Command):
|
||||
fit.cargo.append(cargo)
|
||||
if cargo not in fit.cargo:
|
||||
pyfalog.warning('Failed to append to list')
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
pyfalog.debug('Undoing addition of cargo {} to fit {}'.format(self.cargoInfo, self.fitID))
|
||||
from .remove import CalcRemoveCargoCommand
|
||||
cmd = CalcRemoveCargoCommand(fitID=self.fitID, cargoInfo=self.cargoInfo, commit=self.commit)
|
||||
cmd = CalcRemoveCargoCommand(fitID=self.fitID, cargoInfo=self.cargoInfo)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import CargoInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -28,7 +27,6 @@ class CalcChangeCargoAmountCommand(wx.Command):
|
||||
if self.cargoInfo.amount == self.savedCargoInfo.amount:
|
||||
return False
|
||||
cargo.amount = self.cargoInfo.amount
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import wx
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import CargoInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -12,11 +10,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveCargoCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, cargoInfo, commit=True):
|
||||
def __init__(self, fitID, cargoInfo):
|
||||
wx.Command.__init__(self, True, 'Remove Cargo')
|
||||
self.fitID = fitID
|
||||
self.cargoInfo = cargoInfo
|
||||
self.commit = commit
|
||||
self.savedRemovedAmount = None
|
||||
|
||||
def Do(self):
|
||||
@@ -29,8 +26,6 @@ class CalcRemoveCargoCommand(wx.Command):
|
||||
cargo.amount -= self.savedRemovedAmount
|
||||
if cargo.amount <= 0:
|
||||
fit.cargo.remove(cargo)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -38,6 +33,5 @@ class CalcRemoveCargoCommand(wx.Command):
|
||||
from .add import CalcAddCargoCommand
|
||||
cmd = CalcAddCargoCommand(
|
||||
fitID=self.fitID,
|
||||
cargoInfo=CargoInfo(itemID=self.cargoInfo.itemID, amount=self.savedRemovedAmount),
|
||||
commit=self.commit)
|
||||
cargoInfo=CargoInfo(itemID=self.cargoInfo.itemID, amount=self.savedRemovedAmount))
|
||||
return cmd.Do()
|
||||
|
||||
@@ -10,12 +10,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddCommandCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, commandFitID, state=None, commit=True):
|
||||
def __init__(self, fitID, commandFitID, state=None):
|
||||
wx.Command.__init__(self, True, 'Add Command Fit')
|
||||
self.fitID = fitID
|
||||
self.commandFitID = commandFitID
|
||||
self.state = state
|
||||
self.commit = commit
|
||||
|
||||
def Do(self):
|
||||
pyfalog.debug('Doing addition of command fit {} for fit {}'.format(self.commandFitID, self.fitID))
|
||||
@@ -47,8 +46,6 @@ class CalcAddCommandCommand(wx.Command):
|
||||
return False
|
||||
fitCommandInfo.active = self.state
|
||||
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -59,5 +56,5 @@ class CalcAddCommandCommand(wx.Command):
|
||||
if commandFit is None:
|
||||
return True
|
||||
from .remove import CalcRemoveCommandFitCommand
|
||||
cmd = CalcRemoveCommandFitCommand(fitID=self.fitID, commandFitID=self.commandFitID, commit=self.commit)
|
||||
cmd = CalcRemoveCommandFitCommand(fitID=self.fitID, commandFitID=self.commandFitID)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -10,11 +9,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveCommandFitCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, commandFitID, commit=True):
|
||||
def __init__(self, fitID, commandFitID):
|
||||
wx.Command.__init__(self, True, 'Remove Command Fit')
|
||||
self.fitID = fitID
|
||||
self.commandFitID = commandFitID
|
||||
self.commit = commit
|
||||
self.savedState = None
|
||||
|
||||
def Do(self):
|
||||
@@ -36,8 +34,6 @@ class CalcRemoveCommandFitCommand(wx.Command):
|
||||
pyfalog.warning('Unable to find commanding fit in command dict')
|
||||
return False
|
||||
del fit.commandFitDict[commandFit.ID]
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -46,6 +42,5 @@ class CalcRemoveCommandFitCommand(wx.Command):
|
||||
cmd = CalcAddCommandCommand(
|
||||
fitID=self.fitID,
|
||||
commandFitID=self.commandFitID,
|
||||
state=self.savedState,
|
||||
commit=self.commit)
|
||||
state=self.savedState)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -60,7 +59,6 @@ class CalcToggleCommandFitStatesCommand(wx.Command):
|
||||
# Bail if we cannot calculate which state to take
|
||||
else:
|
||||
return False
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import wx
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import DroneInfo, droneStackLimit
|
||||
from service.fit import Fit
|
||||
from service.market import Market
|
||||
@@ -13,13 +11,12 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddLocalDroneCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, droneInfo, forceNewStack=False, ignoreRestrictions=False, commit=True):
|
||||
def __init__(self, fitID, droneInfo, forceNewStack=False, ignoreRestrictions=False):
|
||||
wx.Command.__init__(self, True, 'Add Local Drone')
|
||||
self.fitID = fitID
|
||||
self.droneInfo = droneInfo
|
||||
self.forceNewStack = forceNewStack
|
||||
self.ignoreRestrictions = ignoreRestrictions
|
||||
self.commit = commit
|
||||
self.savedDroneInfo = None
|
||||
self.savedPosition = None
|
||||
|
||||
@@ -39,8 +36,6 @@ class CalcAddLocalDroneCommand(wx.Command):
|
||||
self.savedDroneInfo = DroneInfo.fromDrone(drone)
|
||||
self.savedPosition = fit.drones.index(drone)
|
||||
drone.amount += self.droneInfo.amount
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
# Do new stack otherwise
|
||||
drone = self.droneInfo.toDrone()
|
||||
@@ -52,11 +47,7 @@ class CalcAddLocalDroneCommand(wx.Command):
|
||||
fit.drones.append(drone)
|
||||
if drone not in fit.drones:
|
||||
pyfalog.warning('Failed to append to list')
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
self.savedPosition = fit.drones.index(drone)
|
||||
return True
|
||||
|
||||
@@ -67,13 +58,10 @@ class CalcAddLocalDroneCommand(wx.Command):
|
||||
drone = fit.drones[self.savedPosition]
|
||||
drone.amount = self.savedDroneInfo.amount
|
||||
drone.amountActive = self.savedDroneInfo.amountActive
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
from .localRemove import CalcRemoveLocalDroneCommand
|
||||
cmd = CalcRemoveLocalDroneCommand(
|
||||
fitID=self.fitID,
|
||||
position=self.savedPosition,
|
||||
amount=self.droneInfo.amount,
|
||||
commit=self.commit)
|
||||
amount=self.droneInfo.amount)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import DroneInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -11,12 +10,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcChangeLocalDroneAmountCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, position, amount, commit=True):
|
||||
def __init__(self, fitID, position, amount):
|
||||
wx.Command.__init__(self, True, 'Change Local Drone Amount')
|
||||
self.fitID = fitID
|
||||
self.position = position
|
||||
self.amount = amount
|
||||
self.commit = commit
|
||||
self.savedDroneInfo = None
|
||||
|
||||
def Do(self):
|
||||
@@ -31,8 +29,6 @@ class CalcChangeLocalDroneAmountCommand(wx.Command):
|
||||
difference = self.amount - self.savedDroneInfo.amount
|
||||
drone.amount = self.amount
|
||||
drone.amountActive = max(min(drone.amountActive + difference, drone.amount), 0)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -42,7 +38,5 @@ class CalcChangeLocalDroneAmountCommand(wx.Command):
|
||||
drone = fit.drones[self.position]
|
||||
drone.amount = self.savedDroneInfo.amount
|
||||
drone.amountActive = self.savedDroneInfo.amountActive
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import DroneInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -11,12 +10,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveLocalDroneCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, position, amount, commit=True):
|
||||
def __init__(self, fitID, position, amount):
|
||||
wx.Command.__init__(self, True, 'Remove Local Drone')
|
||||
self.fitID = fitID
|
||||
self.position = position
|
||||
self.amountToRemove = amount
|
||||
self.commit = commit
|
||||
self.savedDroneInfo = None
|
||||
self.removedStack = None
|
||||
|
||||
@@ -36,8 +34,6 @@ class CalcRemoveLocalDroneCommand(wx.Command):
|
||||
else:
|
||||
self.removedStack = False
|
||||
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -50,13 +46,9 @@ class CalcRemoveLocalDroneCommand(wx.Command):
|
||||
fit.drones.insert(self.position, drone)
|
||||
if drone not in fit.drones:
|
||||
pyfalog.warning('Failed to insert to list')
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
else:
|
||||
drone = fit.drones[self.position]
|
||||
drone.amount = self.savedDroneInfo.amount
|
||||
drone.amountActive = self.savedDroneInfo.amountActive
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -42,7 +42,6 @@ class CalcToggleLocalDroneStatesCommand(wx.Command):
|
||||
if drone.amountActive == 0:
|
||||
drone.amountActive = drone.amount
|
||||
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
import math
|
||||
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import DroneInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -13,11 +11,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddProjectedDroneCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, droneInfo, commit=True):
|
||||
def __init__(self, fitID, droneInfo):
|
||||
wx.Command.__init__(self, True, 'Add Projected Drone')
|
||||
self.fitID = fitID
|
||||
self.droneInfo = droneInfo
|
||||
self.commit = commit
|
||||
self.savedDroneInfo = None
|
||||
|
||||
def Do(self):
|
||||
@@ -32,8 +29,6 @@ class CalcAddProjectedDroneCommand(wx.Command):
|
||||
drone.amount += self.droneInfo.amount
|
||||
if drone.amountActive > 0:
|
||||
drone.amountActive += self.droneInfo.amount
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
# Making new stack
|
||||
drone = self.droneInfo.toDrone()
|
||||
@@ -45,11 +40,7 @@ class CalcAddProjectedDroneCommand(wx.Command):
|
||||
fit.projectedDrones.append(drone)
|
||||
if drone not in fit.projectedDrones:
|
||||
pyfalog.warning('Failed to append to list')
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -63,14 +54,11 @@ class CalcAddProjectedDroneCommand(wx.Command):
|
||||
return False
|
||||
drone.amount = self.savedDroneInfo.amount
|
||||
drone.amountActive = self.savedDroneInfo.amountActive
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
# Removing previously added stack
|
||||
from .projectedRemove import CalcRemoveProjectedDroneCommand
|
||||
cmd = CalcRemoveProjectedDroneCommand(
|
||||
fitID=self.fitID,
|
||||
itemID=self.droneInfo.itemID,
|
||||
amount=math.inf,
|
||||
commit=self.commit)
|
||||
amount=math.inf)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import math
|
||||
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import DroneInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -35,7 +32,6 @@ class CalcChangeProjectedDroneAmountCommand(wx.Command):
|
||||
difference = self.amount - self.savedDroneInfo.amount
|
||||
drone.amount = self.amount
|
||||
drone.amountActive = max(min(drone.amountActive + difference, drone.amount), 0)
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -48,6 +44,5 @@ class CalcChangeProjectedDroneAmountCommand(wx.Command):
|
||||
return False
|
||||
drone.amount = self.savedDroneInfo.amount
|
||||
drone.amountActive = self.savedDroneInfo.amountActive
|
||||
eos.db.commit()
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -10,12 +10,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcChangeProjectedDroneStateCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, itemID, state, commit=True):
|
||||
def __init__(self, fitID, itemID, state):
|
||||
wx.Command.__init__(self, True, 'Change Projected Drone State')
|
||||
self.fitID = fitID
|
||||
self.itemID = itemID
|
||||
self.state = state
|
||||
self.commit = commit
|
||||
self.savedState = None
|
||||
|
||||
def Do(self):
|
||||
@@ -39,8 +38,6 @@ class CalcChangeProjectedDroneStateCommand(wx.Command):
|
||||
else:
|
||||
drone.amountActive = 0
|
||||
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -48,6 +45,5 @@ class CalcChangeProjectedDroneStateCommand(wx.Command):
|
||||
cmd = CalcChangeProjectedDroneStateCommand(
|
||||
fitID=self.fitID,
|
||||
itemID=self.itemID,
|
||||
state=self.savedState,
|
||||
commit=self.commit)
|
||||
state=self.savedState)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import DroneInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -11,12 +10,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveProjectedDroneCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, itemID, amount, commit=True):
|
||||
def __init__(self, fitID, itemID, amount):
|
||||
wx.Command.__init__(self, True, 'Remove Projected Drone')
|
||||
self.fitID = fitID
|
||||
self.itemID = itemID
|
||||
self.amountToRemove = amount
|
||||
self.commit = commit
|
||||
self.savedDroneInfo = None
|
||||
|
||||
def Do(self):
|
||||
@@ -34,8 +32,6 @@ class CalcRemoveProjectedDroneCommand(wx.Command):
|
||||
else:
|
||||
if drone.amountActive > 0:
|
||||
drone.amountActive = min(drone.amountActive, drone.amount)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -46,10 +42,8 @@ class CalcRemoveProjectedDroneCommand(wx.Command):
|
||||
if drone is not None:
|
||||
drone.amount = self.savedDroneInfo.amount
|
||||
drone.amountActive = self.savedDroneInfo.amountActive
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
# Make new stack
|
||||
from .projectedAdd import CalcAddProjectedDroneCommand
|
||||
cmd = CalcAddProjectedDroneCommand(fitID=self.fitID, droneInfo=self.savedDroneInfo, commit=self.commit)
|
||||
cmd = CalcAddProjectedDroneCommand(fitID=self.fitID, droneInfo=self.savedDroneInfo)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -72,7 +71,6 @@ class CalcToggleFighterAbilityStatesCommand(wx.Command):
|
||||
if not ability.active:
|
||||
changes = True
|
||||
ability.active = True
|
||||
eos.db.commit()
|
||||
return changes
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -28,11 +27,9 @@ class CalcChangeFighterAmountCommand(wx.Command):
|
||||
self.savedAmount = fighter.amount
|
||||
if self.amount == -1:
|
||||
fighter.amount = self.amount
|
||||
eos.db.commit()
|
||||
return True
|
||||
else:
|
||||
fighter.amount = max(min(self.amount, fighter.fighterSquadronMaxSize), 0)
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -10,13 +9,12 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddLocalFighterCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, fighterInfo, position=None, ignoreRestrictions=False, commit=True):
|
||||
def __init__(self, fitID, fighterInfo, position=None, ignoreRestrictions=False):
|
||||
wx.Command.__init__(self, True, 'Add Fighter')
|
||||
self.fitID = fitID
|
||||
self.fighterInfo = fighterInfo
|
||||
self.position = position
|
||||
self.ignoreRestrictions = ignoreRestrictions
|
||||
self.commit = commit
|
||||
|
||||
def Do(self):
|
||||
pyfalog.debug('Doing addition of fighter {} to fit {}'.format(self.fighterInfo, self.fitID))
|
||||
@@ -43,24 +41,18 @@ class CalcAddLocalFighterCommand(wx.Command):
|
||||
fit.fighters.append(fighter)
|
||||
if fighter not in fit.fighters:
|
||||
pyfalog.warning('Failed to append to list')
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
self.position = fit.fighters.index(fighter)
|
||||
else:
|
||||
fit.fighters.insert(self.position, fighter)
|
||||
if fighter not in fit.fighters:
|
||||
pyfalog.warning('Failed to insert to list')
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
pyfalog.debug('Undoing addition of fighter {} to fit {}'.format(self.fighterInfo, self.fitID))
|
||||
from .localRemove import CalcRemoveLocalFighterCommand
|
||||
cmd = CalcRemoveLocalFighterCommand(fitID=self.fitID, position=self.position, commit=self.commit)
|
||||
cmd = CalcRemoveLocalFighterCommand(fitID=self.fitID, position=self.position)
|
||||
cmd.Do()
|
||||
return True
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import FighterInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -11,11 +10,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveLocalFighterCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, position, commit=True):
|
||||
def __init__(self, fitID, position):
|
||||
wx.Command.__init__(self, True, 'Remove Fighter')
|
||||
self.fitID = fitID
|
||||
self.position = position
|
||||
self.commit = commit
|
||||
self.savedFighterInfo = None
|
||||
|
||||
def Do(self):
|
||||
@@ -24,8 +22,6 @@ class CalcRemoveLocalFighterCommand(wx.Command):
|
||||
fighter = fit.fighters[self.position]
|
||||
self.savedFighterInfo = FighterInfo.fromFighter(fighter)
|
||||
fit.fighters.remove(fighter)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -35,6 +31,5 @@ class CalcRemoveLocalFighterCommand(wx.Command):
|
||||
fitID=self.fitID,
|
||||
fighterInfo=self.savedFighterInfo,
|
||||
position=self.position,
|
||||
ignoreRestrictions=True,
|
||||
commit=self.commit)
|
||||
ignoreRestrictions=True)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -42,7 +42,6 @@ class CalcToggleLocalFighterStatesCommand(wx.Command):
|
||||
fighter = fit.fighters[position]
|
||||
if not fighter.active:
|
||||
fighter.active = True
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -10,12 +9,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddProjectedFighterCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, fighterInfo, position=None, commit=True):
|
||||
def __init__(self, fitID, fighterInfo, position=None):
|
||||
wx.Command.__init__(self, True, 'Add Projected Fighter')
|
||||
self.fitID = fitID
|
||||
self.fighterInfo = fighterInfo
|
||||
self.position = position
|
||||
self.commit = commit
|
||||
|
||||
def Do(self):
|
||||
pyfalog.debug('Doing addition of projected fighter {} onto: {}'.format(self.fighterInfo, self.fitID))
|
||||
@@ -26,22 +24,16 @@ class CalcAddProjectedFighterCommand(wx.Command):
|
||||
if self.position is not None:
|
||||
fit.projectedFighters.insert(self.position, fighter)
|
||||
if fighter not in fit.projectedFighters:
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
else:
|
||||
fit.projectedFighters.append(fighter)
|
||||
if fighter not in fit.projectedFighters:
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
self.position = fit.projectedFighters.index(fighter)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
pyfalog.debug('Undoing addition of projected fighter {} onto: {}'.format(self.fighterInfo, self.fitID))
|
||||
from .projectedRemove import CalcRemoveProjectedFighterCommand
|
||||
cmd = CalcRemoveProjectedFighterCommand(fitID=self.fitID, position=self.position, commit=self.commit)
|
||||
cmd = CalcRemoveProjectedFighterCommand(fitID=self.fitID, position=self.position)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -10,12 +9,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcChangeProjectedFighterStateCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, position, state, commit=True):
|
||||
def __init__(self, fitID, position, state):
|
||||
wx.Command.__init__(self, True, 'Change Projected Fighter State')
|
||||
self.fitID = fitID
|
||||
self.position = position
|
||||
self.state = state
|
||||
self.commit = commit
|
||||
self.savedState = None
|
||||
|
||||
def Do(self):
|
||||
@@ -31,8 +29,6 @@ class CalcChangeProjectedFighterStateCommand(wx.Command):
|
||||
|
||||
fighter.active = self.state
|
||||
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -41,6 +37,5 @@ class CalcChangeProjectedFighterStateCommand(wx.Command):
|
||||
cmd = CalcChangeProjectedFighterStateCommand(
|
||||
fitID=self.fitID,
|
||||
position=self.position,
|
||||
state=self.savedState,
|
||||
commit=self.commit)
|
||||
state=self.savedState)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import FighterInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -11,11 +10,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveProjectedFighterCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, position, commit=True):
|
||||
def __init__(self, fitID, position):
|
||||
wx.Command.__init__(self, True, 'Add Projected Fighter')
|
||||
self.fitID = fitID
|
||||
self.position = position
|
||||
self.commit = commit
|
||||
self.savedFighterInfo = None
|
||||
|
||||
def Do(self):
|
||||
@@ -24,8 +22,6 @@ class CalcRemoveProjectedFighterCommand(wx.Command):
|
||||
fighter = fit.projectedFighters[self.position]
|
||||
self.savedFighterInfo = FighterInfo.fromFighter(fighter)
|
||||
fit.projectedFighters.remove(fighter)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -34,6 +30,5 @@ class CalcRemoveProjectedFighterCommand(wx.Command):
|
||||
cmd = CalcAddProjectedFighterCommand(
|
||||
fitID=self.fitID,
|
||||
fighterInfo=self.savedFighterInfo,
|
||||
position=self.position,
|
||||
commit=self.commit)
|
||||
position=self.position)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -23,7 +22,6 @@ class CalcFitRenameCommand(wx.Command):
|
||||
return False
|
||||
self.savedName = fit.name
|
||||
fit.name = self.name
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -25,7 +24,6 @@ class CalcChangeFitSystemSecurityCommand(wx.Command):
|
||||
return False
|
||||
self.savedSecStatus = fit.systemSecurity
|
||||
fit.systemSecurity = self.secStatus
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -10,12 +9,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddImplantCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, implantInfo, position=None, commit=True):
|
||||
def __init__(self, fitID, implantInfo, position=None):
|
||||
wx.Command.__init__(self, True, 'Add Implant')
|
||||
self.fitID = fitID
|
||||
self.newImplantInfo = implantInfo
|
||||
self.newPosition = position
|
||||
self.commit = commit
|
||||
self.oldImplantInfo = None
|
||||
self.oldPosition = None
|
||||
|
||||
@@ -40,8 +38,7 @@ class CalcAddImplantCommand(wx.Command):
|
||||
cmd = CalcAddImplantCommand(
|
||||
fitID=self.fitID,
|
||||
implantInfo=self.oldImplantInfo,
|
||||
position=self.oldPosition,
|
||||
commit=self.commit)
|
||||
position=self.oldPosition)
|
||||
cmd.Do()
|
||||
return False
|
||||
else:
|
||||
@@ -51,13 +48,10 @@ class CalcAddImplantCommand(wx.Command):
|
||||
cmd = CalcAddImplantCommand(
|
||||
fitID=self.fitID,
|
||||
implantInfo=self.oldImplantInfo,
|
||||
position=self.oldPosition,
|
||||
commit=self.commit)
|
||||
position=self.oldPosition)
|
||||
cmd.Do()
|
||||
return False
|
||||
self.newPosition = fit.implants.index(newImplant)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -66,9 +60,8 @@ class CalcAddImplantCommand(wx.Command):
|
||||
cmd = CalcAddImplantCommand(
|
||||
fitID=self.fitID,
|
||||
implantInfo=self.oldImplantInfo,
|
||||
position=self.oldPosition,
|
||||
commit=self.commit)
|
||||
position=self.oldPosition)
|
||||
return cmd.Do()
|
||||
from .remove import CalcRemoveImplantCommand
|
||||
cmd = CalcRemoveImplantCommand(fitID=self.fitID, position=self.newPosition, commit=self.commit)
|
||||
cmd = CalcRemoveImplantCommand(fitID=self.fitID, position=self.newPosition)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -10,11 +9,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcChangeImplantLocationCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, source, commit=True):
|
||||
def __init__(self, fitID, source):
|
||||
wx.Command.__init__(self, True, 'Change Implant Location')
|
||||
self.fitID = fitID
|
||||
self.source = source
|
||||
self.commit = commit
|
||||
self.savedSource = None
|
||||
|
||||
def Do(self):
|
||||
@@ -24,10 +22,8 @@ class CalcChangeImplantLocationCommand(wx.Command):
|
||||
if self.source == self.savedSource:
|
||||
return False
|
||||
fit.implantSource = self.source
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
cmd = CalcChangeImplantLocationCommand(fitID=self.fitID, source=self.savedSource, commit=self.commit)
|
||||
cmd = CalcChangeImplantLocationCommand(fitID=self.fitID, source=self.savedSource)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import ImplantInfo
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -11,11 +10,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveImplantCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, position, commit=True):
|
||||
def __init__(self, fitID, position):
|
||||
wx.Command.__init__(self, True, 'Remove Implant')
|
||||
self.fitID = fitID
|
||||
self.position = position
|
||||
self.commit = commit
|
||||
self.savedImplantInfo = None
|
||||
|
||||
def Do(self):
|
||||
@@ -24,8 +22,6 @@ class CalcRemoveImplantCommand(wx.Command):
|
||||
implant = fit.implants[self.position]
|
||||
self.savedImplantInfo = ImplantInfo.fromImplant(implant)
|
||||
fit.implants.remove(implant)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -34,6 +30,5 @@ class CalcRemoveImplantCommand(wx.Command):
|
||||
cmd = CalcAddImplantCommand(
|
||||
fitID=self.fitID,
|
||||
implantInfo=self.savedImplantInfo,
|
||||
position=self.position,
|
||||
commit=self.commit)
|
||||
position=self.position)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -41,7 +40,6 @@ class CalcToggleImplantStatesCommand(wx.Command):
|
||||
implant = fit.implants[position]
|
||||
if not implant.active:
|
||||
implant.active = True
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
from service.market import Market
|
||||
|
||||
@@ -11,13 +10,12 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRebaseItemCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, containerName, position, itemID, commit=True):
|
||||
def __init__(self, fitID, containerName, position, itemID):
|
||||
wx.Command.__init__(self, True, 'Rebase Item')
|
||||
self.fitID = fitID
|
||||
self.containerName = containerName
|
||||
self.position = position
|
||||
self.itemID = itemID
|
||||
self.commit = commit
|
||||
self.savedItemID = None
|
||||
|
||||
def Do(self):
|
||||
@@ -33,8 +31,6 @@ class CalcRebaseItemCommand(wx.Command):
|
||||
pyfalog.warning('Unable to fetch new item')
|
||||
return False
|
||||
obj.rebase(newItem)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -43,6 +39,5 @@ class CalcRebaseItemCommand(wx.Command):
|
||||
fitID=self.fitID,
|
||||
containerName=self.containerName,
|
||||
position=self.position,
|
||||
itemID=self.savedItemID,
|
||||
commit=self.commit)
|
||||
itemID=self.savedItemID)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import restoreCheckedStates
|
||||
from service.fit import Fit
|
||||
from service.market import Market
|
||||
@@ -12,13 +11,12 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcChangeModuleChargesCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, projected, chargeMap, ignoreRestriction=False, commit=True):
|
||||
def __init__(self, fitID, projected, chargeMap, ignoreRestriction=False):
|
||||
wx.Command.__init__(self, True, 'Change Module Charges')
|
||||
self.fitID = fitID
|
||||
self.projected = projected
|
||||
self.chargeMap = chargeMap
|
||||
self.ignoreRestriction = ignoreRestriction
|
||||
self.commit = commit
|
||||
self.savedChargeMap = None
|
||||
self.savedStateCheckChanges = None
|
||||
|
||||
@@ -52,8 +50,6 @@ class CalcChangeModuleChargesCommand(wx.Command):
|
||||
return False
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, None)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -62,8 +58,7 @@ class CalcChangeModuleChargesCommand(wx.Command):
|
||||
fitID=self.fitID,
|
||||
projected=self.projected,
|
||||
chargeMap=self.savedChargeMap,
|
||||
ignoreRestriction=True,
|
||||
commit=self.commit)
|
||||
ignoreRestriction=True)
|
||||
if not cmd.Do():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -34,7 +33,6 @@ class CalcChangeModuleSpoolCommand(wx.Command):
|
||||
return False
|
||||
mod.spoolType = self.spoolType
|
||||
mod.spoolAmount = self.spoolAmount
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
@@ -11,11 +11,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddLocalModuleCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, newModInfo, commit=True):
|
||||
def __init__(self, fitID, newModInfo):
|
||||
wx.Command.__init__(self, True, 'Add Module')
|
||||
self.fitID = fitID
|
||||
self.newModInfo = newModInfo
|
||||
self.commit = commit
|
||||
self.savedPosition = None
|
||||
self.subsystemCmd = None
|
||||
self.savedStateCheckChanges = None
|
||||
@@ -39,8 +38,7 @@ class CalcAddLocalModuleCommand(wx.Command):
|
||||
self.subsystemCmd = CalcReplaceLocalModuleCommand(
|
||||
fitID=self.fitID,
|
||||
position=fit.modules.index(oldMod),
|
||||
newModInfo=self.newModInfo,
|
||||
commit=False)
|
||||
newModInfo=self.newModInfo)
|
||||
if not self.subsystemCmd.Do():
|
||||
return False
|
||||
# Need to flush because checkStates sometimes relies on module->fit
|
||||
@@ -48,8 +46,6 @@ class CalcAddLocalModuleCommand(wx.Command):
|
||||
eos.db.flush()
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, newMod)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
if not newMod.fits(fit):
|
||||
pyfalog.warning('Module does not fit')
|
||||
@@ -57,8 +53,6 @@ class CalcAddLocalModuleCommand(wx.Command):
|
||||
fit.modules.append(newMod)
|
||||
if newMod not in fit.modules:
|
||||
pyfalog.warning('Failed to append to list')
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
self.savedPosition = fit.modules.index(newMod)
|
||||
# Need to flush because checkStates sometimes relies on module->fit
|
||||
@@ -66,8 +60,6 @@ class CalcAddLocalModuleCommand(wx.Command):
|
||||
eos.db.flush()
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, newMod)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -77,16 +69,12 @@ class CalcAddLocalModuleCommand(wx.Command):
|
||||
if not self.subsystemCmd.Undo():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
if self.savedPosition is None:
|
||||
return False
|
||||
from .localRemove import CalcRemoveLocalModulesCommand
|
||||
cmd = CalcRemoveLocalModulesCommand(fitID=self.fitID, positions=[self.savedPosition], commit=False)
|
||||
cmd = CalcRemoveLocalModulesCommand(fitID=self.fitID, positions=[self.savedPosition])
|
||||
if not cmd.Do():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -10,13 +9,12 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcChangeLocalModuleMutationCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, position, mutation, oldMutation=None, commit=True):
|
||||
def __init__(self, fitID, position, mutation, oldMutation=None):
|
||||
wx.Command.__init__(self, True, 'Change Local Module Mutation')
|
||||
self.fitID = fitID
|
||||
self.position = position
|
||||
self.mutation = mutation
|
||||
self.savedMutation = oldMutation
|
||||
self.commit = commit
|
||||
|
||||
def Do(self):
|
||||
pyfalog.debug('Doing changing of local module mutation at position {} to {} for fit ID {}'.format(
|
||||
@@ -41,8 +39,6 @@ class CalcChangeLocalModuleMutationCommand(wx.Command):
|
||||
if mutator.value != self.mutation[mutator.attrID]:
|
||||
mutator.value = self.mutation[mutator.attrID]
|
||||
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -51,6 +47,5 @@ class CalcChangeLocalModuleMutationCommand(wx.Command):
|
||||
cmd = CalcChangeLocalModuleMutationCommand(
|
||||
fitID=self.fitID,
|
||||
position=self.position,
|
||||
mutation=self.savedMutation,
|
||||
commit=self.commit)
|
||||
mutation=self.savedMutation)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from eos.saveddata.module import Module
|
||||
from gui.fitCommands.helpers import restoreCheckedStates
|
||||
from service.fit import Fit
|
||||
@@ -51,7 +50,6 @@ class CalcChangeLocalModuleStatesCommand(wx.Command):
|
||||
return False
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, mainMod)
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -62,5 +60,4 @@ class CalcChangeLocalModuleStatesCommand(wx.Command):
|
||||
pyfalog.debug('Reverting {} to state {} for fit ID {}'.format(mod, state, self.fitID))
|
||||
mod.state = state
|
||||
restoreCheckedStates(fit, self.savedStateCheckChanges, ignoreModPoss=self.savedStates)
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -33,22 +33,19 @@ class CalcCloneLocalModuleCommand(wx.Command):
|
||||
fit.modules.replace(self.dstPosition, copyMod)
|
||||
if copyMod not in fit.modules:
|
||||
pyfalog.warning('Failed to replace module')
|
||||
eos.db.commit()
|
||||
return False
|
||||
# Need to flush because checkStates sometimes relies on module->fit
|
||||
# relationship via .owner attribute, which is handled by SQLAlchemy
|
||||
eos.db.flush()
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, copyMod)
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
pyfalog.debug('Undoing cloning of local module from position {} to position {} for fit ID {}'.format(self.srcPosition, self.dstPosition, self.fitID))
|
||||
from .localRemove import CalcRemoveLocalModulesCommand
|
||||
cmd = CalcRemoveLocalModulesCommand(fitID=self.fitID, positions=[self.dstPosition], commit=False)
|
||||
cmd = CalcRemoveLocalModulesCommand(fitID=self.fitID, positions=[self.dstPosition])
|
||||
if not cmd.Do():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -12,11 +12,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveLocalModulesCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, positions, commit=True):
|
||||
def __init__(self, fitID, positions):
|
||||
wx.Command.__init__(self, True, 'Remove Module')
|
||||
self.fitID = fitID
|
||||
self.positions = positions
|
||||
self.commit = commit
|
||||
self.savedSubInfos = None
|
||||
self.savedModInfos = None
|
||||
self.savedStateCheckChanges = None
|
||||
@@ -45,8 +44,6 @@ class CalcRemoveLocalModulesCommand(wx.Command):
|
||||
eos.db.flush()
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, None)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
# If no modules were removed, report that command was not completed
|
||||
return True
|
||||
|
||||
@@ -63,8 +60,7 @@ class CalcRemoveLocalModulesCommand(wx.Command):
|
||||
fitID=self.fitID,
|
||||
position=position,
|
||||
newModInfo=modInfo,
|
||||
ignoreRestrictions=True,
|
||||
commit=False)
|
||||
ignoreRestrictions=True)
|
||||
results.append(cmd.Do())
|
||||
sFit.recalc(fit)
|
||||
for position, modInfo in self.savedModInfos.items():
|
||||
@@ -72,12 +68,9 @@ class CalcRemoveLocalModulesCommand(wx.Command):
|
||||
fitID=self.fitID,
|
||||
position=position,
|
||||
newModInfo=modInfo,
|
||||
ignoreRestrictions=True,
|
||||
commit=False)
|
||||
ignoreRestrictions=True)
|
||||
results.append(cmd.Do())
|
||||
if not any(results):
|
||||
return False
|
||||
restoreCheckedStates(fit, self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -11,7 +11,7 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcReplaceLocalModuleCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, position, newModInfo, unloadInvalidCharges=False, ignoreRestrictions=False, commit=True):
|
||||
def __init__(self, fitID, position, newModInfo, unloadInvalidCharges=False, ignoreRestrictions=False):
|
||||
wx.Command.__init__(self, True, 'Replace Module')
|
||||
self.fitID = fitID
|
||||
self.position = position
|
||||
@@ -19,7 +19,6 @@ class CalcReplaceLocalModuleCommand(wx.Command):
|
||||
self.oldModInfo = None
|
||||
self.unloadInvalidCharges = unloadInvalidCharges
|
||||
self.ignoreRestrictions = ignoreRestrictions
|
||||
self.commit = commit
|
||||
self.savedStateCheckChanges = None
|
||||
self.unloadedCharge = None
|
||||
|
||||
@@ -62,8 +61,6 @@ class CalcReplaceLocalModuleCommand(wx.Command):
|
||||
eos.db.flush()
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, newMod)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -73,12 +70,10 @@ class CalcReplaceLocalModuleCommand(wx.Command):
|
||||
# Remove if there was no module
|
||||
if self.oldModInfo is None:
|
||||
from .localRemove import CalcRemoveLocalModulesCommand
|
||||
cmd = CalcRemoveLocalModulesCommand(fitID=self.fitID, positions=[self.position], commit=False)
|
||||
cmd = CalcRemoveLocalModulesCommand(fitID=self.fitID, positions=[self.position])
|
||||
if not cmd.Do():
|
||||
return False
|
||||
restoreCheckedStates(fit, self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
# Replace if there was
|
||||
oldMod = self.oldModInfo.toModule()
|
||||
@@ -91,6 +86,4 @@ class CalcReplaceLocalModuleCommand(wx.Command):
|
||||
self.Do()
|
||||
return False
|
||||
restoreCheckedStates(fit, self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -36,14 +35,11 @@ class CalcSwapLocalModuleCommand(wx.Command):
|
||||
if len(fit.modules) <= position2 or fit.modules[position2] is not mod1:
|
||||
fit.modules.replace(position1, mod1)
|
||||
fit.modules.replace(position2, mod2)
|
||||
eos.db.commit()
|
||||
return False
|
||||
fit.modules.replace(position1, mod2)
|
||||
if len(fit.modules) <= position1 or fit.modules[position1] is not mod2:
|
||||
fit.modules.free(position2)
|
||||
fit.modules.replace(position1, mod1)
|
||||
fit.modules.replace(position2, mod2)
|
||||
eos.db.commit()
|
||||
return False
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -12,13 +12,12 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddProjectedModuleCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, modInfo, position=None, ignoreRestrictions=False, commit=True):
|
||||
def __init__(self, fitID, modInfo, position=None, ignoreRestrictions=False):
|
||||
wx.Command.__init__(self, True)
|
||||
self.fitID = fitID
|
||||
self.newModInfo = modInfo
|
||||
self.newPosition = position
|
||||
self.ignoreRestrictions = ignoreRestrictions
|
||||
self.commit = commit
|
||||
self.oldModInfo = None
|
||||
self.oldPosition = None
|
||||
self.savedStateCheckChanges = None
|
||||
@@ -40,14 +39,10 @@ class CalcAddProjectedModuleCommand(wx.Command):
|
||||
if self.newPosition is not None:
|
||||
fit.projectedModules.insert(self.newPosition, newMod)
|
||||
if newMod not in fit.projectedModules:
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
else:
|
||||
fit.projectedModules.append(newMod)
|
||||
if newMod not in fit.projectedModules:
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return False
|
||||
self.newPosition = fit.projectedModules.index(newMod)
|
||||
|
||||
@@ -56,8 +51,6 @@ class CalcAddProjectedModuleCommand(wx.Command):
|
||||
eos.db.flush()
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, newMod)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -67,22 +60,16 @@ class CalcAddProjectedModuleCommand(wx.Command):
|
||||
fitID=self.fitID,
|
||||
modInfo=self.oldModInfo,
|
||||
position=self.oldPosition,
|
||||
ignoreRestrictions=True,
|
||||
commit=False)
|
||||
ignoreRestrictions=True)
|
||||
if not cmd.Do():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
from .projectedRemove import CalcRemoveProjectedModuleCommand
|
||||
cmd = CalcRemoveProjectedModuleCommand(
|
||||
fitID=self.fitID,
|
||||
position=self.newPosition,
|
||||
commit=False)
|
||||
position=self.newPosition)
|
||||
if not cmd.Do():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from eos.const import FittingModuleState
|
||||
from eos.saveddata.module import Module
|
||||
from gui.fitCommands.helpers import restoreCheckedStates
|
||||
@@ -19,12 +18,11 @@ STATE_MAP = {
|
||||
|
||||
class CalcChangeProjectedModuleStatesCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, positions, proposedState, commit=True):
|
||||
def __init__(self, fitID, positions, proposedState):
|
||||
wx.Command.__init__(self, True, 'Change Projected Module States')
|
||||
self.fitID = fitID
|
||||
self.positions = positions
|
||||
self.proposedState = STATE_MAP[proposedState]
|
||||
self.commit = commit
|
||||
self.savedStates = {}
|
||||
self.savedStateCheckChanges = None
|
||||
|
||||
@@ -47,8 +45,6 @@ class CalcChangeProjectedModuleStatesCommand(wx.Command):
|
||||
return False
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, None)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -60,6 +56,4 @@ class CalcChangeProjectedModuleStatesCommand(wx.Command):
|
||||
pyfalog.debug('Reverting projected {} to state {} for fit ID {}'.format(mod, state, self.fitID))
|
||||
mod.state = state
|
||||
restoreCheckedStates(fit, self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -11,11 +11,10 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveProjectedModuleCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, position, commit=True):
|
||||
def __init__(self, fitID, position):
|
||||
wx.Command.__init__(self, True)
|
||||
self.fitID = fitID
|
||||
self.position = position
|
||||
self.commit = commit
|
||||
self.savedModInfo = None
|
||||
self.savedStateCheckChanges = None
|
||||
|
||||
@@ -32,8 +31,6 @@ class CalcRemoveProjectedModuleCommand(wx.Command):
|
||||
eos.db.flush()
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, None)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -43,11 +40,8 @@ class CalcRemoveProjectedModuleCommand(wx.Command):
|
||||
fitID=self.fitID,
|
||||
modInfo=self.savedModInfo,
|
||||
position=self.position,
|
||||
ignoreRestrictions=True,
|
||||
commit=False)
|
||||
ignoreRestrictions=True)
|
||||
if not cmd.Do():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -11,13 +11,12 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcAddProjectedFitCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, projectedFitID, amount, state=None, commit=True):
|
||||
def __init__(self, fitID, projectedFitID, amount, state=None):
|
||||
wx.Command.__init__(self, True, 'Add Projected Fit')
|
||||
self.fitID = fitID
|
||||
self.projectedFitID = projectedFitID
|
||||
self.amount = amount
|
||||
self.state = state
|
||||
self.commit = commit
|
||||
self.changeAmountCommand = None
|
||||
self.savedStateCheckChanges = None
|
||||
|
||||
@@ -40,14 +39,11 @@ class CalcAddProjectedFitCommand(wx.Command):
|
||||
fitID=self.fitID,
|
||||
projectedFitID=self.projectedFitID,
|
||||
amount=self.amount,
|
||||
relative=True,
|
||||
commit=False)
|
||||
relative=True)
|
||||
if not self.changeAmountCommand.Do():
|
||||
return False
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, None)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
else:
|
||||
self.changeAmountCommand = None
|
||||
@@ -70,8 +66,6 @@ class CalcAddProjectedFitCommand(wx.Command):
|
||||
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, None)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -80,8 +74,6 @@ class CalcAddProjectedFitCommand(wx.Command):
|
||||
if not self.changeAmountCommand.Undo():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
# Can't find the projected fit, it must have been deleted. Just skip, as deleted fit
|
||||
# means that someone else just did exactly what we wanted to do
|
||||
@@ -91,11 +83,8 @@ class CalcAddProjectedFitCommand(wx.Command):
|
||||
cmd = CalcRemoveProjectedFitCommand(
|
||||
fitID=self.fitID,
|
||||
projectedFitID=self.projectedFitID,
|
||||
amount=self.amount,
|
||||
commit=False)
|
||||
amount=self.amount)
|
||||
if not cmd.Do():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from service.fit import Fit
|
||||
|
||||
|
||||
@@ -10,13 +9,12 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcChangeProjectedFitAmountCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, projectedFitID, amount, relative=False, commit=True):
|
||||
def __init__(self, fitID, projectedFitID, amount, relative=False):
|
||||
wx.Command.__init__(self, True, 'Change Projected Fit Amount')
|
||||
self.fitID = fitID
|
||||
self.projectedFitID = projectedFitID
|
||||
self.amount = amount
|
||||
self.relative = relative
|
||||
self.commit = commit
|
||||
self.savedAmount = None
|
||||
|
||||
def Do(self):
|
||||
@@ -40,8 +38,6 @@ class CalcChangeProjectedFitAmountCommand(wx.Command):
|
||||
if confinedAmount == self.savedAmount:
|
||||
return False
|
||||
projectionInfo.amount = confinedAmount
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -49,6 +45,5 @@ class CalcChangeProjectedFitAmountCommand(wx.Command):
|
||||
cmd = CalcChangeProjectedFitAmountCommand(
|
||||
fitID=self.fitID,
|
||||
projectedFitID=self.projectedFitID,
|
||||
amount=self.savedAmount,
|
||||
commit=self.commit)
|
||||
amount=self.savedAmount)
|
||||
return cmd.Do()
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import restoreCheckedStates
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -11,12 +10,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcChangeProjectedFitStateCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, projectedFitID, state, commit=True):
|
||||
def __init__(self, fitID, projectedFitID, state):
|
||||
wx.Command.__init__(self, True, 'Change Projected Fit State')
|
||||
self.fitID = fitID
|
||||
self.projectedFitID = projectedFitID
|
||||
self.state = state
|
||||
self.commit = commit
|
||||
self.savedState = None
|
||||
self.savedStateCheckChanges = None
|
||||
|
||||
@@ -43,8 +41,6 @@ class CalcChangeProjectedFitStateCommand(wx.Command):
|
||||
fit = sFit.getFit(self.fitID)
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, None)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -53,11 +49,8 @@ class CalcChangeProjectedFitStateCommand(wx.Command):
|
||||
cmd = CalcChangeProjectedFitStateCommand(
|
||||
fitID=self.fitID,
|
||||
projectedFitID=self.projectedFitID,
|
||||
state=self.savedState,
|
||||
commit=False)
|
||||
state=self.savedState)
|
||||
if not cmd.Do():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from gui.fitCommands.helpers import restoreCheckedStates
|
||||
from service.fit import Fit
|
||||
|
||||
@@ -11,12 +10,11 @@ pyfalog = Logger(__name__)
|
||||
|
||||
class CalcRemoveProjectedFitCommand(wx.Command):
|
||||
|
||||
def __init__(self, fitID, projectedFitID, amount, commit=True):
|
||||
def __init__(self, fitID, projectedFitID, amount):
|
||||
wx.Command.__init__(self, True, 'Add Projected Fit')
|
||||
self.fitID = fitID
|
||||
self.projectedFitID = projectedFitID
|
||||
self.amount = amount
|
||||
self.commit = commit
|
||||
self.savedState = None
|
||||
self.savedAmount = None
|
||||
self.changeAmountCommand = None
|
||||
@@ -48,14 +46,11 @@ class CalcRemoveProjectedFitCommand(wx.Command):
|
||||
self.changeAmountCommand = CalcChangeProjectedFitAmountCommand(
|
||||
fitID=self.fitID,
|
||||
projectedFitID=self.projectedFitID,
|
||||
amount=remainingAmount,
|
||||
commit=False)
|
||||
amount=remainingAmount)
|
||||
if not self.changeAmountCommand.Do():
|
||||
return False
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, None)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
else:
|
||||
self.changeAmountCommand = None
|
||||
@@ -65,8 +60,6 @@ class CalcRemoveProjectedFitCommand(wx.Command):
|
||||
del fit.projectedFitDict[projectedFit.ID]
|
||||
sFit.recalc(fit)
|
||||
self.savedStateCheckChanges = sFit.checkStates(fit, None)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
@@ -75,19 +68,14 @@ class CalcRemoveProjectedFitCommand(wx.Command):
|
||||
if not self.changeAmountCommand.Undo():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
from .add import CalcAddProjectedFitCommand
|
||||
cmd = CalcAddProjectedFitCommand(
|
||||
fitID=self.fitID,
|
||||
projectedFitID=self.projectedFitID,
|
||||
amount=self.savedAmount,
|
||||
state=self.savedState,
|
||||
commit=False)
|
||||
state=self.savedState)
|
||||
if not cmd.Do():
|
||||
return False
|
||||
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
|
||||
if self.commit:
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import wx
|
||||
from logbook import Logger
|
||||
|
||||
import eos.db
|
||||
from eos.saveddata.mode import Mode
|
||||
from service.fit import Fit
|
||||
from service.market import Market
|
||||
@@ -25,7 +24,6 @@ class CalcChangeShipModeCommand(wx.Command):
|
||||
item = Market.getInstance().getItem(self.itemID)
|
||||
mode = Mode(item)
|
||||
fit.mode = mode
|
||||
eos.db.commit()
|
||||
return True
|
||||
|
||||
def Undo(self):
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user