Compare commits

...

68 Commits

Author SHA1 Message Date
DarkPhoenix
adf750fe44 Adjust VNI effects 2019-07-27 12:32:56 +03:00
DarkPhoenix
250996e8ac Update icons 2019-07-27 08:58:27 +03:00
DarkPhoenix
56639a0812 Update database to 1541099 2019-07-27 08:50:47 +03:00
DarkPhoenix
7cf6ff04b6 Comment out target list as it caused graphical issues on windows 2019-05-28 17:47:27 +03:00
DarkPhoenix
5b575fdfe3 Make sure panel has no padding to avoid ugly border on Windows 2019-05-28 17:30:50 +03:00
DarkPhoenix
a8a5fabce7 Always add last data point to dps over time graph 2019-05-28 16:33:30 +03:00
DarkPhoenix
f41d6dd2c1 Update database to 1514398 2019-05-28 16:15:29 +03:00
DarkPhoenix
09727c102a Bump pyfa version 2019-05-28 16:06:40 +03:00
DarkPhoenix
6580734dc7 Print full connection exception in case of failure in debug mode 2019-05-28 16:03:25 +03:00
DarkPhoenix
ff34865067 Add target panel as dark code 2019-05-28 15:05:16 +03:00
DarkPhoenix
bdd400fd51 Remove conflicting shortcut 2019-05-27 19:07:58 +03:00
DarkPhoenix
1e8184a80b Make ESI browser tree panel non-scalable 2019-05-27 19:06:53 +03:00
DarkPhoenix
6a20f04c7f Merge branch 'master' into singularity 2019-05-27 19:04:27 +03:00
Anton Vorobyov
d81acc1f9c Merge pull request #1987 from AaronOpfer/esi_import_sizing
improve sizing on esi fit import browser
2019-05-27 19:03:59 +03:00
DarkPhoenix
bc84c20cb2 Update database with actual contents before and after fill, also do it in UI commands 2019-05-27 15:35:14 +03:00
DarkPhoenix
d5c5e2698e Redraw only after some delay (reuse market search delay for that) 2019-05-27 13:46:40 +03:00
Anton Vorobyov
16a78e689e Merge pull request #1988 from MaruMaruOO/master
Updates EFS exports to support local repairs, cap  warfare and ammo switching.
2019-05-27 10:32:49 +03:00
MaruMaruOO
066f29660d Added repair and cap data to EFS exports. 2019-05-27 02:18:10 -04:00
Aaron Opfer
bba0df5f50 improve sizing on esi fit import browser
On my machine, using the ESI import feature and clicking "Fetch Fits" gives the appearance of nothing happening. Turns out, this was because by default the tree on the left-hand side of the window has zero width by default and the parent window needs to be resized to see the fits. Fix this by setting a minimum size for the fitting browser tree and increase the default window size to compensate.
2019-05-26 04:33:15 -05:00
DarkPhoenix
45452ca680 Add rename mappings for faction trig guns 2019-05-25 22:04:17 +03:00
DarkPhoenix
4fbbc18f9f Accept mix of localized hints and regular names in XML importer 2019-05-25 17:43:47 +03:00
DarkPhoenix
22ec280ec2 Fix showing of neut resistance 2019-05-24 23:17:02 +03:00
DarkPhoenix
89c06b5201 Rescale contents on graph switch 2019-05-24 13:35:45 +03:00
DarkPhoenix
86d5f72988 Normalize drone tracking for Misc column 2019-05-23 15:49:49 +03:00
MaruMaruOO
c3e055a4c9 Merge branch 'master' of https://github.com/pyfa-org/Pyfa 2019-05-22 02:55:46 -04:00
MaruMaruOO
e48631956d Add typeIDs for cargo to EFS exports. 2019-05-22 02:35:47 -04:00
DarkPhoenix
2964f3b009 Do not recreate checkbox on each graphical switch
Leads to weird graphical glitches on GTK
2019-05-21 22:09:08 +03:00
DarkPhoenix
527c66dca4 Change the way radio buttons look 2019-05-21 21:29:26 +03:00
DarkPhoenix
24909f0523 Extend allowable range a little so that first reload of triglavians is included 2019-05-21 21:11:09 +03:00
DarkPhoenix
ed7494b3a4 Implement graph type selection 2019-05-21 19:47:55 +03:00
DarkPhoenix
8fae275e5a Cache graph values on GUI graphs so they do not get recalculated when graph options are changed 2019-05-21 19:06:11 +03:00
DarkPhoenix
a09a2a5f4b Add option whether 0 value should be shown or not on graphs 2019-05-21 17:51:50 +03:00
DarkPhoenix
2adc150811 Limit dmg and dps over time graphs to not hog resources on weaker machines for too long 2019-05-21 14:37:35 +03:00
DarkPhoenix
f5cad33b6c Some layout changes 2019-05-20 12:22:44 +03:00
DarkPhoenix
338cf45f65 Include "high" endpoint for damage over time graph 2019-05-20 10:41:26 +03:00
DarkPhoenix
359c60bafb Increase graph size and add some padding 2019-05-20 10:32:40 +03:00
DarkPhoenix
f808b73a5d Add axis labels 2019-05-20 07:56:04 +03:00
DarkPhoenix
8dd87cde58 When fit is removed, update projected/command contents if needed 2019-05-19 21:53:44 +03:00
DarkPhoenix
1ec78d9beb Remove fit from graph window when it gets deleted 2019-05-19 21:29:43 +03:00
DarkPhoenix
9c710285f2 Do not cycle over mods which are not dealing damage when composing cache 2019-05-19 21:04:41 +03:00
DarkPhoenix
90f745a18f Refresh cache only for changed fits rather than every fit 2019-05-19 20:54:12 +03:00
DarkPhoenix
af446579ab Get clean subwarp speed (no cloaks, propmods, webs etc) 2019-05-19 20:38:56 +03:00
DarkPhoenix
bcc11bd172 Reorder fields in graph 2019-05-19 14:11:05 +03:00
DarkPhoenix
0c31f756a8 Restore DPS vs range graph 2019-05-19 14:02:24 +03:00
DarkPhoenix
16fdd5a5e6 Fix warp graph 2019-05-19 04:07:40 +03:00
DarkPhoenix
ec1a2c66ee Restore shield graphs 2019-05-18 22:52:59 +03:00
DarkPhoenix
c3f41d68e6 Round in getYforX as well 2019-05-18 11:19:08 +03:00
DarkPhoenix
2f8701b4b2 Rework plot point processing for dmg over time graph the same way 2019-05-18 11:15:27 +03:00
DarkPhoenix
9b2d5410d6 Fix dps over time graph 2019-05-18 11:03:12 +03:00
Anton Vorobyov
1d8c9d2c40 Merge pull request #1977 from jtaylormayfield/master
Applied implant and booster skill check
2019-05-18 01:04:05 +03:00
J. Taylor Mayfield
8c0817245f Include skill prerequisites for applied implants and boosters in fit skill check. 2019-05-17 15:27:17 -05:00
DarkPhoenix
2a04e60ae0 Restore functionality of dmg vs time graph 2019-05-17 18:44:52 +03:00
DarkPhoenix
fb5eb220fd Rework graph interfaces again 2019-05-17 17:48:20 +03:00
DarkPhoenix
512f48ebdd Force frame refresh on graph redraw 2019-05-17 16:02:43 +03:00
DarkPhoenix
09db7d26a7 Rework mobility vs time graph 2019-05-17 15:38:06 +03:00
DarkPhoenix
690cf5eca1 Rework cap regen graph to use new interfaces 2019-05-17 15:11:52 +03:00
DarkPhoenix
1aee4c59c4 Merge branch 'singularity' of github.com:pyfa-org/Pyfa into singularity 2019-05-17 14:49:13 +03:00
DarkPhoenix
f1384074b5 Rework internal graph interfaces 2019-05-17 14:48:42 +03:00
DarkPhoenix
203bed06d6 Do not consider previous item heights when setting new item height 2019-05-16 22:13:01 +03:00
DarkPhoenix
0b00e28863 Fix #1974 2019-05-15 01:15:41 +03:00
DarkPhoenix
d74d331642 Merge branch 'singularity' of github.com:pyfa-org/Pyfa into singularity 2019-05-15 00:52:23 +03:00
DarkPhoenix
f075fbdc63 Do not show abyssal items in variations menu 2019-05-15 00:52:04 +03:00
DarkPhoenix
d59b6696ca Remove links to unmaintained packages 2019-05-14 14:22:09 +03:00
Anton Vorobyov
eedf6f9a39 Merge pull request #1973 from ZeroPointEnergy/pyfa_gentoo_overlay
Add link to Gentoo pyfa overlay
2019-05-14 14:19:07 +03:00
DarkPhoenix
1cca5729fc Add cap delta to tooltip on capacitor view 2019-05-14 14:15:58 +03:00
Andreas Zuber
a7b01ece22 Add link to Gentoo pyfa overlay 2019-05-14 13:08:47 +02:00
DarkPhoenix
d17e6d08d8 Fix definite integral calculation for distance traveled graph 2019-05-13 10:03:19 +03:00
DarkPhoenix
b29aaa9e20 Show ship name in legend as well (short, if needed) 2019-05-13 09:27:25 +03:00
617 changed files with 1999 additions and 1969 deletions

