Compare commits

..

97 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
DarkPhoenix
71ae59b2b5 Bump version 2019-05-13 06:48:35 +03:00
DarkPhoenix
51294f6cbc Change the way graphs are imported 2019-05-13 06:46:25 +03:00
DarkPhoenix
0439ace886 UK -> US spelling 2019-05-12 18:35:23 +03:00
DarkPhoenix
c85c735f9a Bump version 2019-05-12 18:04:40 +03:00
DarkPhoenix
c65b582497 Remove dot after "vs" 2019-05-12 18:01:44 +03:00
DarkPhoenix
7f2ac83e17 Add context menu which removes fits from graphs 2019-05-12 17:42:56 +03:00
DarkPhoenix
5ef2a40d1e Delete fits by pressing del key in graphs window 2019-05-12 17:32:17 +03:00
DarkPhoenix
5b52da737a Do not trigger esc when modifier keys are pressed 2019-05-12 17:08:41 +03:00
DarkPhoenix
51e8713cd6 Add warp time graph 2019-05-12 17:04:11 +03:00
DarkPhoenix
c9b60f2c65 Add distance vs time graph 2019-05-12 16:26:02 +03:00
DarkPhoenix
d777999af4 Add speed vs time graph 2019-05-12 15:46:50 +03:00
DarkPhoenix
74444d56c4 Add shield amount vs time graph 2019-05-12 15:30:41 +03:00
DarkPhoenix
a433c9638a Add cap-time graph 2019-05-12 14:59:19 +03:00
DarkPhoenix
672141cffc Add cap amount graph 2019-05-12 14:40:57 +03:00
DarkPhoenix
ac132cbb92 Add shield recharge graph 2019-05-12 14:32:57 +03:00
DarkPhoenix
d9535b08b1 Rename graphs 2019-05-12 12:28:47 +03:00
DarkPhoenix
d93544b3bc Fix DPS over time graph 2019-05-12 06:46:28 +03:00
DarkPhoenix
2320c3cb57 Make sure to include all Y-values 2019-05-12 05:54:03 +03:00
DarkPhoenix
bd5710c676 Calculate graph data only once 2019-05-12 05:30:49 +03:00
DarkPhoenix
49f1412d91 Fix bug with drones 2019-05-12 04:56:59 +03:00
DarkPhoenix
54eea7d702 Rework damage over time graph to show actual damage dealt per volley 2019-05-12 04:44:27 +03:00
DarkPhoenix
e26bcb2e5e Move DoT logic into volley parameter fetcher 2019-05-12 03:15:10 +03:00
DarkPhoenix
7305c0a017 Add optional parameter to cycle parameter getters 2019-05-12 02:55:42 +03:00
DarkPhoenix
7d37b9e0e0 Implement volley parameters for modules 2019-05-12 02:49:21 +03:00
DarkPhoenix
87f28db730 Implement volley parameters for drones and fighters 2019-05-12 02:38:36 +03:00
DarkPhoenix
56d9a8b626 Rework fighter calculations to use cycle parameters 2019-05-12 02:18:44 +03:00
DarkPhoenix
cb8f76c582 Implement module cycle parameters logic for modules 2019-05-11 17:34:01 +03:00
DarkPhoenix
af0b7b92c7 Implement cycle parameters for drones 2019-05-11 16:15:03 +03:00
DarkPhoenix
9418b7a709 Calculate 0 range data points 2019-05-11 14:53:59 +03:00
615 changed files with 2631 additions and 1337 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,105 +17,60 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
import itertools
import math
from abc import ABCMeta, abstractmethod
class Graph(object):
class Graph(metaclass=ABCMeta):
def __init__(self, fit, function, data=None):
self.fit = fit
self.data = {}
if data is not None:
for name, d in data.items():
self.setData(Data(name, d))
def __init__(self):
self._cache = {}
self.function = function
@abstractmethod
def getPlotPoints(self, fit, extraData, xRange, xAmount):
raise NotImplementedError
def clearData(self):
self.data.clear()
def getYForX(self, fit, extraData, x):
raise NotImplementedError
def setData(self, data):
self.data[data.name] = data
def getIterator(self):
pointNames = []
pointIterators = []
for data in self.data.values():
pointNames.append(data.name)
pointIterators.append(data)
return self._iterator(pointNames, pointIterators)
def _iterator(self, pointNames, pointIterators):
for pointValues in itertools.product(*pointIterators):
point = {}
for i in range(len(pointValues)):
point[pointNames[i]] = pointValues[i]
yield point, self.function(point)
class Data(object):
def __init__(self, name, dataString, step=None):
self.name = name
self.step = step
self.data = self.parseString(dataString)
def parseString(self, dataString):
if not isinstance(dataString, str):
return Constant(dataString),
dataList = []
for data in dataString.split(";"):
if isinstance(data, str) and "-" in data:
# Dealing with a range
dataList.append(Range(data, self.step))
else:
dataList.append(Constant(data))
return dataList
def __iter__(self):
for data in self.data:
for value in data:
yield value
def isConstant(self):
return len(self.data) == 1 and self.data[0].isConstant()
class Constant(object):
def __init__(self, const):
if isinstance(const, str):
self.value = None if const == "" else float(const)
def _xIter(self, fit, extraData, xRange, xAmount):
rangeLow, rangeHigh = self._limitXRange(xRange, fit, extraData)
# Amount is amount of ranges between points here, not amount of points
step = (rangeHigh - rangeLow) / xAmount
if step == 0:
yield xRange[0]
else:
self.value = const
current = rangeLow
# Take extra half step to make sure end of range is always included
# despite any possible float errors
while current <= (rangeHigh + step / 2):
yield current
current += step
def __iter__(self):
yield self.value
def _limitXRange(self, xRange, fit, extraData):
rangeLow, rangeHigh = sorted(xRange)
limitLow, limitHigh = self._getXLimits(fit, extraData)
rangeLow = max(limitLow, rangeLow)
rangeHigh = min(limitHigh, rangeHigh)
return rangeLow, rangeHigh
@staticmethod
def isConstant():
return True
def _getXLimits(self, fit, extraData):
return -math.inf, math.inf
def clearCache(self, key=None):
if key is None:
self._cache.clear()
elif key in self._cache:
del self._cache[key]
class Range(object):
def __init__(self, string, step):
start, end = string.split("-")
self.start = float(start)
self.end = float(end)
self.step = step
class SmoothGraph(Graph, metaclass=ABCMeta):
def __iter__(self):
current = start = self.start
end = self.end
step = self.step or (end - start) / 50.0
i = 1
while current < end:
current = start + i * step
i += 1
yield current
@staticmethod
def isConstant():
return False
def getPlotPoints(self, fit, extraData, xRange, xAmount):
xs = []
ys = []
for x in self._xIter(fit, extraData, xRange, xAmount):
xs.append(x)
ys.append(self.getYForX(fit, extraData, x))
return xs, ys

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

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

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

@@ -1,43 +0,0 @@
# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of eos.
#
# eos is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# eos is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from logbook import Logger
from eos.graph import Graph
from eos.utils.spoolSupport import SpoolType, SpoolOptions
pyfalog = Logger(__name__)
class FitDmgTimeGraph(Graph):
defaults = {"time": 0}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcDps, data if data is not None else self.defaults)
self.fit = fit
def calcDps(self, data):
fit = self.fit
time = data["time"]
dmg = 0
for i in range(round(time) + 1):
dmg += fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.TIME, i, True)).total
return dmg

151
eos/graph/fitDmgVsTime.py Normal file
View File

@@ -0,0 +1,151 @@
# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of eos.
#
# eos is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# eos is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from eos.graph import Graph
from eos.utils.spoolSupport import SpoolType, SpoolOptions
from gui.utils.numberFormatter import roundToPrec
class FitDmgVsTimeGraph(Graph):
def getPlotPoints(self, fit, extraData, xRange, xAmount):
# We deliberately ignore xAmount here to build graph which will reflect
# all steps of building up the damage
minX, maxX = self._limitXRange(xRange, fit, extraData)
if fit.ID not in self._cache:
self.__generateCache(fit, maxX)
currentY = None
xs = []
ys = []
cache = self._cache[fit.ID]
for time in sorted(cache):
prevY = currentY
currentX = time / 1000
currentY = roundToPrec(cache[time], 6)
if currentX < minX:
continue
# First set of data points
if not xs:
# Start at exactly requested time, at last known value
initialY = prevY or 0
xs.append(minX)
ys.append(initialY)
# If current time is bigger then starting, extend plot to that time with old value
if currentX > minX:
xs.append(currentX)
ys.append(initialY)
# If new value is different, extend it with new point to the new value
if currentY != prevY:
xs.append(currentX)
ys.append(currentY)
continue
# Last data point
if currentX >= maxX:
xs.append(maxX)
ys.append(prevY)
break
# Anything in-between
if currentY != prevY:
if prevY is not None:
xs.append(currentX)
ys.append(prevY)
xs.append(currentX)
ys.append(currentY)
return xs, ys
def getYForX(self, fit, extraData, x):
time = x * 1000
cache = self._cache[fit.ID]
closestTime = max((t for t in cache if t <= time), default=None)
if closestTime is None:
return 0
return roundToPrec(cache[closestTime], 6)
def _getXLimits(self, fit, extraData):
return 0, 2500
def __generateCache(self, fit, maxTime):
cache = self._cache[fit.ID] = {}
def addDmg(addedTime, addedDmg):
if addedDmg == 0:
return
if addedTime not in cache:
prevTime = max((t for t in cache if t < addedTime), default=None)
if prevTime is None:
cache[addedTime] = 0
else:
cache[addedTime] = cache[prevTime]
for time in (t for t in cache if t >= addedTime):
cache[time] += addedDmg
# We'll handle calculations in milliseconds
maxTime = maxTime * 1000
for mod in fit.modules:
if not mod.isDealingDamage():
continue
cycleParams = mod.getCycleParameters(reloadOverride=True)
if cycleParams is None:
continue
currentTime = 0
nonstopCycles = 0
for cycleTime, inactiveTime in cycleParams.iterCycles():
volleyParams = mod.getVolleyParameters(spoolOptions=SpoolOptions(SpoolType.CYCLES, nonstopCycles, True))
for volleyTime, volley in volleyParams.items():
addDmg(currentTime + volleyTime, volley.total)
if inactiveTime == 0:
nonstopCycles += 1
else:
nonstopCycles = 0
if currentTime > maxTime:
break
currentTime += cycleTime + inactiveTime
for drone in fit.drones:
if not drone.isDealingDamage():
continue
cycleParams = drone.getCycleParameters(reloadOverride=True)
if cycleParams is None:
continue
currentTime = 0
volleyParams = drone.getVolleyParameters()
for cycleTime, inactiveTime in cycleParams.iterCycles():
for volleyTime, volley in volleyParams.items():
addDmg(currentTime + volleyTime, volley.total)
if currentTime > maxTime:
break
currentTime += cycleTime + inactiveTime
for fighter in fit.fighters:
if not fighter.isDealingDamage():
continue
cycleParams = fighter.getCycleParametersPerEffectOptimizedDps(reloadOverride=True)
if cycleParams is None:
continue
volleyParams = fighter.getVolleyParametersPerEffect()
for effectID, abilityCycleParams in cycleParams.items():
if effectID not in volleyParams:
continue
currentTime = 0
abilityVolleyParams = volleyParams[effectID]
for cycleTime, inactiveTime in abilityCycleParams.iterCycles():
for volleyTime, volley in abilityVolleyParams.items():
addDmg(currentTime + volleyTime, volley.total)
if currentTime > maxTime:
break
currentTime += cycleTime + inactiveTime

