diff --git a/eos/graph/__init__.py b/eos/graph/__init__.py
index 77a348e88..59fd0dc61 100644
--- a/eos/graph/__init__.py
+++ b/eos/graph/__init__.py
@@ -47,5 +47,19 @@ class Graph(metaclass=ABCMeta):
yield current
current += step
- def clearCache(self, fitID):
- self.cache.clear()
+ def clearCache(self, fitID=None):
+ if fitID is None:
+ self.cache.clear()
+ elif fitID in self.cache:
+ del self.cache[fitID]
+
+
+class SmoothGraph(Graph, metaclass=ABCMeta):
+
+ def getPlotPoints(self, fit, extraData, xRange, xAmount):
+ xs = []
+ ys = []
+ for x in self._xIter(xRange, xAmount):
+ xs.append(x)
+ ys.append(self.getYForX(fit, extraData, x))
+ return xs, ys
diff --git a/eos/graph/fitCapAmountVsTime.py b/eos/graph/fitCapAmountVsTime.py
index 1b9c25995..16627617d 100644
--- a/eos/graph/fitCapAmountVsTime.py
+++ b/eos/graph/fitCapAmountVsTime.py
@@ -1,23 +1,11 @@
import math
-from eos.graph import Graph
+from eos.graph import SmoothGraph
-class FitCapAmountVsTimeGraph(Graph):
+class FitCapAmountVsTimeGraph(SmoothGraph):
- def getPlotPoints(self, fit, extraData, xRange, xAmount):
- xs = []
- ys = []
- for x in self._xIter(xRange, xAmount):
- xs.append(x)
- ys.append(self.calc(fit, x))
- return xs, {'capAmount': ys}
-
- def getYForX(self, fit, extraData, x):
- return {'capAmount': self.calc(fit, x)}
-
- @staticmethod
- def calc(fit, time):
+ def getYForX(self, fit, extraData, time):
if time < 0:
return 0
maxCap = fit.ship.getModifiedItemAttr('capacitorCapacity')
diff --git a/eos/graph/fitCapRegenVsCapPerc.py b/eos/graph/fitCapRegenVsCapPerc.py
index 81776637f..ff686abea 100644
--- a/eos/graph/fitCapRegenVsCapPerc.py
+++ b/eos/graph/fitCapRegenVsCapPerc.py
@@ -1,23 +1,11 @@
import math
-from eos.graph import Graph
+from eos.graph import SmoothGraph
-class FitCapRegenVsCapPercGraph(Graph):
+class FitCapRegenVsCapPercGraph(SmoothGraph):
- def getPlotPoints(self, fit, extraData, xRange, xAmount):
- xs = []
- ys = []
- for x in self._xIter(xRange, xAmount):
- xs.append(x)
- ys.append(self.calc(fit, x))
- return xs, {'capRegen': ys}
-
- def getYForX(self, fit, extraData, x):
- return {'capRegen': self.calc(fit, x)}
-
- @staticmethod
- def calc(fit, perc):
+ def getYForX(self, fit, extraData, perc):
maxCap = fit.ship.getModifiedItemAttr('capacitorCapacity')
regenTime = fit.ship.getModifiedItemAttr('rechargeRate') / 1000
currentCap = maxCap * perc / 100
diff --git a/eos/graph/fitDistanceVsTime.py b/eos/graph/fitDistanceVsTime.py
new file mode 100644
index 000000000..dcc5ce506
--- /dev/null
+++ b/eos/graph/fitDistanceVsTime.py
@@ -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
diff --git a/eos/graph/fitMobilityVsTime.py b/eos/graph/fitMobilityVsTime.py
deleted file mode 100644
index fc6ad2a08..000000000
--- a/eos/graph/fitMobilityVsTime.py
+++ /dev/null
@@ -1,40 +0,0 @@
-import math
-
-from eos.graph import Graph
-
-
-class FitMobilityVsTimeGraph(Graph):
-
- def getPlotPoints(self, fit, extraData, xRange, xAmount):
- xs = []
- ysSpeed = []
- ysDistance = []
- for x in self._xIter(xRange, xAmount):
- xs.append(x)
- ysSpeed.append(self.calcSpeed(fit, x))
- ysDistance.append(self.calcDistance(fit, x))
- return xs, {'speed': ysSpeed, 'distance': ysDistance}
-
- def getYForX(self, fit, extraData, x):
- return {'speed': self.calcSpeed(fit, x), 'distance': self.calcDistance(fit, x)}
-
- @staticmethod
- def calcSpeed(fit, 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
-
- @staticmethod
- def calcDistance(fit, 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
diff --git a/eos/graph/fitSpeedVsTime.py b/eos/graph/fitSpeedVsTime.py
new file mode 100644
index 000000000..ea19a310a
--- /dev/null
+++ b/eos/graph/fitSpeedVsTime.py
@@ -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
diff --git a/gui/builtinGraphs/fitCapAmountVsTime.py b/gui/builtinGraphs/fitCapAmountVsTime.py
index f5729f9ed..00e30c537 100644
--- a/gui/builtinGraphs/fitCapAmountVsTime.py
+++ b/gui/builtinGraphs/fitCapAmountVsTime.py
@@ -18,6 +18,8 @@
# =============================================================================
+from collections import OrderedDict
+
from eos.graph.fitCapAmountVsTime import FitCapAmountVsTimeGraph as EosGraph
from gui.graph import Graph, XDef, YDef
@@ -31,15 +33,11 @@ class FitCapAmountVsTimeGraph(Graph):
@property
def xDef(self):
- return XDef(handle='time', inputDefault='0-300', inputLabel='Time (seconds)', inputIconID=1392, axisLabel='Time, s')
+ return XDef(inputDefault='0-300', inputLabel='Time (seconds)', inputIconID=1392, axisLabel='Time, s')
@property
def yDefs(self):
- return [YDef(handle='capAmount', switchLabel='Cap amount', axisLabel='Cap amount, GJ')]
-
- def getPlotPoints(self, fit, extraData, xRange, xAmount):
- xRange = self.parseRange(xRange)
- return self.eosGraph.getPlotPoints(fit, extraData, xRange, xAmount)
+ return OrderedDict([('capAmount', YDef(switchLabel='Cap amount', axisLabel='Cap amount, GJ', eosGraph='eosGraph'))])
FitCapAmountVsTimeGraph.register()
diff --git a/gui/builtinGraphs/fitCapRegenVsCapPerc.py b/gui/builtinGraphs/fitCapRegenVsCapPerc.py
index 8431a7e29..41396f498 100644
--- a/gui/builtinGraphs/fitCapRegenVsCapPerc.py
+++ b/gui/builtinGraphs/fitCapRegenVsCapPerc.py
@@ -18,6 +18,8 @@
# =============================================================================
+from collections import OrderedDict
+
from eos.graph.fitCapRegenVsCapPerc import FitCapRegenVsCapPercGraph as EosGraph
from gui.graph import Graph, XDef, YDef
@@ -31,15 +33,11 @@ class FitCapRegenVsCapPercGraph(Graph):
@property
def xDef(self):
- return XDef(handle='percentage', inputDefault='0-100', inputLabel='Cap Amount (percent)', inputIconID=1668, axisLabel='Cap amount, %')
+ return XDef(inputDefault='0-100', inputLabel='Cap Amount (percent)', inputIconID=1668, axisLabel='Cap amount, %')
@property
def yDefs(self):
- return [YDef(handle='capRegen', switchLabel='Cap regen', axisLabel='Cap regen, GJ/s')]
-
- def getPlotPoints(self, fit, extraData, xRange, xAmount):
- xRange = self.parseRange(xRange)
- return self.eosGraph.getPlotPoints(fit, extraData, xRange, xAmount)
+ return OrderedDict([('capRegen', YDef(switchLabel='Cap regen', axisLabel='Cap regen, GJ/s', eosGraph='eosGraph'))])
FitCapRegenVsCapPercGraph.register()
diff --git a/gui/builtinGraphs/fitMobilityVsTime.py b/gui/builtinGraphs/fitMobilityVsTime.py
index e5836497a..24c237b27 100644
--- a/gui/builtinGraphs/fitMobilityVsTime.py
+++ b/gui/builtinGraphs/fitMobilityVsTime.py
@@ -17,7 +17,11 @@
# along with pyfa. If not, see .
# =============================================================================
-from eos.graph.fitMobilityVsTime import FitMobilityVsTimeGraph as EosGraph
+
+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
@@ -26,19 +30,18 @@ class FitMobilityVsTimeGraph(Graph):
name = 'Mobility vs Time'
def __init__(self):
- self.eosGraph = EosGraph()
+ self.eosGraphSpeed = EosGraphSpeed()
+ self.eosGraphDistance = EosGraphDistance()
@property
def xDef(self):
- return XDef(handle='time', inputDefault='0-80', inputLabel='Time (seconds)', inputIconID=1392, axisLabel='Time, s')
+ return XDef(inputDefault='0-80', inputLabel='Time (seconds)', inputIconID=1392, axisLabel='Time, s')
@property
def yDefs(self):
- return [YDef(handle='speed', switchLabel='Speed', axisLabel='Speed, m/s'), YDef(handle='distance', switchLabel='Distance', axisLabel='Distance, m')]
-
- def getPlotPoints(self, fit, extraData, xRange, xAmount):
- xRange = self.parseRange(xRange)
- return self.eosGraph.getPlotPoints(fit, extraData, xRange, xAmount)
+ return OrderedDict([
+ ('speed', YDef(switchLabel='Speed', axisLabel='Speed, m/s', eosGraph='eosGraphSpeed')),
+ ('distance', YDef(switchLabel='Distance', axisLabel='Distance, m', eosGraph='eosGraphDistance'))])
FitMobilityVsTimeGraph.register()
diff --git a/gui/builtinGraphs/fitSpeedTime.py b/gui/builtinGraphs/fitSpeedTime.py
deleted file mode 100644
index 68a0cc36c..000000000
--- a/gui/builtinGraphs/fitSpeedTime.py
+++ /dev/null
@@ -1,81 +0,0 @@
-# =============================================================================
-# Copyright (C) 2010 Diego Duclos
-#
-# This file is part of pyfa.
-#
-# pyfa is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# pyfa is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with pyfa. If not, see .
-# =============================================================================
-
-import gui.mainFrame
-from eos.graph import Data
-from eos.graph.fitSpeedTime import FitSpeedTimeGraph as EosFitSpeedTimeGraph
-from gui.bitmap_loader import BitmapLoader
-from gui.graph import Graph
-from service.attribute import Attribute
-
-
-class FitSpeedTimeGraph(Graph):
-
- propertyLabelMap = {"time": "Time (seconds)"}
-
- defaults = EosFitSpeedTimeGraph.defaults.copy()
-
- def __init__(self):
- Graph.__init__(self)
- self.defaults["time"] = "0-80"
- self.name = "Speed vs Time"
- self.eosGraph = None
- self.mainFrame = gui.mainFrame.MainFrame.getInstance()
-
- def getFields(self):
- return self.defaults
-
- def getLabels(self):
- return self.propertyLabelMap
-
- def getIcons(self):
- iconFile = Attribute.getInstance().getAttributeInfo('duration').iconID
- bitmap = BitmapLoader.getBitmap(iconFile, "icons")
- return {"time": bitmap}
-
- def getPoints(self, fit, fields):
- eosGraph = getattr(self, "eosGraph", None)
- if eosGraph is None or eosGraph.fit != fit:
- eosGraph = self.eosGraph = EosFitSpeedTimeGraph(fit)
-
- eosGraph.clearData()
- variable = None
- for fieldName, value in fields.items():
- d = Data(fieldName, value)
- if not d.isConstant():
- if variable is None:
- variable = fieldName
- else:
- # We can't handle more then one variable atm, OOPS FUCK OUT
- return False, "Can only handle 1 variable"
-
- eosGraph.setData(d)
-
- if variable is None:
- return False, "No variable"
-
- x = []
- y = []
- for point, val in eosGraph.getIterator():
- x.append(point[variable])
- y.append(val)
- return x, y
-
-
-FitSpeedTimeGraph.register()
diff --git a/gui/graph.py b/gui/graph.py
index 3d02915b8..7b75d4688 100644
--- a/gui/graph.py
+++ b/gui/graph.py
@@ -44,7 +44,7 @@ class Graph(metaclass=ABCMeta):
@property
def extraInputs(self):
- return ()
+ return {}
@property
@abstractmethod
@@ -55,6 +55,11 @@ class Graph(metaclass=ABCMeta):
def redrawOnEffectiveChange(self):
return False
+ def getPlotPoints(self, fit, extraData, xRange, xAmount, yType):
+ xRange = self.parseRange(xRange)
+ graph = getattr(self, self.yDefs[yType].eosGraph, None)
+ return graph.getPlotPoints(fit, extraData, xRange, xAmount)
+
def parseRange(self, string):
m = re.match('\s*(?P\d+(\.\d+)?)\s*(-\s*(?P\d+(\.\d+)?))?', string)
if m is None:
@@ -67,8 +72,8 @@ class Graph(metaclass=ABCMeta):
return (float(first), float(second))
-XDef = namedtuple('XDef', ('handle', 'inputDefault', 'inputLabel', 'inputIconID', 'axisLabel'))
-YDef = namedtuple('YDef', ('handle', 'switchLabel', 'axisLabel'))
+XDef = namedtuple('XDef', ('inputDefault', 'inputLabel', 'inputIconID', 'axisLabel'))
+YDef = namedtuple('YDef', ('switchLabel', 'axisLabel', 'eosGraph'))
ExtraInput = namedtuple('ExtraInput', ('handle', 'inputDefault', 'inputLabel', 'inputIconID'))
diff --git a/gui/graphFrame.py b/gui/graphFrame.py
index cf03d203a..dcbf9b884 100644
--- a/gui/graphFrame.py
+++ b/gui/graphFrame.py
@@ -244,9 +244,9 @@ class GraphFrame(wx.Frame):
self.fields.clear()
# Setup textboxes
- for fieldDef in (view.xDef, *view.extraInputs):
+ for fieldHandle, fieldDef in (('x', view.xDef), *view.extraInputs.items()):
textBox = wx.TextCtrl(self.gridPanel, wx.ID_ANY, style=0)
- self.fields[fieldDef.handle] = textBox
+ self.fields[fieldHandle] = textBox
textBox.Bind(wx.EVT_TEXT, self.onFieldChanged)
sizer.Add(textBox, 1, wx.EXPAND | wx.ALIGN_CENTER_VERTICAL | wx.ALL, 3)
if fieldDef.inputDefault is not None:
@@ -293,14 +293,16 @@ class GraphFrame(wx.Frame):
min_y = 0
max_y = 0
- xRange = values[view.xDef.handle]
- extraInputs = {i.handle: values[i.handle] for i in view.extraInputs}
- chosenY = view.yDefs[0].handle
+ xRange = values['x']
+ extraInputs = {ih: values[ih] for ih in view.extraInputs}
+ chosenY = None
+ for handle in view.yDefs:
+ chosenY = handle
+ break
for fit in self.fits:
try:
- xs, ys = view.getPlotPoints(fit, extraInputs, xRange, 100)
- ys = ys[chosenY]
+ xs, ys = view.getPlotPoints(fit, extraInputs, xRange, 100, chosenY)
min_y = min(min_y, min(ys, default=0))
max_y = max(max_y, max(ys, default=0))