View File

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

View File

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

View File

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

View File

@@ -17,107 +17,60 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
import itertools
import math
from abc import ABCMeta, abstractmethod
class Graph:
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:
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:
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:
class SmoothGraph(Graph, metaclass=ABCMeta):
def __init__(self, string, step):
start, end = string.split("-")
self.start = float(start)
self.end = float(end)
self.step = step
def __iter__(self):
current = start = self.start
end = self.end
step = self.step or (end - start) / 200
i = 0
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

View File

@@ -1,24 +0,0 @@
import math
from logbook import Logger
from eos.graph import Graph
pyfalog = Logger(__name__)
class FitCapAmountTimeGraph(Graph):
defaults = {"time": 0}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcAmount, data if data is not None else self.defaults)
self.fit = fit
def calcAmount(self, data):
time = data["time"]
maxCap = self.fit.ship.getModifiedItemAttr('capacitorCapacity')
regenTime = self.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

View 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

View File

@@ -1,25 +0,0 @@
import math
from logbook import Logger
from eos.graph import Graph
pyfalog = Logger(__name__)
class FitCapRegenAmountGraph(Graph):
defaults = {"percentage": '0-100'}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcRegen, data if data is not None else self.defaults)
self.fit = fit
def calcRegen(self, data):
perc = data['percentage']
maxCap = self.fit.ship.getModifiedItemAttr('capacitorCapacity')
regenTime = self.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