View File

@@ -1,42 +0,0 @@
# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of eos.
#
# eos is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# eos is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from logbook import Logger
from eos.graph import Graph
from eos.utils.spoolSupport import SpoolType, SpoolOptions
pyfalog = Logger(__name__)
class FitDpsTimeGraph(Graph):
defaults = {"time": 0}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcDps, data if data is not None else self.defaults)
self.fit = fit
def calcDps(self, data):
fit = self.fit
time = data["time"]
dps = fit.getTotalDps(spoolOptions=SpoolOptions(SpoolType.TIME, time, True)).total
return dps

View File

@@ -17,80 +17,62 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from math import exp, log, radians, sin
from math import exp, log, radians, sin, inf
from logbook import Logger
from eos.const import FittingHardpoint, FittingModuleState
from eos.graph import Graph
from eos.graph import SmoothGraph
pyfalog = Logger(__name__)
class FitDpsRangeGraph(Graph):
class FitDpsVsRangeGraph(SmoothGraph):
defaults = {
"angle" : 0,
"distance" : 0,
"signatureRadius": None,
"velocity" : 0
}
def __init__(self, fit, data=None):
Graph.__init__(self, fit, self.calcDps, data if data is not None else self.defaults)
self.fit = fit
def calcDps(self, data):
ew = {'signatureRadius': [], 'velocity': []}
fit = self.fit
def getYForX(self, fit, extraData, distance):
tgtSpeed = extraData['speed']
tgtSigRad = extraData['signatureRadius'] if extraData['signatureRadius'] is not None else inf
angle = extraData['angle']
tgtSigRadMods = []
tgtSpeedMods = []
total = 0
distance = data["distance"] * 1000
abssort = lambda _val: -abs(_val - 1)
distance = distance * 1000
for mod in fit.modules:
if not mod.isEmpty and mod.state >= FittingModuleState.ACTIVE:
if "remoteTargetPaintFalloff" in mod.item.effects or "structureModuleEffectTargetPainter" in mod.item.effects:
ew['signatureRadius'].append(
1 + (mod.getModifiedItemAttr("signatureRadiusBonus") / 100) * self.calculateModuleMultiplier(
mod, data))
tgtSigRadMods.append(
1 + (mod.getModifiedItemAttr("signatureRadiusBonus") / 100)
* self.calculateModuleMultiplier(mod, distance))
if "remoteWebifierFalloff" in mod.item.effects or "structureModuleEffectStasisWebifier" in mod.item.effects:
if distance <= mod.getModifiedItemAttr("maxRange"):
ew['velocity'].append(1 + (mod.getModifiedItemAttr("speedFactor") / 100))
tgtSpeedMods.append(1 + (mod.getModifiedItemAttr("speedFactor") / 100))
elif mod.getModifiedItemAttr("falloffEffectiveness") > 0:
# I am affected by falloff
ew['velocity'].append(
1 + (mod.getModifiedItemAttr("speedFactor") / 100) * self.calculateModuleMultiplier(mod,
data))
tgtSpeedMods.append(
1 + (mod.getModifiedItemAttr("speedFactor") / 100) *
self.calculateModuleMultiplier(mod, distance))
ew['signatureRadius'].sort(key=abssort)
ew['velocity'].sort(key=abssort)
for attr, values in ew.items():
val = data[attr]
try:
for i in range(len(values)):
bonus = values[i]
val *= 1 + (bonus - 1) * exp(- i ** 2 / 7.1289)
data[attr] = val
except Exception as e:
pyfalog.critical("Caught exception in calcDPS.")
pyfalog.critical(e)
tgtSpeed = self.penalizeModChain(tgtSpeed, tgtSpeedMods)
tgtSigRad = self.penalizeModChain(tgtSigRad, tgtSigRadMods)
attRad = fit.ship.getModifiedItemAttr('radius', 0)
for mod in fit.modules:
dps = mod.getDps(targetResists=fit.targetResists).total
if mod.hardpoint == FittingHardpoint.TURRET:
if mod.state >= FittingModuleState.ACTIVE:
total += dps * self.calculateTurretMultiplier(mod, data)
total += dps * self.calculateTurretMultiplier(fit, mod, distance, angle, tgtSpeed, tgtSigRad)
elif mod.hardpoint == FittingHardpoint.MISSILE:
if mod.state >= FittingModuleState.ACTIVE and mod.maxRange is not None and mod.maxRange >= distance:
total += dps * self.calculateMissileMultiplier(mod, data)
if mod.state >= FittingModuleState.ACTIVE and mod.maxRange is not None and (mod.maxRange - attRad) >= distance:
total += dps * self.calculateMissileMultiplier(mod, tgtSpeed, tgtSigRad)
if distance <= fit.extraAttributes["droneControlRange"]:
if distance <= fit.extraAttributes['droneControlRange']:
for drone in fit.drones:
multiplier = 1 if drone.getModifiedItemAttr("maxVelocity") > 1 else self.calculateTurretMultiplier(
drone, data)
multiplier = 1 if drone.getModifiedItemAttr('maxVelocity') > 1 else self.calculateTurretMultiplier(
fit, drone, distance, angle, tgtSpeed, tgtSigRad)
dps = drone.getDps(targetResists=fit.targetResists).total
total += dps * multiplier
@@ -103,69 +85,62 @@ class FitDpsRangeGraph(Graph):
if ability.dealsDamage and ability.active:
if ability.effectID not in fighterDpsMap:
continue
multiplier = self.calculateFighterMissileMultiplier(ability, data)
multiplier = self.calculateFighterMissileMultiplier(tgtSpeed, tgtSigRad, ability)
dps = fighterDpsMap[ability.effectID].total
total += dps * multiplier
return total
@staticmethod
def calculateMissileMultiplier(mod, data):
targetSigRad = data["signatureRadius"]
targetVelocity = data["velocity"]
explosionRadius = mod.getModifiedChargeAttr("aoeCloudSize")
targetSigRad = explosionRadius if targetSigRad is None else targetSigRad
explosionVelocity = mod.getModifiedChargeAttr("aoeVelocity")
damageReductionFactor = mod.getModifiedChargeAttr("aoeDamageReductionFactor")
def calculateMissileMultiplier(mod, tgtSpeed, tgtSigRad):
explosionRadius = mod.getModifiedChargeAttr('aoeCloudSize')
explosionVelocity = mod.getModifiedChargeAttr('aoeVelocity')
damageReductionFactor = mod.getModifiedChargeAttr('aoeDamageReductionFactor')
sigRadiusFactor = targetSigRad / explosionRadius
if targetVelocity:
velocityFactor = (explosionVelocity / explosionRadius * targetSigRad / targetVelocity) ** damageReductionFactor
sigRadiusFactor = tgtSigRad / explosionRadius
if tgtSpeed:
velocityFactor = (explosionVelocity / explosionRadius * tgtSigRad / tgtSpeed) ** damageReductionFactor
else:
velocityFactor = 1
return min(sigRadiusFactor, velocityFactor, 1)
def calculateTurretMultiplier(self, mod, data):
@classmethod
def calculateTurretMultiplier(cls, fit, mod, distance, angle, tgtSpeed, tgtSigRad):
# Source for most of turret calculation info: http://wiki.eveonline.com/en/wiki/Falloff
chanceToHit = self.calculateTurretChanceToHit(mod, data)
chanceToHit = cls.calculateTurretChanceToHit(fit, mod, distance, angle, tgtSpeed, tgtSigRad)
if chanceToHit > 0.01:
# AvgDPS = Base Damage * [ ( ChanceToHit^2 + ChanceToHit + 0.0499 ) / 2 ]
multiplier = (chanceToHit ** 2 + chanceToHit + 0.0499) / 2
else:
# All hits are wreckings
multiplier = chanceToHit * 3
dmgScaling = mod.getModifiedItemAttr("turretDamageScalingRadius")
dmgScaling = mod.getModifiedItemAttr('turretDamageScalingRadius')
if dmgScaling:
targetSigRad = data["signatureRadius"]
multiplier = min(1, (float(targetSigRad) / dmgScaling) ** 2)
multiplier = min(1, (float(tgtSigRad) / dmgScaling) ** 2)
return multiplier
@staticmethod
def calculateFighterMissileMultiplier(ability, data):
def calculateFighterMissileMultiplier(tgtSpeed, tgtSigRad, ability):
prefix = ability.attrPrefix
targetSigRad = data["signatureRadius"]
targetVelocity = data["velocity"]
explosionRadius = ability.fighter.getModifiedItemAttr("{}ExplosionRadius".format(prefix))
explosionVelocity = ability.fighter.getModifiedItemAttr("{}ExplosionVelocity".format(prefix))
damageReductionFactor = ability.fighter.getModifiedItemAttr("{}ReductionFactor".format(prefix), None)
explosionRadius = ability.fighter.getModifiedItemAttr('{}ExplosionRadius'.format(prefix))
explosionVelocity = ability.fighter.getModifiedItemAttr('{}ExplosionVelocity'.format(prefix))
damageReductionFactor = ability.fighter.getModifiedItemAttr('{}ReductionFactor'.format(prefix), None)
# the following conditionals are because CCP can't keep a decent naming convention, as if fighter implementation
# wasn't already fucked.
if damageReductionFactor is None:
damageReductionFactor = ability.fighter.getModifiedItemAttr("{}DamageReductionFactor".format(prefix))
damageReductionFactor = ability.fighter.getModifiedItemAttr('{}DamageReductionFactor'.format(prefix))
damageReductionSensitivity = ability.fighter.getModifiedItemAttr("{}ReductionSensitivity".format(prefix), None)
damageReductionSensitivity = ability.fighter.getModifiedItemAttr('{}ReductionSensitivity'.format(prefix), None)
if damageReductionSensitivity is None:
damageReductionSensitivity = ability.fighter.getModifiedItemAttr(
"{}DamageReductionSensitivity".format(prefix))
damageReductionSensitivity = ability.fighter.getModifiedItemAttr('{}DamageReductionSensitivity'.format(prefix))
targetSigRad = explosionRadius if targetSigRad is None else targetSigRad
sigRadiusFactor = targetSigRad / explosionRadius
sigRadiusFactor = tgtSigRad / explosionRadius
if targetVelocity:
velocityFactor = (explosionVelocity / explosionRadius * targetSigRad / targetVelocity) ** (
if tgtSpeed:
velocityFactor = (explosionVelocity / explosionRadius * tgtSigRad / tgtSpeed) ** (
log(damageReductionFactor) / log(damageReductionSensitivity))
else:
velocityFactor = 1
@@ -173,28 +148,47 @@ class FitDpsRangeGraph(Graph):
return min(sigRadiusFactor, velocityFactor, 1)
@staticmethod
def calculateTurretChanceToHit(mod, data):
distance = data["distance"] * 1000
tracking = mod.getModifiedItemAttr("trackingSpeed")
def calculateTurretChanceToHit(fit, mod, distance, angle, tgtSpeed, tgtSigRad):
tracking = mod.getModifiedItemAttr('trackingSpeed')
turretOptimal = mod.maxRange
turretFalloff = mod.falloff
turretSigRes = mod.getModifiedItemAttr("optimalSigRadius")
targetSigRad = data["signatureRadius"]
targetSigRad = turretSigRes if targetSigRad is None else targetSigRad
transversal = sin(radians(data["angle"])) * data["velocity"]
trackingEq = (((transversal / (distance * tracking)) *
(turretSigRes / targetSigRad)) ** 2)
turretSigRes = mod.getModifiedItemAttr('optimalSigRadius')
transversal = sin(radians(angle)) * tgtSpeed
# Angular velocity is calculated using range from ship center to target center.
# We do not know target radius but we know attacker radius
angDistance = distance + fit.ship.getModifiedItemAttr('radius', 0)
if angDistance == 0 and transversal == 0:
angularVelocity = 0
elif angDistance == 0 and transversal != 0:
angularVelocity = inf
else:
angularVelocity = transversal / angDistance
trackingEq = (((angularVelocity / tracking) *
(turretSigRes / tgtSigRad)) ** 2)
rangeEq = ((max(0, distance - turretOptimal)) / turretFalloff) ** 2
return 0.5 ** (trackingEq + rangeEq)
@staticmethod
def calculateModuleMultiplier(mod, data):
def calculateModuleMultiplier(mod, distance):
# Simplified formula, we make some assumptions about the module
# This is basically the calculateTurretChanceToHit without tracking values
distance = data["distance"] * 1000
turretOptimal = mod.maxRange
turretFalloff = mod.falloff
rangeEq = ((max(0, distance - turretOptimal)) / turretFalloff) ** 2
return 0.5 ** rangeEq
@staticmethod
def penalizeModChain(value, mods):
mods.sort(key=lambda v: -abs(v - 1))
try:
for i in range(len(mods)):
bonus = mods[i]
value *= 1 + (bonus - 1) * exp(- i ** 2 / 7.1289)
return value
except Exception as e:
pyfalog.critical('Caught exception when penalizing modifier chain.')
pyfalog.critical(e)
return value

165
eos/graph/fitDpsVsTime.py Normal file
View File

@@ -0,0 +1,165 @@
# ===============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of eos.
#
# eos is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# eos is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from itertools import chain
from eos.graph import Graph
from eos.utils.spoolSupport import SpoolType, SpoolOptions
from gui.utils.numberFormatter import roundToPrec
class FitDpsVsTimeGraph(Graph):
def getPlotPoints(self, fit, extraData, xRange, xAmount):
# We deliberately ignore xAmount here to build graph which will reflect
# all steps of building up the damage
minX, maxX = self._limitXRange(xRange, fit, extraData)
if fit.ID not in self._cache:
self.__generateCache(fit, maxX)
currentY = None
prevY = None
xs = []
ys = []
cache = self._cache[fit.ID]
for time in sorted(cache):
prevY = currentY
currentX = time / 1000
currentY = roundToPrec(cache[time], 6)
if currentX < minX:
continue
# First set of data points
if not xs:
# Start at exactly requested time, at last known value
initialY = prevY or 0
xs.append(minX)
ys.append(initialY)
# If current time is bigger then starting, extend plot to that time with old value
if currentX > minX:
xs.append(currentX)
ys.append(initialY)
# If new value is different, extend it with new point to the new value
if currentY != prevY:
xs.append(currentX)
ys.append(currentY)
continue
# Last data point
if currentX >= maxX:
xs.append(maxX)
ys.append(prevY)
break
# Anything in-between
if currentY != prevY:
if prevY is not None:
xs.append(currentX)
ys.append(prevY)
xs.append(currentX)
ys.append(currentY)
if max(xs) < maxX:
xs.append(maxX)
ys.append(currentY or 0)
return xs, ys
def getYForX(self, fit, extraData, x):
time = x * 1000
cache = self._cache[fit.ID]
closestTime = max((t for t in cache if t <= time), default=None)
if closestTime is None:
return 0
return roundToPrec(cache[closestTime], 6)
def _getXLimits(self, fit, extraData):
return 0, 2500
def __generateCache(self, fit, maxTime):
cache = []
def addDmg(addedTimeStart, addedTimeFinish, addedDmg):
if addedDmg == 0:
return
addedDps = 1000 * addedDmg / (addedTimeFinish - addedTimeStart)
cache.append((addedTimeStart, addedTimeFinish, addedDps))
# We'll handle calculations in milliseconds
maxTime = maxTime * 1000
for mod in fit.modules:
if not mod.isDealingDamage():
continue
cycleParams = mod.getCycleParameters(reloadOverride=True)
if cycleParams is None:
continue
currentTime = 0
nonstopCycles = 0
for cycleTime, inactiveTime in cycleParams.iterCycles():
cycleDamage = 0
volleyParams = mod.getVolleyParameters(spoolOptions=SpoolOptions(SpoolType.CYCLES, nonstopCycles, True))
for volleyTime, volley in volleyParams.items():
cycleDamage += volley.total
addDmg(currentTime, currentTime + cycleTime, cycleDamage)
currentTime += cycleTime + inactiveTime
if inactiveTime > 0:
nonstopCycles = 0
else:
nonstopCycles += 1
if currentTime > maxTime:
break
for drone in fit.drones:
if not drone.isDealingDamage():
continue
cycleParams = drone.getCycleParameters(reloadOverride=True)
if cycleParams is None:
continue
currentTime = 0
for cycleTime, inactiveTime in cycleParams.iterCycles():
cycleDamage = 0
volleyParams = drone.getVolleyParameters()
for volleyTime, volley in volleyParams.items():
cycleDamage += volley.total
addDmg(currentTime, currentTime + cycleTime, cycleDamage)
currentTime += cycleTime + inactiveTime
if currentTime > maxTime:
break
for fighter in fit.fighters:
if not fighter.isDealingDamage():
continue
cycleParams = fighter.getCycleParametersPerEffectOptimizedDps(reloadOverride=True)
if cycleParams is None:
continue
volleyParams = fighter.getVolleyParametersPerEffect()
for effectID, abilityCycleParams in cycleParams.items():
if effectID not in volleyParams:
continue
abilityVolleyParams = volleyParams[effectID]
currentTime = 0
for cycleTime, inactiveTime in abilityCycleParams.iterCycles():
cycleDamage = 0
for volleyTime, volley in abilityVolleyParams.items():
cycleDamage += volley.total
addDmg(currentTime, currentTime + cycleTime, cycleDamage)
currentTime += cycleTime + inactiveTime
if currentTime > maxTime:
break
# Post-process cache
finalCache = {}
for time in sorted(set(chain((i[0] for i in cache), (i[1] for i in cache)))):
entries = (e for e in cache if e[0] <= time < e[1])
dps = sum(e[2] for e in entries)
finalCache[time] = dps
self._cache[fit.ID] = finalCache

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

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

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

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

@@ -17,13 +17,14 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
import math
from logbook import Logger
from sqlalchemy.orm import validates, reconstructor
from sqlalchemy.orm import reconstructor, validates
import eos.db
from eos.effectHandlerHelpers import HandledItem, HandledCharge
from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut
from eos.effectHandlerHelpers import HandledCharge, HandledItem
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
from eos.utils.cycles import CycleInfo
from eos.utils.stats import DmgTypes
@@ -104,7 +105,16 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@property
def cycleTime(self):
return max(self.getModifiedItemAttr("duration", 0), 0)
if self.hasAmmo:
cycleTime = self.getModifiedItemAttr("missileLaunchDuration", 0)
else:
for attr in ("speed", "duration"):
cycleTime = self.getModifiedItemAttr(attr, None)
if cycleTime is not None:
break
if cycleTime is None:
return 0
return max(cycleTime, 0)
@property
def dealsDamage(self):
@@ -121,9 +131,16 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def hasAmmo(self):
return self.charge is not None
def getVolley(self, targetResists=None):
def isDealingDamage(self):
volleyParams = self.getVolleyParameters()
for volley in volleyParams.values():
if volley.total > 0:
return True
return False
def getVolleyParameters(self, targetResists=None):
if not self.dealsDamage or self.amountActive <= 0:
return DmgTypes(0, 0, 0, 0)
return {0: DmgTypes(0, 0, 0, 0)}
if self.__baseVolley is None:
dmgGetter = self.getModifiedChargeAttr if self.hasAmmo else self.getModifiedItemAttr
dmgMult = self.amountActive * (self.getModifiedItemAttr("damageMultiplier", 1))
@@ -137,15 +154,19 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
thermal=self.__baseVolley.thermal * (1 - getattr(targetResists, "thermalAmount", 0)),
kinetic=self.__baseVolley.kinetic * (1 - getattr(targetResists, "kineticAmount", 0)),
explosive=self.__baseVolley.explosive * (1 - getattr(targetResists, "explosiveAmount", 0)))
return volley
return {0: volley}
def getVolley(self, targetResists=None):
return self.getVolleyParameters(targetResists=targetResists)[0]
def getDps(self, targetResists=None):
volley = self.getVolley(targetResists=targetResists)
if not volley:
return DmgTypes(0, 0, 0, 0)
cycleAttr = "missileLaunchDuration" if self.hasAmmo else "speed"
cycleTime = self.getModifiedItemAttr(cycleAttr)
dpsFactor = 1 / (cycleTime / 1000)
cycleParams = self.getCycleParameters()
if cycleParams is None:
return DmgTypes(0, 0, 0, 0)
dpsFactor = 1 / (cycleParams.averageTime / 1000)
dps = DmgTypes(
em=volley.em * dpsFactor,
thermal=volley.thermal * dpsFactor,
@@ -153,6 +174,12 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
explosive=volley.explosive * dpsFactor)
return dps
def getCycleParameters(self, reloadOverride=None):
cycleTime = self.cycleTime
if cycleTime == 0:
return None
return CycleInfo(self.cycleTime, 0, math.inf)
def getRemoteReps(self, ignoreState=False):
if self.amountActive <= 0 and not ignoreState:
return (None, 0)
@@ -174,7 +201,12 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
rrAmount = 0
if rrAmount:
droneAmount = self.amount if ignoreState else self.amountActive
rrAmount *= droneAmount / (self.cycleTime / 1000)
cycleParams = self.getCycleParameters()
if cycleParams is None:
rrType = None
rrAmount = 0
else:
rrAmount *= droneAmount / (cycleParams.averageTime / 1000)
self.__baseRemoteReps = (rrType, rrAmount)
return self.__baseRemoteReps
@@ -182,12 +214,14 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def miningStats(self):
if self.__miningyield is None:
if self.mines is True and self.amountActive > 0:
attr = "duration"
getter = self.getModifiedItemAttr
cycleTime = self.getModifiedItemAttr(attr)
volley = sum([getter(d) for d in self.MINING_ATTRIBUTES]) * self.amountActive
self.__miningyield = volley / (cycleTime / 1000.0)
cycleParams = self.getCycleParameters()
if cycleParams is None:
self.__miningyield = 0
else:
cycleTime = cycleParams.averageTime
volley = sum([getter(d) for d in self.MINING_ATTRIBUTES]) * self.amountActive
self.__miningyield = volley / (cycleTime / 1000.0)
else:
self.__miningyield = 0

