diff --git a/eos/graph/__init__.py b/eos/graph/__init__.py index e9a9530e8..55b6ec0e4 100644 --- a/eos/graph/__init__.py +++ b/eos/graph/__init__.py @@ -25,7 +25,7 @@ from abc import ABCMeta, abstractmethod class Graph(metaclass=ABCMeta): def __init__(self): - self.cache = {} + self._cache = {} @abstractmethod def getPlotPoints(self, fit, extraData, xRange, xAmount): @@ -60,9 +60,9 @@ class Graph(metaclass=ABCMeta): def clearCache(self, key=None): if key is None: - self.cache.clear() - elif key in self.cache: - del self.cache[key] + self._cache.clear() + elif key in self._cache: + del self._cache[key] class SmoothGraph(Graph, metaclass=ABCMeta): diff --git a/eos/graph/fitDmgVsTime.py b/eos/graph/fitDmgVsTime.py index a3fdaaeb9..3be53bf29 100644 --- a/eos/graph/fitDmgVsTime.py +++ b/eos/graph/fitDmgVsTime.py @@ -29,12 +29,12 @@ class FitDmgVsTimeGraph(Graph): # 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: + if fit.ID not in self._cache: self.__generateCache(fit, maxX) currentY = None xs = [] ys = [] - cache = self.cache[fit.ID] + cache = self._cache[fit.ID] for time in sorted(cache): prevY = currentY currentX = time / 1000 @@ -74,7 +74,7 @@ class FitDmgVsTimeGraph(Graph): def getYForX(self, fit, extraData, x): time = x * 1000 - cache = self.cache[fit.ID] + cache = self._cache[fit.ID] closestTime = max((t for t in cache if t <= time), default=None) if closestTime is None: return 0 @@ -84,7 +84,7 @@ class FitDmgVsTimeGraph(Graph): return 0, 1000 def __generateCache(self, fit, maxTime): - cache = self.cache[fit.ID] = {} + cache = self._cache[fit.ID] = {} def addDmg(addedTime, addedDmg): if addedDmg == 0: diff --git a/eos/graph/fitDpsVsTime.py b/eos/graph/fitDpsVsTime.py index bb8d2f443..e6a075d27 100644 --- a/eos/graph/fitDpsVsTime.py +++ b/eos/graph/fitDpsVsTime.py @@ -31,12 +31,12 @@ class FitDpsTimeGraph(Graph): # 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: + if fit.ID not in self._cache: self.__generateCache(fit, maxX) currentY = None xs = [] ys = [] - cache = self.cache[fit.ID] + cache = self._cache[fit.ID] for time in sorted(cache): prevY = currentY currentX = time / 1000 @@ -76,7 +76,7 @@ class FitDpsTimeGraph(Graph): def getYForX(self, fit, extraData, x): time = x * 1000 - cache = self.cache[fit.ID] + cache = self._cache[fit.ID] closestTime = max((t for t in cache if t <= time), default=None) if closestTime is None: return 0 @@ -160,4 +160,4 @@ class FitDpsTimeGraph(Graph): 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 + self._cache[fit.ID] = finalCache diff --git a/eos/graph/fitWarpTimeVsDistance.py b/eos/graph/fitWarpTimeVsDistance.py index f30baad02..a16a63ec9 100644 --- a/eos/graph/fitWarpTimeVsDistance.py +++ b/eos/graph/fitWarpTimeVsDistance.py @@ -16,10 +16,10 @@ class FitWarpTimeVsDistanceGraph(SmoothGraph): def getYForX(self, fit, extraData, distance): if distance == 0: return 0 - if fit.ID not in self.cache: + if fit.ID not in self._cache: self.__generateCache(fit) maxWarpSpeed = fit.warpSpeed - subwarpSpeed = self.cache[fit.ID]['cleanSubwarpSpeed'] + subwarpSpeed = self._cache[fit.ID]['cleanSubwarpSpeed'] time = calculate_time_in_warp(maxWarpSpeed, subwarpSpeed, distance * AU_METERS) return time @@ -54,7 +54,7 @@ class FitWarpTimeVsDistanceGraph(SmoothGraph): projFighterStates[fighter] = fighter.active fighter.active = False fit.calculateModifiedAttributes() - self.cache[fit.ID] = {'cleanSubwarpSpeed': fit.ship.getModifiedItemAttr('maxVelocity')} + self._cache[fit.ID] = {'cleanSubwarpSpeed': fit.ship.getModifiedItemAttr('maxVelocity')} for projInfo, state in projFitStates.items(): projInfo.active = state for mod, state in modStates.items(): diff --git a/gui/builtinGraphs/fitCapAmountVsTime.py b/gui/builtinGraphs/fitCapAmountVsTime.py index 00e30c537..e2aa9bbf6 100644 --- a/gui/builtinGraphs/fitCapAmountVsTime.py +++ b/gui/builtinGraphs/fitCapAmountVsTime.py @@ -29,6 +29,7 @@ class FitCapAmountVsTimeGraph(Graph): name = 'Cap Amount vs Time' def __init__(self): + super().__init__() self.eosGraph = EosGraph() @property diff --git a/gui/builtinGraphs/fitCapRegenVsCapPerc.py b/gui/builtinGraphs/fitCapRegenVsCapPerc.py index 88dc4951d..bf6731b8a 100644 --- a/gui/builtinGraphs/fitCapRegenVsCapPerc.py +++ b/gui/builtinGraphs/fitCapRegenVsCapPerc.py @@ -29,6 +29,7 @@ class FitCapRegenVsCapPercGraph(Graph): name = 'Cap Regen vs Cap Amount' def __init__(self): + super().__init__() self.eosGraph = EosGraph() @property diff --git a/gui/builtinGraphs/fitDmgVsTime.py b/gui/builtinGraphs/fitDmgVsTime.py index 98b0d2567..4603e38c6 100644 --- a/gui/builtinGraphs/fitDmgVsTime.py +++ b/gui/builtinGraphs/fitDmgVsTime.py @@ -30,6 +30,7 @@ class FitDmgVsTimeGraph(Graph): name = 'Damage vs Time' def __init__(self): + super().__init__() self.eosGraphDmg = EosGraphDmg() self.eosGraphDps = EosGraphDps() diff --git a/gui/builtinGraphs/fitDpsVsRange.py b/gui/builtinGraphs/fitDpsVsRange.py index fb9509034..9b39a8ed6 100644 --- a/gui/builtinGraphs/fitDpsVsRange.py +++ b/gui/builtinGraphs/fitDpsVsRange.py @@ -29,6 +29,7 @@ class FitDpsVsRangeGraph(Graph): name = 'DPS vs Range' def __init__(self): + super().__init__() self.eosGraph = EosGraph() @property diff --git a/gui/builtinGraphs/fitMobilityVsTime.py b/gui/builtinGraphs/fitMobilityVsTime.py index 24c237b27..1d55f6061 100644 --- a/gui/builtinGraphs/fitMobilityVsTime.py +++ b/gui/builtinGraphs/fitMobilityVsTime.py @@ -30,6 +30,7 @@ class FitMobilityVsTimeGraph(Graph): name = 'Mobility vs Time' def __init__(self): + super().__init__() self.eosGraphSpeed = EosGraphSpeed() self.eosGraphDistance = EosGraphDistance() diff --git a/gui/builtinGraphs/fitShieldAmountVsTime.py b/gui/builtinGraphs/fitShieldAmountVsTime.py index c3464c6f4..d3c58dddd 100644 --- a/gui/builtinGraphs/fitShieldAmountVsTime.py +++ b/gui/builtinGraphs/fitShieldAmountVsTime.py @@ -30,6 +30,7 @@ class FitShieldAmountVsTimeGraph(Graph): name = 'Shield Amount vs Time' def __init__(self): + super().__init__() self.eosGraph = EosGraph() self.mainFrame = gui.mainFrame.MainFrame.getInstance() diff --git a/gui/builtinGraphs/fitShieldRegenVsShieldPerc.py b/gui/builtinGraphs/fitShieldRegenVsShieldPerc.py index 6fcbe3a0c..e684688ba 100644 --- a/gui/builtinGraphs/fitShieldRegenVsShieldPerc.py +++ b/gui/builtinGraphs/fitShieldRegenVsShieldPerc.py @@ -30,6 +30,7 @@ class FitShieldRegenVsShieldPercGraph(Graph): name = 'Shield Regen vs Shield Amount' def __init__(self): + super().__init__() self.eosGraph = EosGraph() self.mainFrame = gui.mainFrame.MainFrame.getInstance() diff --git a/gui/builtinGraphs/fitWarpTimeVsDistance.py b/gui/builtinGraphs/fitWarpTimeVsDistance.py index 16246ee92..b3f479a2c 100644 --- a/gui/builtinGraphs/fitWarpTimeVsDistance.py +++ b/gui/builtinGraphs/fitWarpTimeVsDistance.py @@ -29,6 +29,7 @@ class FitWarpTimeVsDistanceGraph(Graph): name = 'Warp Time vs Distance' def __init__(self): + super().__init__() self.eosGraph = EosGraph() @property diff --git a/gui/graph.py b/gui/graph.py index ffbd92578..bd1ef1f40 100644 --- a/gui/graph.py +++ b/gui/graph.py @@ -32,6 +32,9 @@ class Graph(metaclass=ABCMeta): def register(cls): Graph.views.append(cls) + def __init__(self): + self._cache = {} + @property @abstractmethod def name(self): @@ -56,10 +59,16 @@ class Graph(metaclass=ABCMeta): return False def getPlotPoints(self, fit, extraData, xRange, xAmount, yType): - xRange = self.parseRange(xRange) - extraData = {k: float(v) if v else None for k, v in extraData.items()} - graph = getattr(self, self.yDefs[yType].eosGraph, None) - return graph.getPlotPoints(fit, extraData, xRange, xAmount) + try: + plotData = self._cache[fit.ID][yType] + except KeyError: + xRange = self.parseRange(xRange) + extraData = {k: float(v) if v else None for k, v in extraData.items()} + graph = getattr(self, self.yDefs[yType].eosGraph, None) + plotData = graph.getPlotPoints(fit, extraData, xRange, xAmount) + fitCache = self._cache.setdefault(fit.ID, {}) + fitCache[yType] = plotData + return plotData def parseRange(self, string): m = re.match('\s*(?P\d+(\.\d+)?)\s*(-\s*(?P\d+(\.\d+)?))?', string) @@ -72,9 +81,13 @@ class Graph(metaclass=ABCMeta): high = max(first, second) return (low, high) - def clearCache(self, *args, **kwargs): + def clearCache(self, key=None): + if key is None: + self._cache.clear() + elif key in self._cache: + del self._cache[key] for yDef in self.yDefs.values(): - getattr(self, yDef.eosGraph).clearCache(*args, **kwargs) + getattr(self, yDef.eosGraph).clearCache(key=key) XDef = namedtuple('XDef', ('inputDefault', 'inputLabel', 'inputIconID', 'axisLabel'))