View 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

View File

@@ -1,26 +0,0 @@
import math
from logbook import Logger
from eos.graph import Graph
pyfalog = Logger(__name__)
class FitDistanceTimeGraph(Graph):
defaults = {"time": 0}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcDistance, data if data is not None else self.defaults)
self.fit = fit
def calcDistance(self, data):
time = data["time"]
maxSpeed = self.fit.ship.getModifiedItemAttr('maxVelocity')
mass = self.fit.ship.getModifiedItemAttr('mass')
agility = self.fit.ship.getModifiedItemAttr('agility')
# Definite integral of:
# https://wiki.eveuniversity.org/Acceleration#Mathematics_and_formulae
distance = maxSpeed * time + (maxSpeed * agility * mass * math.exp((-time * 1000000) / (agility * mass)) / 1000000)
return distance

View 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

View File

@@ -17,50 +17,90 @@
# 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
from gui.utils.numberFormatter import roundToPrec
pyfalog = Logger(__name__)
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
class FitDmgTimeGraph(Graph):
defaults = {"time": 0}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcDmg, data if data is not None else self.defaults)
self.fit = fit
self.__cache = {}
def calcDmg(self, data):
time = data["time"] * 1000
closestTime = max((t for t in self.__cache if t <= time), default=None)
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 self.__cache[closestTime]
return roundToPrec(cache[closestTime], 6)
def recalc(self):
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 self.__cache:
prevTime = max((t for t in self.__cache if t < addedTime), default=None)
if addedTime not in cache:
prevTime = max((t for t in cache if t < addedTime), default=None)
if prevTime is None:
self.__cache[addedTime] = 0
cache[addedTime] = 0
else:
self.__cache[addedTime] = self.__cache[prevTime]
for time in (t for t in self.__cache if t >= addedTime):
self.__cache[time] += addedDmg
cache[addedTime] = cache[prevTime]
for time in (t for t in cache if t >= addedTime):
cache[time] += addedDmg
self.__cache.clear()
fit = self.fit
# We'll handle calculations in milliseconds
maxTime = self.data["time"].data[0].end * 1000
maxTime = maxTime * 1000
for mod in fit.modules:
if not mod.isDealingDamage():
continue
cycleParams = mod.getCycleParameters(reloadOverride=True)
if cycleParams is None:
continue
@@ -69,17 +109,17 @@ class FitDmgTimeGraph(Graph):
for cycleTime, inactiveTime in cycleParams.iterCycles():
volleyParams = mod.getVolleyParameters(spoolOptions=SpoolOptions(SpoolType.CYCLES, nonstopCycles, True))
for volleyTime, volley in volleyParams.items():
if currentTime + volleyTime <= maxTime and volleyTime <= cycleTime:
addDmg(currentTime + volleyTime, volley.total)
currentTime += cycleTime
currentTime += inactiveTime
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
@@ -87,13 +127,13 @@ class FitDmgTimeGraph(Graph):
volleyParams = drone.getVolleyParameters()
for cycleTime, inactiveTime in cycleParams.iterCycles():
for volleyTime, volley in volleyParams.items():
if currentTime + volleyTime <= maxTime and volleyTime <= cycleTime:
addDmg(currentTime + volleyTime, volley.total)
currentTime += cycleTime
currentTime += inactiveTime
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
@@ -105,9 +145,7 @@ class FitDmgTimeGraph(Graph):
abilityVolleyParams = volleyParams[effectID]
for cycleTime, inactiveTime in abilityCycleParams.iterCycles():
for volleyTime, volley in abilityVolleyParams.items():
if currentTime + volleyTime <= maxTime and volleyTime <= cycleTime:
addDmg(currentTime + volleyTime, volley.total)
currentTime += cycleTime
currentTime += inactiveTime
addDmg(currentTime + volleyTime, volley.total)
if currentTime > maxTime:
break
currentTime += cycleTime + inactiveTime