View File

@@ -17,16 +17,19 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
import math
from logbook import Logger
from sqlalchemy.orm import validates, reconstructor
from sqlalchemy.orm import reconstructor, validates
import eos.db
from eos.effectHandlerHelpers import HandledItem, HandledCharge
from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut
from eos.saveddata.fighterAbility import FighterAbility
from eos.utils.stats import DmgTypes
from eos.const import FittingSlot
from eos.effectHandlerHelpers import HandledCharge, HandledItem
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
from eos.saveddata.fighterAbility import FighterAbility
from eos.utils.cycles import CycleInfo, CycleSequence
from eos.utils.stats import DmgTypes
from eos.utils.float import floatUnerr
pyfalog = Logger(__name__)
@@ -172,28 +175,45 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def hasAmmo(self):
return self.charge is not None
def getVolley(self, targetResists=None):
def isDealingDamage(self):
volleyParams = self.getVolleyParametersPerEffect()
for effectData in volleyParams.values():
for volley in effectData.values():
if volley.total > 0:
return True
return False
def getVolleyParametersPerEffect(self, targetResists=None):
if not self.active or self.amountActive <= 0:
return DmgTypes(0, 0, 0, 0)
return {}
if self.__baseVolley is None:
em = 0
therm = 0
kin = 0
exp = 0
self.__baseVolley = {}
for ability in self.abilities:
# Not passing resists here as we want to calculate and store base volley
abilityVolley = ability.getVolley()
em += abilityVolley.em
therm += abilityVolley.thermal
kin += abilityVolley.kinetic
exp += abilityVolley.explosive
self.__baseVolley = DmgTypes(em, therm, kin, exp)
volley = DmgTypes(
em=self.__baseVolley.em * (1 - getattr(targetResists, "emAmount", 0)),
thermal=self.__baseVolley.thermal * (1 - getattr(targetResists, "thermalAmount", 0)),
kinetic=self.__baseVolley.kinetic * (1 - getattr(targetResists, "kineticAmount", 0)),
explosive=self.__baseVolley.explosive * (1 - getattr(targetResists, "explosiveAmount", 0)))
return volley
self.__baseVolley[ability.effectID] = {0: ability.getVolley()}
adjustedVolley = {}
for effectID, effectData in self.__baseVolley.items():
adjustedVolley[effectID] = {}
for volleyTime, volleyValue in effectData.items():
adjustedVolley[effectID][volleyTime] = DmgTypes(
em=volleyValue.em * (1 - getattr(targetResists, "emAmount", 0)),
thermal=volleyValue.thermal * (1 - getattr(targetResists, "thermalAmount", 0)),
kinetic=volleyValue.kinetic * (1 - getattr(targetResists, "kineticAmount", 0)),
explosive=volleyValue.explosive * (1 - getattr(targetResists, "explosiveAmount", 0)))
return adjustedVolley
def getVolley(self, targetResists=None):
volleyParams = self.getVolleyParametersPerEffect(targetResists=targetResists)
em = 0
therm = 0
kin = 0
exp = 0
for volleyData in volleyParams.values():
em += volleyData[0].em
therm += volleyData[0].thermal
kin += volleyData[0].kinetic
exp += volleyData[0].explosive
return DmgTypes(em, therm, kin, exp)
def getDps(self, targetResists=None):
em = 0
@@ -207,44 +227,81 @@ class Fighter(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
explosive += dps.explosive
return DmgTypes(em=em, thermal=thermal, kinetic=kinetic, explosive=explosive)
def getUptime(self):
if not self.owner.factorReload:
return 1
activeTimes = []
reloadTimes = []
for ability in self.abilities:
if ability.numShots > 0:
activeTimes.append(ability.numShots * ability.cycleTime)
reloadTimes.append(ability.reloadTime)
if not activeTimes:
return 1
shortestActive = sorted(activeTimes)[0]
longestReload = sorted(reloadTimes, reverse=True)[0]
uptime = shortestActive / (shortestActive + longestReload)
return uptime
def getDpsPerEffect(self, targetResists=None):
if not self.active or self.amountActive <= 0:
return {}
uptime = self.getUptime()
if uptime == 1:
return {a.effectID: a.getDps(targetResists=targetResists) for a in self.abilities}
# Decide if it's better to keep steady dps up and never reload or reload from time to time
dpsMapSteady = {}
dpsMapPeakAdjusted = {}
cycleParams = self.getCycleParametersPerEffectOptimizedDps(targetResists=targetResists)
dpsMap = {}
for ability in self.abilities:
abilityDps = ability.getDps(targetResists=targetResists)
dpsMapPeakAdjusted[ability.effectID] = DmgTypes(
em=abilityDps.em * uptime,
thermal=abilityDps.thermal * uptime,
kinetic=abilityDps.kinetic * uptime,
explosive=abilityDps.explosive * uptime)
# Infinite use - add to steady dps
if ability.numShots == 0:
dpsMapSteady[ability.effectID] = abilityDps
totalSteady = sum(i.total for i in dpsMapSteady.values())
totalPeakAdjusted = sum(i.total for i in dpsMapPeakAdjusted.values())
return dpsMapSteady if totalSteady >= totalPeakAdjusted else dpsMapPeakAdjusted
if ability.effectID in cycleParams:
cycleTime = cycleParams[ability.effectID].averageTime
dpsMap[ability.effectID] = ability.getDps(targetResists=targetResists, cycleTimeOverride=cycleTime)
return dpsMap
def getCycleParametersPerEffectOptimizedDps(self, targetResists=None, reloadOverride=None):
cycleParamsInfinite = self.getCycleParametersPerEffectInfinite()
cycleParamsReload = self.getCycleParametersPerEffect(reloadOverride=reloadOverride)
dpsMapOnlyInfinite = {}
dpsMapAllWithReloads = {}
# Decide if it's better to keep steady dps up and never reload or reload from time to time
for ability in self.abilities:
if ability.effectID in cycleParamsInfinite:
cycleTime = cycleParamsInfinite[ability.effectID].averageTime
dpsMapOnlyInfinite[ability.effectID] = ability.getDps(targetResists=targetResists, cycleTimeOverride=cycleTime)
if ability.effectID in cycleParamsReload:
cycleTime = cycleParamsReload[ability.effectID].averageTime
dpsMapAllWithReloads[ability.effectID] = ability.getDps(targetResists=targetResists, cycleTimeOverride=cycleTime)
totalOnlyInfinite = sum(i.total for i in dpsMapOnlyInfinite.values())
totalAllWithReloads = sum(i.total for i in dpsMapAllWithReloads.values())
return cycleParamsInfinite if totalOnlyInfinite >= totalAllWithReloads else cycleParamsReload
def getCycleParametersPerEffectInfinite(self):
return {a.effectID: CycleInfo(a.cycleTime, 0, math.inf) for a in self.abilities if a.numShots == 0 and a.cycleTime > 0}
def getCycleParametersPerEffect(self, reloadOverride=None):
factorReload = reloadOverride if reloadOverride is not None else self.owner.factorReload
# Assume it can cycle infinitely
if not factorReload:
return {a.effectID: CycleInfo(a.cycleTime, 0, math.inf) for a in self.abilities if a.cycleTime > 0}
limitedAbilities = [a for a in self.abilities if a.numShots > 0 and a.cycleTime > 0]
if len(limitedAbilities) == 0:
return {a.effectID: CycleInfo(a.cycleTime, 0, math.inf) for a in self.abilities if a.cycleTime > 0}
validAbilities = [a for a in self.abilities if a.cycleTime > 0]
if len(validAbilities) == 0:
return {}
mostLimitedAbility = min(limitedAbilities, key=lambda a: a.cycleTime * a.numShots)
durationToRefuel = mostLimitedAbility.cycleTime * mostLimitedAbility.numShots
# find out how many shots various abilities will do until reload, and how much time
# "extra" cycle will last (None for no extra cycle)
cyclesUntilRefuel = {mostLimitedAbility.effectID: (mostLimitedAbility.numShots, None)}
for ability in (a for a in validAbilities if a is not mostLimitedAbility):
fullCycles = int(floatUnerr(durationToRefuel / ability.cycleTime))
extraShotTime = floatUnerr(durationToRefuel - (fullCycles * ability.cycleTime))
if extraShotTime == 0:
extraShotTime = None
cyclesUntilRefuel[ability.effectID] = (fullCycles, extraShotTime)
refuelTimes = {}
for ability in validAbilities:
spentShots, extraShotTime = cyclesUntilRefuel[ability.effectID]
if extraShotTime is not None:
spentShots += 1
refuelTimes[ability.effectID] = ability.getReloadTime(spentShots)
refuelTime = max(refuelTimes.values())
cycleParams = {}
for ability in validAbilities:
regularShots, extraShotTime = cyclesUntilRefuel[ability.effectID]
sequence = []
if extraShotTime is not None:
if regularShots > 0:
sequence.append(CycleInfo(ability.cycleTime, 0, regularShots))
sequence.append(CycleInfo(extraShotTime, refuelTime, 1))
else:
regularShotsNonReload = regularShots - 1
if regularShotsNonReload > 0:
sequence.append(CycleInfo(ability.cycleTime, 0, regularShotsNonReload))
sequence.append(CycleInfo(ability.cycleTime, refuelTime, 1))
cycleParams[ability.effectID] = CycleSequence(sequence, math.inf)
return cycleParams
@property
def maxRange(self):

View File

@@ -95,8 +95,15 @@ class FighterAbility(object):
@property
def reloadTime(self):
return self.getReloadTime()
def getReloadTime(self, spentShots=None):
if spentShots is not None:
spentShots = max(self.numShots, spentShots)
else:
spentShots = self.numShots
rearm_time = (self.REARM_TIME_MAPPING[self.fighter.getModifiedItemAttr("fighterSquadronRole")] or 0 if self.hasCharges else 0)
return self.fighter.getModifiedItemAttr("fighterRefuelingTime") + rearm_time * self.numShots
return self.fighter.getModifiedItemAttr("fighterRefuelingTime") + rearm_time * spentShots
@property
def numShots(self):
@@ -128,11 +135,12 @@ class FighterAbility(object):
explosive=exp * dmgMult * (1 - getattr(targetResists, "explosiveAmount", 0)))
return volley
def getDps(self, targetResists=None):
def getDps(self, targetResists=None, cycleTimeOverride=None):
volley = self.getVolley(targetResists=targetResists)
if not volley:
return DmgTypes(0, 0, 0, 0)
dpsFactor = 1 / (self.cycleTime / 1000)
cycleTime = cycleTimeOverride if cycleTimeOverride is not None else self.cycleTime
dpsFactor = 1 / (cycleTime / 1000)
dps = DmgTypes(
em=volley.em * dpsFactor,
thermal=volley.thermal * dpsFactor,

View File

@@ -17,21 +17,22 @@
# along with eos. If not, see <http://www.gnu.org/licenses/>.
# ===============================================================================
from math import floor
from logbook import Logger
import math
from sqlalchemy.orm import reconstructor, validates
import eos.db
from eos.const import FittingModuleState, FittingHardpoint, FittingSlot
from eos.const import FittingHardpoint, FittingModuleState, FittingSlot
from eos.effectHandlerHelpers import HandledCharge, HandledItem
from eos.modifiedAttributeDict import ChargeAttrShortcut, ItemAttrShortcut, ModifiedAttributeDict
from eos.saveddata.citadel import Citadel
from eos.saveddata.mutator import Mutator
from eos.utils.cycles import CycleInfo, CycleSequence
from eos.utils.float import floatUnerr
from eos.utils.spoolSupport import calculateSpoolup, resolveSpoolOptions
from eos.utils.stats import DmgTypes
pyfalog = Logger(__name__)
ProjectedMap = {
@@ -287,7 +288,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
# numcycles = math.floor(module_capacity / (module_volume * module_chargerate))
chargeRate = self.getModifiedItemAttr("chargeRate")
numCharges = self.numCharges
numShots = floor(numCharges / chargeRate)
numShots = math.floor(numCharges / chargeRate)
else:
numShots = None
return numShots
@@ -300,7 +301,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
chance = self.getModifiedChargeAttr("crystalVolatilityChance")
damage = self.getModifiedChargeAttr("crystalVolatilityDamage")
crystals = self.numCharges
numShots = floor((crystals * hp) / (damage * chance))
numShots = math.floor((crystals * hp) / (damage * chance))
else:
# Set 0 (infinite) for permanent crystals like t1 laser crystals
numShots = 0
@@ -400,8 +401,12 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
volley = self.getModifiedItemAttr("specialtyMiningAmount") or self.getModifiedItemAttr(
"miningAmount") or 0
if volley:
cycleTime = self.cycleTime
self.__miningyield = volley / (cycleTime / 1000.0)
cycleParams = self.getCycleParameters()
if cycleParams is None:
self.__miningyield = 0
else:
cycleTime = cycleParams.averageTime
self.__miningyield = volley / (cycleTime / 1000.0)
else:
self.__miningyield = 0
else:
@@ -409,42 +414,71 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
return self.__miningyield
def getVolley(self, spoolOptions=None, targetResists=None, ignoreState=False):
def isDealingDamage(self, ignoreState=False):
volleyParams = self.getVolleyParameters(ignoreState=ignoreState)
for volley in volleyParams.values():
if volley.total > 0:
return True
return False
def getVolleyParameters(self, spoolOptions=None, targetResists=None, ignoreState=False):
if self.isEmpty or (self.state < FittingModuleState.ACTIVE and not ignoreState):
return DmgTypes(0, 0, 0, 0)
return {0: DmgTypes(0, 0, 0, 0)}
if self.__baseVolley is None:
self.__baseVolley = {}
dmgGetter = self.getModifiedChargeAttr if self.charge else self.getModifiedItemAttr
dmgMult = self.getModifiedItemAttr("damageMultiplier", 1)
self.__baseVolley = DmgTypes(
em=(dmgGetter("emDamage", 0)) * dmgMult,
thermal=(dmgGetter("thermalDamage", 0)) * dmgMult,
kinetic=(dmgGetter("kineticDamage", 0)) * dmgMult,
explosive=(dmgGetter("explosiveDamage", 0)) * dmgMult)
dmgDelay = self.getModifiedItemAttr("damageDelayDuration", 0) or self.getModifiedItemAttr("doomsdayWarningDuration", 0)
dmgDuration = self.getModifiedItemAttr("doomsdayDamageDuration", 0)
dmgSubcycle = self.getModifiedItemAttr("doomsdayDamageCycleTime", 0)
if dmgDuration != 0 and dmgSubcycle != 0:
subcycles = math.floor(floatUnerr(dmgDuration / dmgSubcycle))
else:
subcycles = 1
for i in range(subcycles):
self.__baseVolley[dmgDelay + dmgSubcycle * i] = DmgTypes(
em=(dmgGetter("emDamage", 0)) * dmgMult,
thermal=(dmgGetter("thermalDamage", 0)) * dmgMult,
kinetic=(dmgGetter("kineticDamage", 0)) * dmgMult,
explosive=(dmgGetter("explosiveDamage", 0)) * dmgMult)
spoolType, spoolAmount = resolveSpoolOptions(spoolOptions, self)
spoolBoost = calculateSpoolup(
self.getModifiedItemAttr("damageMultiplierBonusMax", 0),
self.getModifiedItemAttr("damageMultiplierBonusPerCycle", 0),
self.rawCycleTime / 1000, spoolType, spoolAmount)[0]
spoolMultiplier = 1 + spoolBoost
volley = DmgTypes(
em=self.__baseVolley.em * spoolMultiplier * (1 - getattr(targetResists, "emAmount", 0)),
thermal=self.__baseVolley.thermal * spoolMultiplier * (1 - getattr(targetResists, "thermalAmount", 0)),
kinetic=self.__baseVolley.kinetic * spoolMultiplier * (1 - getattr(targetResists, "kineticAmount", 0)),
explosive=self.__baseVolley.explosive * spoolMultiplier * (1 - getattr(targetResists, "explosiveAmount", 0)))
return volley
adjustedVolley = {}
for volleyTime, volleyValue in self.__baseVolley.items():
adjustedVolley[volleyTime] = DmgTypes(
em=volleyValue.em * spoolMultiplier * (1 - getattr(targetResists, "emAmount", 0)),
thermal=volleyValue.thermal * spoolMultiplier * (1 - getattr(targetResists, "thermalAmount", 0)),
kinetic=volleyValue.kinetic * spoolMultiplier * (1 - getattr(targetResists, "kineticAmount", 0)),
explosive=volleyValue.explosive * spoolMultiplier * (1 - getattr(targetResists, "explosiveAmount", 0)))
return adjustedVolley
def getVolley(self, spoolOptions=None, targetResists=None, ignoreState=False):
volleyParams = self.getVolleyParameters(spoolOptions=spoolOptions, targetResists=targetResists, ignoreState=ignoreState)
if len(volleyParams) == 0:
return DmgTypes(0, 0, 0, 0)
return volleyParams[min(volleyParams)]
def getDps(self, spoolOptions=None, targetResists=None, ignoreState=False):
volley = self.getVolley(spoolOptions=spoolOptions, targetResists=targetResists, ignoreState=ignoreState)
if not volley:
return DmgTypes(0, 0, 0, 0)
# Some weapons repeat multiple times in one cycle (bosonic doomsdays). Get the number of times it fires off
volleysPerCycle = max(self.getModifiedItemAttr("doomsdayDamageDuration", 1) / self.getModifiedItemAttr("doomsdayDamageCycleTime", 1), 1)
dpsFactor = volleysPerCycle / (self.cycleTime / 1000)
dmgDuringCycle = DmgTypes(0, 0, 0, 0)
cycleParams = self.getCycleParameters()
if cycleParams is None:
return dmgDuringCycle
volleyParams = self.getVolleyParameters(spoolOptions=spoolOptions, targetResists=targetResists, ignoreState=ignoreState)
avgCycleTime = cycleParams.averageTime
if len(volleyParams) == 0 or avgCycleTime == 0:
return dmgDuringCycle
for volleyValue in volleyParams.values():
dmgDuringCycle += volleyValue
dpsFactor = 1 / (avgCycleTime / 1000)
dps = DmgTypes(
em=volley.em * dpsFactor,
thermal=volley.thermal * dpsFactor,
kinetic=volley.kinetic * dpsFactor,
explosive=volley.explosive * dpsFactor)
em=dmgDuringCycle.em * dpsFactor,
thermal=dmgDuringCycle.thermal * dpsFactor,
kinetic=dmgDuringCycle.kinetic * dpsFactor,
explosive=dmgDuringCycle.explosive * dpsFactor)
return dps
def getRemoteReps(self, spoolOptions=None, ignoreState=False):
@@ -474,7 +508,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
else:
return None, 0
if rrAmount:
rrAmount *= 1 / (self.cycleTime / 1000)
cycleParams = self.getCycleParameters()
if cycleParams is None:
return None, 0
rrAmount *= 1 / (cycleParams.averageTime / 1000)
if module.item.group.name == "Ancillary Remote Armor Repairer" and module.charge:
rrAmount *= module.getModifiedItemAttr("chargedArmorDamageMultiplier", 1)
@@ -819,49 +856,61 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
except:
effect.handler(fit, self, context)
@property
def cycleTime(self):
def getCycleParameters(self, reloadOverride=None):
"""Copied from new eos as well"""
# Determine if we'll take into account reload time or not
factorReload = self.owner.factorReload if self.forceReload is None else self.forceReload
numShots = self.numShots
speed = self.rawCycleTime
if factorReload and self.charge:
raw_reload_time = self.reloadTime
if reloadOverride is not None:
factorReload = reloadOverride
else:
raw_reload_time = 0.0
factorReload = self.owner.factorReload if self.forceReload is None else self.forceReload
# Module can only fire one shot at a time, think bomb launchers or defender launchers
if self.disallowRepeatingAction:
if numShots > 0:
"""
The actual mechanics behind this is complex. Behavior will be (for 3 ammo):
fire, reactivation delay, fire, reactivation delay, fire, max(reactivation delay, reload)
so your effective reload time depends on where you are at in the cycle.
cycles_until_reload = self.numShots
if cycles_until_reload == 0:
cycles_until_reload = math.inf
We can't do that, so instead we'll average it out.
Currently would apply to bomb launchers and defender missiles
"""
effective_reload_time = ((self.reactivationDelay * (numShots - 1)) + max(raw_reload_time, self.reactivationDelay, 0))
else:
"""
Applies to MJD/MJFG
"""
effective_reload_time = max(raw_reload_time, self.reactivationDelay, 0)
speed = speed + effective_reload_time
active_time = self.rawCycleTime
if active_time == 0:
return None
forced_inactive_time = self.reactivationDelay
reload_time = self.reloadTime
# Effects which cannot be reloaded have the same processing whether
# caller wants to take reload time into account or not
if reload_time is None and cycles_until_reload < math.inf:
final_cycles = 1
early_cycles = cycles_until_reload - final_cycles
# Single cycle until effect cannot run anymore
if early_cycles == 0:
return CycleInfo(active_time, 0, 1)
# Multiple cycles with the same parameters
if forced_inactive_time == 0:
return CycleInfo(active_time, 0, cycles_until_reload)
# Multiple cycles with different parameters
return CycleSequence((
CycleInfo(active_time, forced_inactive_time, early_cycles),
CycleInfo(active_time, 0, final_cycles)
), 1)
# Module cycles the same way all the time in 3 cases:
# 1) caller doesn't want to take into account reload time
# 2) effect does not have to reload anything to keep running
# 3) effect has enough time to reload during inactivity periods
if (
not factorReload or
cycles_until_reload == math.inf or
forced_inactive_time >= reload_time
):
return CycleInfo(active_time, forced_inactive_time, math.inf)
# We've got to take reload into consideration
else:
"""
Currently no other modules would have a reactivation delay, so for sanities sake don't try and account for it.
Okay, technically cloaks do, but they also have 0 cycle time and cap usage so why do you care?
"""
effective_reload_time = raw_reload_time
if numShots > 0 and self.charge:
speed = (speed * numShots + effective_reload_time) / numShots
return speed
final_cycles = 1
early_cycles = cycles_until_reload - final_cycles
# If effect has to reload after each its cycle, then its parameters
# are the same all the time
if early_cycles == 0:
return CycleInfo(active_time, reload_time, math.inf)
return CycleSequence((
CycleInfo(active_time, forced_inactive_time, early_cycles),
CycleInfo(active_time, reload_time, final_cycles)
), math.inf)
@property
def rawCycleTime(self):
@@ -887,7 +936,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def capUse(self):
capNeed = self.getModifiedItemAttr("capacitorNeed")
if capNeed and self.state >= FittingModuleState.ACTIVE:
cycleTime = self.cycleTime
cycleParams = self.getCycleParameters()
if cycleParams is None:
return 0
cycleTime = cycleParams.averageTime
if cycleTime > 0:
capUsed = capNeed / (cycleTime / 1000.0)
return capUsed

68
eos/utils/cycles.py Normal file
View File

@@ -0,0 +1,68 @@
# Borrowed from new eos
from utils.repr import makeReprStr
class CycleInfo:
def __init__(self, activeTime, inactiveTime, quantity):
self.activeTime = activeTime
self.inactiveTime = inactiveTime
self.quantity = quantity
@property
def averageTime(self):
return self.activeTime + self.inactiveTime
def iterCycles(self):
i = 0
while i < self.quantity:
yield self.activeTime, self.inactiveTime
i += 1
def _getCycleQuantity(self):
return self.quantity
def _getTime(self):
return (self.activeTime + self.inactiveTime) * self.quantity
def __repr__(self):
spec = ['activeTime', 'inactiveTime', 'quantity']
return makeReprStr(self, spec)
class CycleSequence:
def __init__(self, sequence, quantity):
self.sequence = sequence
self.quantity = quantity
@property
def averageTime(self):
"""Get average time between cycles."""
return self._getTime() / self._getCycleQuantity()
def iterCycles(self):
i = 0
while i < self.quantity:
for cycleInfo in self.sequence:
for cycleTime, inactiveTime in cycleInfo.iterCycles():
yield cycleTime, inactiveTime
i += 1
def _getCycleQuantity(self):
quantity = 0
for item in self.sequence:
quantity += item._getCycleQuantity()
return quantity
def _getTime(self):
time = 0
for item in self.sequence:
time += item._getTime()
return time
def __repr__(self):
spec = ['sequence', 'quantity']
return makeReprStr(self, spec)

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,5 +1,11 @@
__all__ = [
"fitDpsRange",
"fitDpsTime",
"fitDmgTime"
]
# noinspection PyUnresolvedReferences
from gui.builtinGraphs import ( # noqa: E402,F401
fitDpsVsRange,
fitDmgVsTime,
fitShieldRegenVsShieldPerc,
fitShieldAmountVsTime,
fitCapRegenVsCapPerc,
fitCapAmountVsTime,
fitMobilityVsTime,
fitWarpTimeVsDistance
)

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

@@ -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,82 +0,0 @@
# =============================================================================
# Copyright (C) 2010 Diego Duclos
#
# This file is part of pyfa.
#
# pyfa is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# pyfa is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
# =============================================================================
import gui.mainFrame
from eos.graph import Data
from eos.graph.fitDmgTime import FitDmgTimeGraph as EosFitDmgTimeGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitDmgTimeGraph(Graph):
propertyLabelMap = {"time": "Time (seconds)"}
defaults = EosFitDmgTimeGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["time"] = "0-300"
self.name = "Damage over time"
self.fitDmgTime = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getFields(self):
return self.defaults
def getLabels(self):
return self.propertyLabelMap
def getIcons(self):
iconFile = Attribute.getInstance().getAttributeInfo('duration').iconID
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
return {"time": bitmap}
def getPoints(self, fit, fields):
fitDmgTime = getattr(self, "fitDmgTime", None)
if fitDmgTime is None or fitDmgTime.fit != fit:
fitDmgTime = self.fitDmgTime = EosFitDmgTimeGraph(fit)
fitDmgTime.clearData()
variable = None
for fieldName, value in fields.items():
d = Data(fieldName, value)
if not d.isConstant():
if variable is None:
variable = fieldName
else:
# We can't handle more then one variable atm, OOPS FUCK OUT
return False, "Can only handle 1 variable"
fitDmgTime.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in fitDmgTime.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDmgTimeGraph.register()

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 over range"
self.fitDpsRange = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getFields(self):
return self.defaults
def getLabels(self):
return self.propertyLabelMap
def getIcons(self):
icons = {}
sAttr = Attribute.getInstance()
for key, attrName in self.propertyAttributeMap.items():
iconFile = sAttr.getAttributeInfo(attrName).iconID
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
if bitmap:
icons[key] = bitmap
return icons
def getPoints(self, fit, fields):
fitDpsRange = getattr(self, "fitDpsRange", None)
if fitDpsRange is None or fitDpsRange.fit != fit:
fitDpsRange = self.fitDpsRange = EosFitDpsRangeGraph(fit)
fitDpsRange.clearData()
variable = None
for fieldName, value in fields.items():
d = Data(fieldName, value)
if not d.isConstant():
if variable is None:
variable = fieldName
else:
# We can't handle more then one variable atm, OOPS FUCK OUT
return False, "Can only handle 1 variable"
fitDpsRange.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in fitDpsRange.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDpsRangeGraph.register()

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.fitDpsTime import FitDpsTimeGraph as EosFitDpsTimeGraph
from gui.bitmap_loader import BitmapLoader
from gui.graph import Graph
from service.attribute import Attribute
class FitDpsTimeGraph(Graph):
propertyLabelMap = {"time": "Time (seconds)"}
defaults = EosFitDpsTimeGraph.defaults.copy()
def __init__(self):
Graph.__init__(self)
self.defaults["time"] = "0-300"
self.name = "DPS over time"
self.fitDpsTime = None
self.mainFrame = gui.mainFrame.MainFrame.getInstance()
def getFields(self):
return self.defaults
def getLabels(self):
return self.propertyLabelMap
def getIcons(self):
iconFile = Attribute.getInstance().getAttributeInfo('duration').iconID
bitmap = BitmapLoader.getBitmap(iconFile, "icons")
return {"time": bitmap}
def getPoints(self, fit, fields):
fitDpsTime = getattr(self, "fitDpsTime", None)
if fitDpsTime is None or fitDpsTime.fit != fit:
fitDpsTime = self.fitDpsTime = EosFitDpsTimeGraph(fit)
fitDpsTime.clearData()
variable = None
for fieldName, value in fields.items():
d = Data(fieldName, value)
if not d.isConstant():
if variable is None:
variable = fieldName
else:
# We can't handle more then one variable atm, OOPS FUCK OUT
return False, "Can only handle 1 variable"
fitDpsTime.setData(d)
if variable is None:
return False, "No variable"
x = []
y = []
for point, val in fitDpsTime.getIterator():
x.append(point[variable])
y.append(val)
return x, y
FitDpsTimeGraph.register()

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

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

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

@@ -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__)
@@ -291,7 +292,9 @@ class FitItem(SFItem.SFBrowserItem):
event.Skip()
def editCheckEsc(self, event):
if event.GetKeyCode() == wx.WXK_ESCAPE:
keycode = event.GetKeyCode()
mstate = wx.GetMouseState()
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
self.RestoreEditButton()
else:
event.Skip()
@@ -377,9 +380,8 @@ class FitItem(SFItem.SFBrowserItem):
break
sFit.deleteFit(self.fitID)
# Notify other areas that a fit has been deleted
wx.PostEvent(self.mainFrame, FitRemoved(fitID=self.fitID))
wx.PostEvent(self.mainFrame, GE.FitRemoved(fitID=self.fitID))
# todo: would a simple RefreshList() work here instead of posting that a stage has been selected?
if self.shipBrowser.GetActiveStage() == 5:

View File

@@ -105,7 +105,9 @@ class NavigationPanel(SFItem.SFBrowserItem):
self.BrowserSearchBox.Show(False)
def OnBrowserSearchBoxKeyPress(self, event):
if event.GetKeyCode() == wx.WXK_ESCAPE:
keycode = event.GetKeyCode()
mstate = wx.GetMouseState()
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
self.BrowserSearchBox.Show(False)
elif event.RawControlDown() and event.GetKeyCode() == wx.WXK_BACK:
HandleCtrlBackspace(self.BrowserSearchBox)

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

@@ -175,7 +175,9 @@ class ShipItem(SFItem.SFBrowserItem):
self.Refresh()
def editCheckEsc(self, event):
if event.GetKeyCode() == wx.WXK_ESCAPE:
keycode = event.GetKeyCode()
mstate = wx.GetMouseState()
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
self.tcFitName.Show(False)
else:
event.Skip()

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":
@@ -140,7 +142,10 @@ class Miscellanea(ViewColumn):
return "+ " + ", ".join(info), "Slot Modifiers"
elif itemGroup == "Energy Neutralizer":
neutAmount = stuff.getModifiedItemAttr("energyNeutralizerAmount")
cycleTime = stuff.cycleTime
cycleParams = stuff.getCycleParameters()
if cycleParams is None:
return "", None
cycleTime = cycleParams.averageTime
if not neutAmount or not cycleTime:
return "", None
capPerSec = float(-neutAmount) * 1000 / cycleTime
@@ -149,7 +154,10 @@ class Miscellanea(ViewColumn):
return text, tooltip
elif itemGroup == "Energy Nosferatu":
neutAmount = stuff.getModifiedItemAttr("powerTransferAmount")
cycleTime = stuff.cycleTime
cycleParams = stuff.getCycleParameters()
if cycleParams is None:
return "", None
cycleTime = cycleParams.averageTime
if not neutAmount or not cycleTime:
return "", None
capPerSec = float(-neutAmount) * 1000 / cycleTime

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
@@ -256,7 +258,8 @@ class CharacterEditor(wx.Frame):
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_ESCAPE:
mstate = wx.GetMouseState()
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
self.closeWindow()
return
event.Skip()
@@ -875,9 +878,11 @@ class APIView(wx.Panel):
def __fetchCallback(self, e=None):
if e:
exc_type, exc_obj, exc_trace = e
pyfalog.warn("Error fetching skill information for character")
pyfalog.warn(exc_obj)
pyfalog.warn("Error fetching skill information for character for __fetchCallback")
exc_type, exc_value, exc_trace = e
if config.debug:
exc_value = ''.join(traceback.format_exception(exc_type, exc_value, exc_trace))
pyfalog.warn(exc_value)
wx.MessageBox(
"Error fetching skill information",

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)
@@ -96,7 +97,8 @@ class EveFittings(wx.Frame):
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_ESCAPE:
mstate = wx.GetMouseState()
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
self.closeWindow()
return
event.Skip()
@@ -250,7 +252,8 @@ class ExportToEve(wx.Frame):
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_ESCAPE:
mstate = wx.GetMouseState()
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
self.closeWindow()
return
event.Skip()
@@ -353,7 +356,8 @@ class SsoCharacterMgmt(wx.Dialog):
def kbEvent(self, event):
keycode = event.GetKeyCode()
if keycode == wx.WXK_ESCAPE:
mstate = wx.GetMouseState()
if keycode == wx.WXK_ESCAPE and mstate.GetModifiers() == wx.MOD_NONE:
self.closeWindow()
return
event.Skip()

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