View File

@@ -17,80 +17,62 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
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,88 +85,79 @@ 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
return min(sigRadiusFactor, velocityFactor, 1)
def calculateTurretChanceToHit(self, mod, data):
distance = data["distance"] * 1000
tracking = mod.getModifiedItemAttr("trackingSpeed")
@staticmethod
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"]
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 + self.fit.ship.getModifiedItemAttr('radius', 0)
angDistance = distance + fit.ship.getModifiedItemAttr('radius', 0)
if angDistance == 0 and transversal == 0:
angularVelocity = 0
elif angDistance == 0 and transversal != 0:
@@ -192,18 +165,30 @@ class FitDpsRangeGraph(Graph):
else:
angularVelocity = transversal / angDistance
trackingEq = (((angularVelocity / tracking) *
(turretSigRes / targetSigRad)) ** 2)
(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

View File

@@ -17,43 +17,90 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from logbook import Logger
from itertools import chain
from eos.graph import Graph
from eos.utils.spoolSupport import SpoolType, SpoolOptions
from gui.utils.numberFormatter import roundToPrec
pyfalog = Logger(__name__)
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
class FitDpsTimeGraph(Graph):
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)
defaults = {"time": 0}
def _getXLimits(self, fit, extraData):
return 0, 2500
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcDps, data if data is not None else self.defaults)
self.fit = fit
self.__cache = []
def calcDps(self, data):
time = data["time"] * 1000
entries = (e for e in self.__cache if e[0] <= time < e[1])
dps = sum(e[2] for e in entries)
return dps
def recalc(self):
def __generateCache(self, fit, maxTime):
cache = []
def addDmg(addedTimeStart, addedTimeFinish, addedDmg):
if addedDmg == 0:
return
addedDps = 1000 * addedDmg / (addedTimeFinish - addedTimeStart)
self.__cache.append((addedTimeStart, addedTimeFinish, addedDps))
cache.append((addedTimeStart, addedTimeFinish, addedDps))
self.__cache = []
fit = self.fit
# We'll handle calculations in milliseconds
maxTime = self.data["time"].data[0].end * 1000
maxTime = maxTime * 1000
for mod in fit.modules:
if not mod.isDealingDamage():
continue
cycleParams = mod.getCycleParameters(reloadOverride=True)
if cycleParams is None:
continue
@@ -63,11 +110,9 @@ class FitDpsTimeGraph(Graph):
cycleDamage = 0
volleyParams = mod.getVolleyParameters(spoolOptions=SpoolOptions(SpoolType.CYCLES, nonstopCycles, True))
for volleyTime, volley in volleyParams.items():
if currentTime + volleyTime <= maxTime and volleyTime <= cycleTime:
cycleDamage += volley.total
cycleDamage += volley.total
addDmg(currentTime, currentTime + cycleTime, cycleDamage)
currentTime += cycleTime
currentTime += inactiveTime
currentTime += cycleTime + inactiveTime
if inactiveTime > 0:
nonstopCycles = 0
else:
@@ -75,6 +120,8 @@ class FitDpsTimeGraph(Graph):
if currentTime > maxTime:
break
for drone in fit.drones:
if not drone.isDealingDamage():
continue
cycleParams = drone.getCycleParameters(reloadOverride=True)
if cycleParams is None:
continue
@@ -83,14 +130,14 @@ class FitDpsTimeGraph(Graph):
cycleDamage = 0
volleyParams = drone.getVolleyParameters()
for volleyTime, volley in volleyParams.items():
if currentTime + volleyTime <= maxTime and volleyTime <= cycleTime:
cycleDamage += volley.total
cycleDamage += volley.total
addDmg(currentTime, currentTime + cycleTime, cycleDamage)
currentTime += cycleTime
currentTime += inactiveTime
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
@@ -103,10 +150,16 @@ class FitDpsTimeGraph(Graph):
for cycleTime, inactiveTime in abilityCycleParams.iterCycles():
cycleDamage = 0
for volleyTime, volley in abilityVolleyParams.items():
if currentTime + volleyTime <= maxTime and volleyTime <= cycleTime:
cycleDamage += volley.total
cycleDamage += volley.total
addDmg(currentTime, currentTime + cycleTime, cycleDamage)
currentTime += cycleTime
currentTime += inactiveTime
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

View File

@@ -1,29 +0,0 @@
import math
from logbook import Logger
from eos.graph import Graph
pyfalog = Logger(__name__)
class FitShieldAmountTimeGraph(Graph):
defaults = {"time": 0}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcAmount, data if data is not None else self.defaults)
self.fit = fit
import gui.mainFrame
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def calcAmount(self, data):
time = data["time"]
maxShield = self.fit.ship.getModifiedItemAttr('shieldCapacity')
regenTime = self.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 self.fit.damagePattern is not None and useEhp:
shield = self.fit.damagePattern.effectivify(self.fit, shield, 'shield')
return shield

View 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

View File

@@ -1,49 +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/>.
# ===============================================================================
import math
from logbook import Logger
from eos.graph import Graph
pyfalog = Logger(__name__)
class FitShieldRegenAmountGraph(Graph):
defaults = {"percentage": '0-100'}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcRegen, data if data is not None else self.defaults)
self.fit = fit
import gui.mainFrame
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def calcRegen(self, data):
perc = data["percentage"]
maxShield = self.fit.ship.getModifiedItemAttr('shieldCapacity')
regenTime = self.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 self.fit.damagePattern is not None and useEhp:
regen = self.fit.damagePattern.effectivify(self.fit, regen, 'shield')
return regen

View 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

View File

@@ -1,25 +0,0 @@
import math
from logbook import Logger
from eos.graph import Graph
pyfalog = Logger(__name__)
class FitSpeedTimeGraph(Graph):
defaults = {"time": 0}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcSpeed, data if data is not None else self.defaults)
self.fit = fit
def calcSpeed(self, data):
time = data["time"]
maxSpeed = self.fit.ship.getModifiedItemAttr('maxVelocity')
mass = self.fit.ship.getModifiedItemAttr('mass')
agility = self.fit.ship.getModifiedItemAttr('agility')
# https://wiki.eveuniversity.org/Acceleration#Mathematics_and_formulae
speed = maxSpeed * (1 - math.exp((-time * 1000000) / (agility * mass)))
return speed

View 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

View File

@@ -1,61 +0,0 @@
import math
from logbook import Logger
from eos.graph import Graph
pyfalog = Logger(__name__)
AU_METERS = 149597870700
class FitWarpTimeDistanceGraph(Graph):
defaults = {"distance": 0}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcTime, data if data is not None else self.defaults)
self.fit = fit
def calcTime(self, data):
distance = data["distance"]
if distance == 0:
return 0
maxWarpDistance = self.fit.maxWarpDistance
if distance > maxWarpDistance:
return None
maxSubwarpSpeed = self.fit.ship.getModifiedItemAttr('maxVelocity')
maxWarpSpeed = self.fit.warpSpeed
time = calculate_time_in_warp(maxWarpSpeed, maxSubwarpSpeed, distance * AU_METERS)
return time
# 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