View File

@@ -12,13 +12,12 @@ pyfalog = Logger(__name__)
class CalcAddProjectedModuleCommand(wx.Command):
def __init__(self, fitID, modInfo, position=None, ignoreRestrictions=False, commit=True):
def __init__(self, fitID, modInfo, position=None, ignoreRestrictions=False):
wx.Command.__init__(self, True)
self.fitID = fitID
self.newModInfo = modInfo
self.newPosition = position
self.ignoreRestrictions = ignoreRestrictions
self.commit = commit
self.oldModInfo = None
self.oldPosition = None
self.savedStateCheckChanges = None
@@ -40,14 +39,10 @@ class CalcAddProjectedModuleCommand(wx.Command):
if self.newPosition is not None:
fit.projectedModules.insert(self.newPosition, newMod)
if newMod not in fit.projectedModules:
if self.commit:
eos.db.commit()
return False
else:
fit.projectedModules.append(newMod)
if newMod not in fit.projectedModules:
if self.commit:
eos.db.commit()
return False
self.newPosition = fit.projectedModules.index(newMod)
@@ -56,8 +51,6 @@ class CalcAddProjectedModuleCommand(wx.Command):
eos.db.flush()
sFit.recalc(fit)
self.savedStateCheckChanges = sFit.checkStates(fit, newMod)
if self.commit:
eos.db.commit()
return True
def Undo(self):
@@ -67,22 +60,16 @@ class CalcAddProjectedModuleCommand(wx.Command):
fitID=self.fitID,
modInfo=self.oldModInfo,
position=self.oldPosition,
ignoreRestrictions=True,
commit=False)
ignoreRestrictions=True)
if not cmd.Do():
return False
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
if self.commit:
eos.db.commit()
return True
from .projectedRemove import CalcRemoveProjectedModuleCommand
cmd = CalcRemoveProjectedModuleCommand(
fitID=self.fitID,
position=self.newPosition,
commit=False)
position=self.newPosition)
if not cmd.Do():
return False
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
if self.commit:
eos.db.commit()
return True