View 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

View File

@@ -131,6 +131,13 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def hasAmmo(self):
return self.charge is not 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 {0: DmgTypes(0, 0, 0, 0)}

View File

@@ -175,6 +175,14 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def hasAmmo(self):
return self.charge is not 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 {}

View File

@@ -414,6 +414,13 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
return self.__miningyield
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 {0: DmgTypes(0, 0, 0, 0)}

BIN
eve.db

Binary file not shown.

View File

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

View File

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

View File

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

View File

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

View File

@@ -1,13 +1,11 @@
# noinspection PyUnresolvedReferences
from gui.builtinGraphs import ( # noqa: E402,F401
fitDpsRange,
fitDpsTime,
fitDmgTime,
fitShieldRegenAmount,
fitShieldAmountTime,
fitCapRegenAmount,
fitCapAmountTime,
fitSpeedTime,
fitDistanceTime,
fitWarpTimeDistance
fitDpsVsRange,
fitDmgVsTime,
fitShieldRegenVsShieldPerc,
fitShieldAmountVsTime,
fitCapRegenVsCapPerc,
fitCapAmountVsTime,
fitMobilityVsTime,
fitWarpTimeVsDistance
)

View File

@@ -1,81 +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.fitCapAmountTime import FitCapAmountTimeGraph as EosFitCapAmountTimeGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitCapAmountTimeGraph(Graph):
propertyLabelMap = {"time": "Time (seconds)"}
defaults = EosFitCapAmountTimeGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["time"] = "0-300"
self.name = "Cap Amount vs Time"
self.eosGraph = 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):
eosGraph = getattr(self, "eosGraph", None)
if eosGraph is None or eosGraph.fit != fit:
eosGraph = self.eosGraph = EosFitCapAmountTimeGraph(fit)
eosGraph.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"
eosGraph.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in eosGraph.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitCapAmountTimeGraph.register()

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

View File

@@ -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.fitCapRegenAmount import FitCapRegenAmountGraph as EosFitCapRegenAmountGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitCapRegenAmountGraph(Graph):
propertyLabelMap = {"percentage": "Cap Amount (percent)"}
defaults = EosFitCapRegenAmountGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["percentage"] = "0-100"
self.name = "Cap Regen vs Cap Amount"
self.eosGraph = 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('capacitorCapacity').iconID
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
return {"percentage": bitmap}
def getPoints(self, fit, fields):
eosGraph = getattr(self, "eosGraph", None)
if eosGraph is None or eosGraph.fit != fit:
eosGraph = self.eosGraph = EosFitCapRegenAmountGraph(fit)
eosGraph.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"
eosGraph.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in eosGraph.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitCapRegenAmountGraph.register()

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

View File

@@ -1,81 +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.fitDistanceTime import FitDistanceTimeGraph as EosFitDistanceTimeGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitDistanceTimeGraph(Graph):
propertyLabelMap = {"time": "Time (seconds)"}
defaults = EosFitDistanceTimeGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["time"] = "0-80"
self.name = "Distance Traveled vs Time"
self.eosGraph = 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):
eosGraph = getattr(self, "eosGraph", None)
if eosGraph is None or eosGraph.fit != fit:
eosGraph = self.eosGraph = EosFitDistanceTimeGraph(fit)
eosGraph.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"
eosGraph.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in eosGraph.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDistanceTimeGraph.register()

View File

@@ -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-80"
self.name = "Damage Inflicted vs Time"
self.eosGraph = 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):
eosGraph = getattr(self, "eosGraph", None)
if eosGraph is None or eosGraph.fit != fit:
eosGraph = self.eosGraph = EosFitDmgTimeGraph(fit)
eosGraph.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"
eosGraph.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
eosGraph.recalc()
for point, val in eosGraph.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDmgTimeGraph.register()

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

View File

@@ -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 vs Range"
self.eosGraph = 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):
eosGraph = getattr(self, "eosGraph", None)
if eosGraph is None or eosGraph.fit != fit:
eosGraph = self.eosGraph = EosFitDpsRangeGraph(fit)
eosGraph.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"
eosGraph.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in eosGraph.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDpsRangeGraph.register()