View File

@@ -1,7 +1,6 @@
import wx
from logbook import Logger
import eos.db
from eos.const import FittingModuleState
from eos.saveddata.module import Module
from gui.fitCommands.helpers import restoreCheckedStates
@@ -19,12 +18,11 @@ STATE_MAP = {
class CalcChangeProjectedModuleStatesCommand(wx.Command):
def __init__(self, fitID, positions, proposedState, commit=True):
def __init__(self, fitID, positions, proposedState):
wx.Command.__init__(self, True, 'Change Projected Module States')
self.fitID = fitID
self.positions = positions
self.proposedState = STATE_MAP[proposedState]
self.commit = commit
self.savedStates = {}
self.savedStateCheckChanges = None
@@ -47,8 +45,6 @@ class CalcChangeProjectedModuleStatesCommand(wx.Command):
return False
sFit.recalc(fit)
self.savedStateCheckChanges = sFit.checkStates(fit, None)
if self.commit:
eos.db.commit()
return True
def Undo(self):
@@ -60,6 +56,4 @@ class CalcChangeProjectedModuleStatesCommand(wx.Command):
pyfalog.debug('Reverting projected {} to state {} for fit ID {}'.format(mod, state, self.fitID))
mod.state = state
restoreCheckedStates(fit, self.savedStateCheckChanges)
if self.commit:
eos.db.commit()
return True

View File

@@ -11,11 +11,10 @@ pyfalog = Logger(__name__)
class CalcRemoveProjectedModuleCommand(wx.Command):
def __init__(self, fitID, position, commit=True):
def __init__(self, fitID, position):
wx.Command.__init__(self, True)
self.fitID = fitID
self.position = position
self.commit = commit
self.savedModInfo = None
self.savedStateCheckChanges = None
@@ -32,8 +31,6 @@ class CalcRemoveProjectedModuleCommand(wx.Command):
eos.db.flush()
sFit.recalc(fit)
self.savedStateCheckChanges = sFit.checkStates(fit, None)
if self.commit:
eos.db.commit()
return True
def Undo(self):
@@ -43,11 +40,8 @@ class CalcRemoveProjectedModuleCommand(wx.Command):
fitID=self.fitID,
modInfo=self.savedModInfo,
position=self.position,
ignoreRestrictions=True,
commit=False)
ignoreRestrictions=True)
if not cmd.Do():
return False
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
if self.commit:
eos.db.commit()
return True