View File

@@ -1,83 +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-80"
self.name = "DPS vs Time"
self.eosGraph = 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):
eosGraph = getattr(self, "eosGraph", None)
if eosGraph is None or eosGraph.fit != fit:
eosGraph = self.eosGraph = EosFitDpsTimeGraph(fit)
eosGraph.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"
eosGraph.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
eosGraph.recalc()
for point, val in eosGraph.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDpsTimeGraph.register()

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

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

View File

@@ -1,85 +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.fitShieldAmountTime import FitShieldAmountTimeGraph as EosFitShieldAmountTimeGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitShieldAmountTimeGraph(Graph):
propertyLabelMap = {"time": "Time (seconds)"}
defaults = EosFitShieldAmountTimeGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["time"] = "0-300"
self.name = "Shield Amount vs Time"
self.eosGraph = 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):
eosGraph = getattr(self, "eosGraph", None)
if eosGraph is None or eosGraph.fit != fit:
eosGraph = self.eosGraph = EosFitShieldAmountTimeGraph(fit)
eosGraph.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"
eosGraph.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in eosGraph.getIterator():
x.append(point[variable])
y.append(val)
return x, y
@property
def redrawOnEffectiveChange(self):
return True
FitShieldAmountTimeGraph.register()

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

View File

@@ -1,86 +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.fitShieldRegenAmount import FitShieldRegenAmountGraph as EosFitShieldRegenAmountGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitShieldRegenAmountGraph(Graph):
propertyLabelMap = {"percentage": "Shield Capacity (percent)"}
defaults = EosFitShieldRegenAmountGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["percentage"] = "0-100"
self.name = "Shield Regen vs Shield Amount"
self.eosGraph = 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('shieldCapacity').iconID
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
return {"percentage": bitmap}
def getPoints(self, fit, fields):
eosGraph = getattr(self, "eosGraph", None)
if eosGraph is None or eosGraph.fit != fit:
eosGraph = self.eosGraph = EosFitShieldRegenAmountGraph(fit)
eosGraph.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"
eosGraph.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in eosGraph.getIterator():
x.append(point[variable])
y.append(val)
return x, y
@property
def redrawOnEffectiveChange(self):
return True
FitShieldRegenAmountGraph.register()

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

View File

@@ -1,81 +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.fitSpeedTime import FitSpeedTimeGraph as EosFitSpeedTimeGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitSpeedTimeGraph(Graph):
propertyLabelMap = {"time": "Time (seconds)"}
defaults = EosFitSpeedTimeGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["time"] = "0-80"
self.name = "Speed vs Time"
self.eosGraph = 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):
eosGraph = getattr(self, "eosGraph", None)
if eosGraph is None or eosGraph.fit != fit:
eosGraph = self.eosGraph = EosFitSpeedTimeGraph(fit)
eosGraph.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"
eosGraph.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in eosGraph.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitSpeedTimeGraph.register()

View File

@@ -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.fitWarpTimeDistance import FitWarpTimeDistanceGraph as EosFitWarpTimeDistanceGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitWarpTimeDistanceGraph(Graph):
propertyLabelMap = {"distance": "Distance (AU)"}
defaults = EosFitWarpTimeDistanceGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["distance"] = "0-50"
self.name = "Warp Time vs Distance"
self.eosGraph = 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('maxRange').iconID
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
return {"distance": bitmap}
def getPoints(self, fit, fields):
eosGraph = getattr(self, "eosGraph", None)
if eosGraph is None or eosGraph.fit != fit:
eosGraph = self.eosGraph = EosFitWarpTimeDistanceGraph(fit)
eosGraph.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"
eosGraph.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in eosGraph.getIterator():
if val is not None:
x.append(point[variable])
y.append(val)
return x, y
FitWarpTimeDistanceGraph.register()

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

View File

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

View File

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

View File

@@ -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__)
@@ -379,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:

View File

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

View File

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

View File

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

View File

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

View File

@@ -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
@@ -876,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",

View File

@@ -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",

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -42,7 +42,6 @@ class CalcToggleLocalDroneStatesCommand(wx.Command):
if drone.amountActive == 0:
drone.amountActive = drone.amount
eos.db.commit()
return True
def Undo(self):

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More