View File

@@ -11,13 +11,12 @@ pyfalog = Logger(__name__)
class CalcAddProjectedFitCommand(wx.Command):
def __init__(self, fitID, projectedFitID, amount, state=None, commit=True):
def __init__(self, fitID, projectedFitID, amount, state=None):
wx.Command.__init__(self, True, 'Add Projected Fit')
self.fitID = fitID
self.projectedFitID = projectedFitID
self.amount = amount
self.state = state
self.commit = commit
self.changeAmountCommand = None
self.savedStateCheckChanges = None
@@ -40,14 +39,11 @@ class CalcAddProjectedFitCommand(wx.Command):
fitID=self.fitID,
projectedFitID=self.projectedFitID,
amount=self.amount,
relative=True,
commit=False)
relative=True)
if not self.changeAmountCommand.Do():
return False
sFit.recalc(fit)
self.savedStateCheckChanges = sFit.checkStates(fit, None)
if self.commit:
eos.db.commit()
return True
else:
self.changeAmountCommand = None
@@ -70,8 +66,6 @@ class CalcAddProjectedFitCommand(wx.Command):
sFit.recalc(fit)
self.savedStateCheckChanges = sFit.checkStates(fit, None)
if self.commit:
eos.db.commit()
return True
def Undo(self):
@@ -80,8 +74,6 @@ class CalcAddProjectedFitCommand(wx.Command):
if not self.changeAmountCommand.Undo():
return False
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
if self.commit:
eos.db.commit()
return True
# Can't find the projected fit, it must have been deleted. Just skip, as deleted fit
# means that someone else just did exactly what we wanted to do
@@ -91,11 +83,8 @@ class CalcAddProjectedFitCommand(wx.Command):
cmd = CalcRemoveProjectedFitCommand(
fitID=self.fitID,
projectedFitID=self.projectedFitID,
amount=self.amount,
commit=False)
amount=self.amount)
if not cmd.Do():
return False
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
if self.commit:
eos.db.commit()
return True

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 CalcChangeProjectedFitAmountCommand(wx.Command):
def __init__(self, fitID, projectedFitID, amount, relative=False, commit=True):
def __init__(self, fitID, projectedFitID, amount, relative=False):
wx.Command.__init__(self, True, 'Change Projected Fit Amount')
self.fitID = fitID
self.projectedFitID = projectedFitID
self.amount = amount
self.relative = relative
self.commit = commit
self.savedAmount = None
def Do(self):
@@ -40,8 +38,6 @@ class CalcChangeProjectedFitAmountCommand(wx.Command):
if confinedAmount == self.savedAmount:
return False
projectionInfo.amount = confinedAmount
if self.commit:
eos.db.commit()
return True
def Undo(self):
@@ -49,6 +45,5 @@ class CalcChangeProjectedFitAmountCommand(wx.Command):
cmd = CalcChangeProjectedFitAmountCommand(
fitID=self.fitID,
projectedFitID=self.projectedFitID,
amount=self.savedAmount,
commit=self.commit)
amount=self.savedAmount)
return cmd.Do()

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
@@ -11,12 +10,11 @@ pyfalog = Logger(__name__)
class CalcChangeProjectedFitStateCommand(wx.Command):
def __init__(self, fitID, projectedFitID, state, commit=True):
def __init__(self, fitID, projectedFitID, state):
wx.Command.__init__(self, True, 'Change Projected Fit State')
self.fitID = fitID
self.projectedFitID = projectedFitID
self.state = state
self.commit = commit
self.savedState = None
self.savedStateCheckChanges = None
@@ -43,8 +41,6 @@ class CalcChangeProjectedFitStateCommand(wx.Command):
fit = sFit.getFit(self.fitID)
sFit.recalc(fit)
self.savedStateCheckChanges = sFit.checkStates(fit, None)
if self.commit:
eos.db.commit()
return True
def Undo(self):
@@ -53,11 +49,8 @@ class CalcChangeProjectedFitStateCommand(wx.Command):
cmd = CalcChangeProjectedFitStateCommand(
fitID=self.fitID,
projectedFitID=self.projectedFitID,
state=self.savedState,
commit=False)
state=self.savedState)
if not cmd.Do():
return False
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
if self.commit:
eos.db.commit()
return True

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
@@ -11,12 +10,11 @@ pyfalog = Logger(__name__)
class CalcRemoveProjectedFitCommand(wx.Command):
def __init__(self, fitID, projectedFitID, amount, commit=True):
def __init__(self, fitID, projectedFitID, amount):
wx.Command.__init__(self, True, 'Add Projected Fit')
self.fitID = fitID
self.projectedFitID = projectedFitID
self.amount = amount
self.commit = commit
self.savedState = None
self.savedAmount = None
self.changeAmountCommand = None
@@ -48,14 +46,11 @@ class CalcRemoveProjectedFitCommand(wx.Command):
self.changeAmountCommand = CalcChangeProjectedFitAmountCommand(
fitID=self.fitID,
projectedFitID=self.projectedFitID,
amount=remainingAmount,
commit=False)
amount=remainingAmount)
if not self.changeAmountCommand.Do():
return False
sFit.recalc(fit)
self.savedStateCheckChanges = sFit.checkStates(fit, None)
if self.commit:
eos.db.commit()
return True
else:
self.changeAmountCommand = None
@@ -65,8 +60,6 @@ class CalcRemoveProjectedFitCommand(wx.Command):
del fit.projectedFitDict[projectedFit.ID]
sFit.recalc(fit)
self.savedStateCheckChanges = sFit.checkStates(fit, None)
if self.commit:
eos.db.commit()
return True
def Undo(self):
@@ -75,19 +68,14 @@ class CalcRemoveProjectedFitCommand(wx.Command):
if not self.changeAmountCommand.Undo():
return False
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
if self.commit:
eos.db.commit()
return True
from .add import CalcAddProjectedFitCommand
cmd = CalcAddProjectedFitCommand(
fitID=self.fitID,
projectedFitID=self.projectedFitID,
amount=self.savedAmount,
state=self.savedState,
commit=False)
state=self.savedState)
if not cmd.Do():
return False
restoreCheckedStates(Fit.getInstance().getFit(self.fitID), self.savedStateCheckChanges)
if self.commit:
eos.db.commit()
return True

View File

@@ -1,7 +1,6 @@
import wx
from logbook import Logger
import eos.db
from eos.saveddata.mode import Mode
from service.fit import Fit
from service.market import Market
@@ -25,7 +24,6 @@ class CalcChangeShipModeCommand(wx.Command):
item = Market.getInstance().getItem(self.itemID)
mode = Mode(item)
fit.mode = mode
eos.db.commit()
return True
def Undo(self):

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