From 93e7b4f5cfba519810ad9126d9e644ef0dfb06a8 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Wed, 15 Feb 2017 17:23:53 -0800 Subject: [PATCH 01/13] Cherry pick d033e4a8d919664d3ae210098291e38df71d3256 --- eos/saveddata/module.py | 9 ++ gui/builtinStatsViews/__init__.py | 2 +- gui/builtinStatsViews/outgoingViewFull.py | 153 ++++++++++++++++++++++ 3 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 gui/builtinStatsViews/outgoingViewFull.py diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index ba41d559d..f211ce4bc 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -701,6 +701,15 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): else: return 0 + def getAmountPerSec(self, attribute): + amount = self.getModifiedItemAttr(attribute) + if not amount: + return 0 + cycleTime = self.cycleTime + if not cycleTime: + return 0 + return float(amount) * 1000 / cycleTime + def __deepcopy__(self, memo): item = self.item if item is None: diff --git a/gui/builtinStatsViews/__init__.py b/gui/builtinStatsViews/__init__.py index 5f2ca646e..7161d1c38 100644 --- a/gui/builtinStatsViews/__init__.py +++ b/gui/builtinStatsViews/__init__.py @@ -1,3 +1,3 @@ __all__ = ["resourcesViewFull", "resistancesViewFull", - "rechargeViewFull", "firepowerViewFull", "capacitorViewFull", + "rechargeViewFull", "firepowerViewFull", "capacitorViewFull", "outgoingViewFull", "targetingMiscViewFull", "priceViewFull", "miningyieldViewFull"] diff --git a/gui/builtinStatsViews/outgoingViewFull.py b/gui/builtinStatsViews/outgoingViewFull.py new file mode 100644 index 000000000..75734e24e --- /dev/null +++ b/gui/builtinStatsViews/outgoingViewFull.py @@ -0,0 +1,153 @@ +#=============================================================================== +# Copyright (C) 2014 Alexandros Kosiaris +# +# 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 wx +import service +import gui.mainFrame +from gui.statsView import StatsView +from gui import bitmapLoader +from gui.utils.numberFormatter import formatAmount + +class OutgoingViewFull(StatsView): + name = "outgoingViewFull" + def __init__(self, parent): + StatsView.__init__(self) + self.parent = parent + self._cachedValues = [] + def getHeaderText(self, fit): + return "Outgoing" + + def getTextExtentW(self, text): + width, height = self.parent.GetTextExtent( text ) + return width + + def populatePanel(self, contentPanel, headerPanel): + contentSizer = contentPanel.GetSizer() + parent = self.panel = contentPanel + self.headerPanel = headerPanel + + panel = "full" + + sizerOutgoing = wx.FlexGridSizer(1, 6) + sizerOutgoing.AddGrowableCol(1) + + contentSizer.Add( sizerOutgoing, 0, wx.EXPAND, 0) + + counter = 0 + + for outgoingType, label, image in (("remoteArmor","Armor RR","armorActive") , ("remoteShield","Shield RR","shieldActive")): + baseBox = wx.BoxSizer(wx.HORIZONTAL) + sizerOutgoing.Add(baseBox, 1, wx.ALIGN_LEFT if counter == 0 else wx.ALIGN_CENTER_HORIZONTAL) + + baseBox.Add(bitmapLoader.getStaticBitmap("%s_big" % image, parent, "icons"), 0, wx.ALIGN_CENTER) + + box = wx.BoxSizer(wx.VERTICAL) + baseBox.Add(box, 0, wx.ALIGN_CENTER) + + box.Add(wx.StaticText(parent, wx.ID_ANY, label), 0, wx.ALIGN_LEFT) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + box.Add(hbox, 1, wx.ALIGN_CENTER) + + lbl = wx.StaticText(parent, wx.ID_ANY, u"0.0 HP/s") + setattr(self, "label%soutgoing%s" % (panel.capitalize() ,outgoingType.capitalize()), lbl) + + hbox.Add(lbl, 0, wx.ALIGN_CENTER) + self._cachedValues.append(0) + counter += 1 + + targetSizer = sizerOutgoing + + baseBox = wx.BoxSizer(wx.HORIZONTAL) + targetSizer.Add(baseBox, 0, wx.ALIGN_RIGHT) + + baseBox.Add(bitmapLoader.getStaticBitmap("capacitorInfo_big", parent, "icons"), 0, wx.ALIGN_CENTER) + + gridS = wx.GridSizer(2,2,0,0) + + baseBox.Add(gridS, 0) + + lbl = wx.StaticText(parent, wx.ID_ANY, "0.0 GJ/s") + setattr(self, "label%soutgoingRemotecapacitor" % panel.capitalize(), lbl) + gridS.Add(wx.StaticText(parent, wx.ID_ANY, " +CAP: "), 0, wx.ALL | wx.ALIGN_RIGHT) + gridS.Add(lbl, 0, wx.ALIGN_LEFT) + + self._cachedValues.append(0) + + lbl = wx.StaticText(parent, wx.ID_ANY, "0.0 GJ/s") + setattr(self, "label%soutgoingNeuting" % panel.capitalize(), lbl) + gridS.Add(wx.StaticText(parent, wx.ID_ANY, " Neut: "), 0, wx.ALL | wx.ALIGN_RIGHT) + + self._cachedValues.append(0) + + gridS.Add(lbl, 0, wx.ALIGN_LEFT) + + image = bitmapLoader.getBitmap("turret_small", "icons") + firepower = wx.BitmapButton(contentPanel, -1, image) + firepower.SetToolTip(wx.ToolTip("Click to toggle to Firepower View")) + firepower.Bind(wx.EVT_BUTTON, self.switchToFirepowerView) + sizerOutgoing.Add(firepower, 0, wx.ALIGN_LEFT) + + self._cachedValues.append(0) + + def switchToFirepowerView(self, event): + # Getting the active fit + mainFrame = gui.mainFrame.MainFrame.getInstance() + sFit = service.Fit.getInstance() + fit = sFit.getFit(mainFrame.getActiveFit()) + # Remove ourselves from statsPane's view list + self.parent.views.remove(self) + self._cachedValues = [] + # And no longer display us + self.panel.GetSizer().Clear(True) + self.panel.GetSizer().Layout() + # Get the new view + view = StatsView.getView("firepowerViewFull")(self.parent) + view.populatePanel(self.panel, self.headerPanel) + # Populate us in statsPane's view list + self.parent.views.append(view) + # Get the TogglePanel + tp = self.panel.GetParent() + tp.SetLabel(view.getHeaderText(fit)) + view.refreshPanel(fit) + + def refreshPanel(self, fit): + #If we did anything intresting, we'd update our labels to reflect the new fit's stats here + + stats = (("labelFulloutgoingRemotearmor", lambda: fit.armorRR, 3, 0, 0, u"%s HP/s", None), + ("labelFulloutgoingRemoteshield", lambda: fit.shieldRR, 3, 0, 0, u"%s HP/s", None), + ("labelFulloutgoingRemotecapacitor", lambda: fit.captransfer, 3, 0, 0, u"%s GJ/s",None), + ("labelFulloutgoingNeuting", lambda: fit.neut, 3, 0, 0, u"%s GJ/s", None)) + + counter = 0 + for labelName, value, prec, lowest, highest, valueFormat, altFormat in stats: + label = getattr(self, labelName) + value = value() if fit is not None else 0 + value = value if value is not None else 0 + if self._cachedValues[counter] != value: + valueStr = formatAmount(value, prec, lowest, highest) + label.SetLabel(valueFormat % valueStr) + tipStr = valueFormat % valueStr if altFormat is None else altFormat % value + label.SetToolTip(wx.ToolTip(tipStr)) + self._cachedValues[counter] = value + counter +=1 + self.panel.Layout() + self.headerPanel.Layout() + +OutgoingViewFull.register() From 25b17a221c6377acf05771702eac7a425539a307 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Wed, 15 Feb 2017 18:23:14 -0800 Subject: [PATCH 02/13] Update to current version --- eos/saveddata/module.py | 9 --------- 1 file changed, 9 deletions(-) diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index f211ce4bc..ba41d559d 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -701,15 +701,6 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): else: return 0 - def getAmountPerSec(self, attribute): - amount = self.getModifiedItemAttr(attribute) - if not amount: - return 0 - cycleTime = self.cycleTime - if not cycleTime: - return 0 - return float(amount) * 1000 / cycleTime - def __deepcopy__(self, memo): item = self.item if item is None: From 6e047074576d204228f6fc7560e61fd6e39761ef Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Wed, 15 Feb 2017 18:25:11 -0800 Subject: [PATCH 03/13] Commit *ALL* the files. --- eos/saveddata/fit.py | 85 ++++++++++++++++++++++++++++++++++++++++++++ gui/statsPane.py | 2 +- gui/statsView.py | 1 + 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index de245e185..07960928d 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -18,6 +18,7 @@ # =============================================================================== import time +import math from copy import deepcopy from itertools import chain from math import sqrt, log, asinh @@ -127,6 +128,12 @@ class Fit(object): self.__capUsed = None self.__capRecharge = None self.__calculatedTargets = [] + self.__remoteReps = { + "Armor": 0, + "Shield": 0, + "Hull": 0, + "Capacitor": 0, + } self.factorReload = False self.boostsFits = set() self.gangBoosts = None @@ -392,6 +399,9 @@ class Fit(object): self.ecmProjectedStr = 1 self.commandBonuses = {} + for remoterep_type in ("Armor", "Shield", "Hull", "Capacitor"): + self.__remoteReps[remoterep_type] = 0 + del self.__calculatedTargets[:] del self.__extraDrains[:] @@ -1147,6 +1157,81 @@ class Fit(object): self.__capStable = True self.__capState = 100 + @property + def remoteReps(self): + def amount_per_second(module_amount, module_duration, module_reload, module_chargerate, module_capacity, module_volume): + numcycles = math.floor(module_capacity / (module_volume * module_chargerate)) + + module_amount *= numcycles + module_duration = module_chargerate * numcycles + module_reload + + return module_amount / module_duration + + for module in self.modules: + # Skip empty modules + if module.isEmpty: + continue + + module_group = getattr(module.item.group, "name") + + # Skip modules that aren't online + if getattr(module, "state", 0) < 1: + continue + + if module_group in ("Remote Armor Repairer", "Ancillary Remote Armor Repairer"): + # Remote Armor Reppers + hp = module.getModifiedItemAttr("armorDamageAmount", 0) + duration = module.getModifiedItemAttr("duration", 0) / 1000 + reloadTime = module.getModifiedItemAttr("reloadTime", 0) / 1000 + chargeRate = module.getModifiedItemAttr("chargeRate", 1) + fueledMultiplier = module.getModifiedItemAttr("chargedArmorDamageMultiplier", 1) + capacity = module.getModifiedItemAttr("capacity", 0) + volume = module.getModifiedChargeAttr("volume", 0) + + if module.charge: + hp *= fueledMultiplier + hp_per_s = amount_per_second(hp, duration, reloadTime, chargeRate, capacity, volume) + else: + hp_per_s = hp / duration + + self.__remoteReps["Armor"] += hp_per_s + + elif module_group in ("Remote Hull Repairer",): + # Remote Hull Reppers + hp = module.getModifiedItemAttr("structureDamageAmount", 0) + duration = module.getModifiedItemAttr("duration", 0) / 1000 + + hp_per_s = hp / duration + + self.__remoteReps["Hull"] += hp_per_s + + elif module_group in ("Remote Shield Booster", "Ancillary Remote Shield Booster"): + # Remote Shield Reppers + hp = module.getModifiedItemAttr("shieldBonus", 0) + duration = module.getModifiedItemAttr("duration", 0) / 1000 + reloadTime = module.getModifiedItemAttr("reloadTime", 0) / 1000 + chargeRate = module.getModifiedItemAttr("chargeRate", 1) + capacity = module.getModifiedItemAttr("capacity", 0) + volume = module.getModifiedChargeAttr("volume", 0) + + if module.charge: + hp_per_s = amount_per_second(hp, duration, reloadTime, chargeRate, capacity, volume) + else: + hp_per_s = hp / duration + + self.__remoteReps["Shield"] += hp_per_s + + elif module_group in ("Remote Capacitor Transmitter",): + # Remote Capacitor Boosters + hp = module.getModifiedItemAttr("powerTransferAmount", 0) + duration = module.getModifiedItemAttr("duration", 0) / 1000 + + hp_per_s = hp / duration + + self.__remoteReps["Capacitor"] += hp_per_s + + return self.__remoteReps + @property def hp(self): hp = {} diff --git a/gui/statsPane.py b/gui/statsPane.py index 6aaf277f5..c86786f97 100644 --- a/gui/statsPane.py +++ b/gui/statsPane.py @@ -33,7 +33,7 @@ from gui.pyfatogglepanel import TogglePanel class StatsPane(wx.Panel): DEFAULT_VIEWS = ["resourcesViewFull", "resistancesViewFull", "rechargeViewFull", "firepowerViewFull", "capacitorViewFull", "targetingmiscViewFull", - "priceViewFull"] + "priceViewFull", "outgoingViewFull"] def fitChanged(self, event): sFit = Fit.getInstance() diff --git a/gui/statsView.py b/gui/statsView.py index 773063ca4..dbdb6da3c 100644 --- a/gui/statsView.py +++ b/gui/statsView.py @@ -52,4 +52,5 @@ from gui.builtinStatsViews import ( # noqa: E402, F401 rechargeViewFull, targetingMiscViewFull, priceViewFull, + outgoingViewFull, ) From 13996d777076149d50c8d6ca01959741151c56b1 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Wed, 15 Feb 2017 18:50:35 -0800 Subject: [PATCH 04/13] Stupid change list making me miss files. --- gui/builtinStatsViews/outgoingViewFull.py | 121 +++++++--------------- 1 file changed, 37 insertions(+), 84 deletions(-) diff --git a/gui/builtinStatsViews/outgoingViewFull.py b/gui/builtinStatsViews/outgoingViewFull.py index 75734e24e..5a693aae9 100644 --- a/gui/builtinStatsViews/outgoingViewFull.py +++ b/gui/builtinStatsViews/outgoingViewFull.py @@ -1,4 +1,4 @@ -#=============================================================================== +# =============================================================================== # Copyright (C) 2014 Alexandros Kosiaris # # This file is part of pyfa. @@ -15,26 +15,28 @@ # # You should have received a copy of the GNU General Public License # along with pyfa. If not, see . -#=============================================================================== +# =============================================================================== +# noinspection PyPackageRequirements import wx -import service -import gui.mainFrame from gui.statsView import StatsView -from gui import bitmapLoader +from gui.bitmapLoader import BitmapLoader from gui.utils.numberFormatter import formatAmount + class OutgoingViewFull(StatsView): name = "outgoingViewFull" + def __init__(self, parent): StatsView.__init__(self) self.parent = parent self._cachedValues = [] + def getHeaderText(self, fit): - return "Outgoing" + return "Remote Reps" def getTextExtentW(self, text): - width, height = self.parent.GetTextExtent( text ) + width, height = self.parent.GetTextExtent(text) return width def populatePanel(self, contentPanel, headerPanel): @@ -44,96 +46,46 @@ class OutgoingViewFull(StatsView): panel = "full" - sizerOutgoing = wx.FlexGridSizer(1, 6) - sizerOutgoing.AddGrowableCol(1) + sizerOutgoing = wx.GridSizer(1, 4) - contentSizer.Add( sizerOutgoing, 0, wx.EXPAND, 0) + contentSizer.Add(sizerOutgoing, 0, wx.EXPAND, 0) counter = 0 - for outgoingType, label, image in (("remoteArmor","Armor RR","armorActive") , ("remoteShield","Shield RR","shieldActive")): - baseBox = wx.BoxSizer(wx.HORIZONTAL) - sizerOutgoing.Add(baseBox, 1, wx.ALIGN_LEFT if counter == 0 else wx.ALIGN_CENTER_HORIZONTAL) + rr_list = [ + ("RemoteArmor", "Armor RR", "armorActive"), + ("RemoteShield", "Shield RR", "shieldActive"), + ("RemoteHull", "Hull RR", "hullActive"), + ("RemoteCapacitor", "Capacitor RR", "capacitorInfo"), + ] - baseBox.Add(bitmapLoader.getStaticBitmap("%s_big" % image, parent, "icons"), 0, wx.ALIGN_CENTER) + for outgoingType, label, image in rr_list: + baseBox = wx.BoxSizer(wx.VERTICAL) - box = wx.BoxSizer(wx.VERTICAL) - baseBox.Add(box, 0, wx.ALIGN_CENTER) + baseBox.Add(BitmapLoader.getStaticBitmap("%s_big" % image, parent, "gui"), 0, wx.ALIGN_CENTER) - box.Add(wx.StaticText(parent, wx.ID_ANY, label), 0, wx.ALIGN_LEFT) + if "Capacitor" in label: + lbl = wx.StaticText(parent, wx.ID_ANY, u"0 GJ/s") + else: + lbl = wx.StaticText(parent, wx.ID_ANY, u"0 HP/s") - hbox = wx.BoxSizer(wx.HORIZONTAL) - box.Add(hbox, 1, wx.ALIGN_CENTER) + setattr(self, "label%s" % outgoingType, lbl) - lbl = wx.StaticText(parent, wx.ID_ANY, u"0.0 HP/s") - setattr(self, "label%soutgoing%s" % (panel.capitalize() ,outgoingType.capitalize()), lbl) - - hbox.Add(lbl, 0, wx.ALIGN_CENTER) + baseBox.Add(lbl, 0, wx.ALIGN_CENTER) self._cachedValues.append(0) counter += 1 - targetSizer = sizerOutgoing - - baseBox = wx.BoxSizer(wx.HORIZONTAL) - targetSizer.Add(baseBox, 0, wx.ALIGN_RIGHT) - - baseBox.Add(bitmapLoader.getStaticBitmap("capacitorInfo_big", parent, "icons"), 0, wx.ALIGN_CENTER) - - gridS = wx.GridSizer(2,2,0,0) - - baseBox.Add(gridS, 0) - - lbl = wx.StaticText(parent, wx.ID_ANY, "0.0 GJ/s") - setattr(self, "label%soutgoingRemotecapacitor" % panel.capitalize(), lbl) - gridS.Add(wx.StaticText(parent, wx.ID_ANY, " +CAP: "), 0, wx.ALL | wx.ALIGN_RIGHT) - gridS.Add(lbl, 0, wx.ALIGN_LEFT) - - self._cachedValues.append(0) - - lbl = wx.StaticText(parent, wx.ID_ANY, "0.0 GJ/s") - setattr(self, "label%soutgoingNeuting" % panel.capitalize(), lbl) - gridS.Add(wx.StaticText(parent, wx.ID_ANY, " Neut: "), 0, wx.ALL | wx.ALIGN_RIGHT) - - self._cachedValues.append(0) - - gridS.Add(lbl, 0, wx.ALIGN_LEFT) - - image = bitmapLoader.getBitmap("turret_small", "icons") - firepower = wx.BitmapButton(contentPanel, -1, image) - firepower.SetToolTip(wx.ToolTip("Click to toggle to Firepower View")) - firepower.Bind(wx.EVT_BUTTON, self.switchToFirepowerView) - sizerOutgoing.Add(firepower, 0, wx.ALIGN_LEFT) - - self._cachedValues.append(0) - - def switchToFirepowerView(self, event): - # Getting the active fit - mainFrame = gui.mainFrame.MainFrame.getInstance() - sFit = service.Fit.getInstance() - fit = sFit.getFit(mainFrame.getActiveFit()) - # Remove ourselves from statsPane's view list - self.parent.views.remove(self) - self._cachedValues = [] - # And no longer display us - self.panel.GetSizer().Clear(True) - self.panel.GetSizer().Layout() - # Get the new view - view = StatsView.getView("firepowerViewFull")(self.parent) - view.populatePanel(self.panel, self.headerPanel) - # Populate us in statsPane's view list - self.parent.views.append(view) - # Get the TogglePanel - tp = self.panel.GetParent() - tp.SetLabel(view.getHeaderText(fit)) - view.refreshPanel(fit) + sizerOutgoing.Add(baseBox, 1, wx.ALIGN_LEFT) def refreshPanel(self, fit): - #If we did anything intresting, we'd update our labels to reflect the new fit's stats here + # If we did anything intresting, we'd update our labels to reflect the new fit's stats here - stats = (("labelFulloutgoingRemotearmor", lambda: fit.armorRR, 3, 0, 0, u"%s HP/s", None), - ("labelFulloutgoingRemoteshield", lambda: fit.shieldRR, 3, 0, 0, u"%s HP/s", None), - ("labelFulloutgoingRemotecapacitor", lambda: fit.captransfer, 3, 0, 0, u"%s GJ/s",None), - ("labelFulloutgoingNeuting", lambda: fit.neut, 3, 0, 0, u"%s GJ/s", None)) + stats = [ + ("labelRemoteArmor", lambda: fit.remoteReps["Armor"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteShield", lambda: fit.remoteReps["Shield"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteHull", lambda: fit.remoteReps["Hull"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteCapacitor", lambda: fit.remoteReps["Capacitor"], 3, 0, 0, u"%s GJ/s", None), + ] counter = 0 for labelName, value, prec, lowest, highest, valueFormat, altFormat in stats: @@ -146,8 +98,9 @@ class OutgoingViewFull(StatsView): tipStr = valueFormat % valueStr if altFormat is None else altFormat % value label.SetToolTip(wx.ToolTip(tipStr)) self._cachedValues[counter] = value - counter +=1 + counter += 1 self.panel.Layout() self.headerPanel.Layout() - + + OutgoingViewFull.register() From eb97a1c11cd93dfff6e1e50891df985293197861 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Wed, 15 Feb 2017 19:11:32 -0800 Subject: [PATCH 05/13] Add tooltip and also a minimal version of the view (for future state). --- gui/builtinStatsViews/outgoingViewFull.py | 14 +-- gui/builtinStatsViews/outgoingViewMinimal.py | 108 +++++++++++++++++++ 2 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 gui/builtinStatsViews/outgoingViewMinimal.py diff --git a/gui/builtinStatsViews/outgoingViewFull.py b/gui/builtinStatsViews/outgoingViewFull.py index 5a693aae9..945edd4fe 100644 --- a/gui/builtinStatsViews/outgoingViewFull.py +++ b/gui/builtinStatsViews/outgoingViewFull.py @@ -53,22 +53,24 @@ class OutgoingViewFull(StatsView): counter = 0 rr_list = [ - ("RemoteArmor", "Armor RR", "armorActive"), - ("RemoteShield", "Shield RR", "shieldActive"), - ("RemoteHull", "Hull RR", "hullActive"), - ("RemoteCapacitor", "Capacitor RR", "capacitorInfo"), + ("RemoteArmor", "Armor:", "armorActive", "Armor hitpoints per second repaired remotely."), + ("RemoteShield", "Shield:", "shieldActive", "Shield hitpoints per second repaired remotely."), + ("RemoteHull", "Hull:", "hullActive", "Hull hitpoints per second repaired remotely."), + ("RemoteCapacitor", "Capacitor:", "capacitorInfo", "Capacitor GJ/s per second transferred remotely."), ] - for outgoingType, label, image in rr_list: + for outgoingType, label, image, tooltip in rr_list: baseBox = wx.BoxSizer(wx.VERTICAL) baseBox.Add(BitmapLoader.getStaticBitmap("%s_big" % image, parent, "gui"), 0, wx.ALIGN_CENTER) - if "Capacitor" in label: + if "Capacitor" in outgoingType: lbl = wx.StaticText(parent, wx.ID_ANY, u"0 GJ/s") else: lbl = wx.StaticText(parent, wx.ID_ANY, u"0 HP/s") + lbl.SetToolTip(wx.ToolTip(tooltip)) + setattr(self, "label%s" % outgoingType, lbl) baseBox.Add(lbl, 0, wx.ALIGN_CENTER) diff --git a/gui/builtinStatsViews/outgoingViewMinimal.py b/gui/builtinStatsViews/outgoingViewMinimal.py new file mode 100644 index 000000000..945edd4fe --- /dev/null +++ b/gui/builtinStatsViews/outgoingViewMinimal.py @@ -0,0 +1,108 @@ +# =============================================================================== +# Copyright (C) 2014 Alexandros Kosiaris +# +# 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 . +# =============================================================================== + +# noinspection PyPackageRequirements +import wx +from gui.statsView import StatsView +from gui.bitmapLoader import BitmapLoader +from gui.utils.numberFormatter import formatAmount + + +class OutgoingViewFull(StatsView): + name = "outgoingViewFull" + + def __init__(self, parent): + StatsView.__init__(self) + self.parent = parent + self._cachedValues = [] + + def getHeaderText(self, fit): + return "Remote Reps" + + def getTextExtentW(self, text): + width, height = self.parent.GetTextExtent(text) + return width + + def populatePanel(self, contentPanel, headerPanel): + contentSizer = contentPanel.GetSizer() + parent = self.panel = contentPanel + self.headerPanel = headerPanel + + panel = "full" + + sizerOutgoing = wx.GridSizer(1, 4) + + contentSizer.Add(sizerOutgoing, 0, wx.EXPAND, 0) + + counter = 0 + + rr_list = [ + ("RemoteArmor", "Armor:", "armorActive", "Armor hitpoints per second repaired remotely."), + ("RemoteShield", "Shield:", "shieldActive", "Shield hitpoints per second repaired remotely."), + ("RemoteHull", "Hull:", "hullActive", "Hull hitpoints per second repaired remotely."), + ("RemoteCapacitor", "Capacitor:", "capacitorInfo", "Capacitor GJ/s per second transferred remotely."), + ] + + for outgoingType, label, image, tooltip in rr_list: + baseBox = wx.BoxSizer(wx.VERTICAL) + + baseBox.Add(BitmapLoader.getStaticBitmap("%s_big" % image, parent, "gui"), 0, wx.ALIGN_CENTER) + + if "Capacitor" in outgoingType: + lbl = wx.StaticText(parent, wx.ID_ANY, u"0 GJ/s") + else: + lbl = wx.StaticText(parent, wx.ID_ANY, u"0 HP/s") + + lbl.SetToolTip(wx.ToolTip(tooltip)) + + setattr(self, "label%s" % outgoingType, lbl) + + baseBox.Add(lbl, 0, wx.ALIGN_CENTER) + self._cachedValues.append(0) + counter += 1 + + sizerOutgoing.Add(baseBox, 1, wx.ALIGN_LEFT) + + def refreshPanel(self, fit): + # If we did anything intresting, we'd update our labels to reflect the new fit's stats here + + stats = [ + ("labelRemoteArmor", lambda: fit.remoteReps["Armor"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteShield", lambda: fit.remoteReps["Shield"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteHull", lambda: fit.remoteReps["Hull"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteCapacitor", lambda: fit.remoteReps["Capacitor"], 3, 0, 0, u"%s GJ/s", None), + ] + + counter = 0 + for labelName, value, prec, lowest, highest, valueFormat, altFormat in stats: + label = getattr(self, labelName) + value = value() if fit is not None else 0 + value = value if value is not None else 0 + if self._cachedValues[counter] != value: + valueStr = formatAmount(value, prec, lowest, highest) + label.SetLabel(valueFormat % valueStr) + tipStr = valueFormat % valueStr if altFormat is None else altFormat % value + label.SetToolTip(wx.ToolTip(tipStr)) + self._cachedValues[counter] = value + counter += 1 + self.panel.Layout() + self.headerPanel.Layout() + + +OutgoingViewFull.register() From 5ca882d3eafd99b083cdd7c730d547c9c6aa0bbf Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Fri, 24 Feb 2017 13:06:02 -0800 Subject: [PATCH 06/13] implement a suggestion from @blitzmann --- eos/saveddata/fit.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 07960928d..5e40aff80 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -399,7 +399,7 @@ class Fit(object): self.ecmProjectedStr = 1 self.commandBonuses = {} - for remoterep_type in ("Armor", "Shield", "Hull", "Capacitor"): + for remoterep_type in self.__remoteReps: self.__remoteReps[remoterep_type] = 0 del self.__calculatedTargets[:] From 3892ac5996be5b5d21ca8f7962b211e5557d08ed Mon Sep 17 00:00:00 2001 From: blitzman Date: Fri, 24 Feb 2017 18:33:42 -0500 Subject: [PATCH 07/13] Change functionality of remote rep calculations to be more efficient. * Implement a property per attribute * Use None as our cleared value (signifies that it really hasn't been calculated, not just that the calc was 0) --- eos/saveddata/fit.py | 51 +++++++++++++++----- gui/builtinStatsViews/outgoingViewFull.py | 8 +-- gui/builtinStatsViews/outgoingViewMinimal.py | 8 +-- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 5e40aff80..c6cbd7c0c 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -129,10 +129,10 @@ class Fit(object): self.__capRecharge = None self.__calculatedTargets = [] self.__remoteReps = { - "Armor": 0, - "Shield": 0, - "Hull": 0, - "Capacitor": 0, + "Armor": None, + "Shield": None, + "Hull": None, + "Capacitor": None, } self.factorReload = False self.boostsFits = set() @@ -307,6 +307,34 @@ class Fit(object): def totalYield(self): return self.droneYield + self.minerYield + @property + def armorRR(self): + if self.__remoteReps["Armor"] is None: + self.calculateRemoteReps() + + return self.__remoteReps["Armor"] + + @property + def shieldRR(self): + if self.__remoteReps["Shield"] is None: + self.calculateRemoteReps() + + return self.__remoteReps["Shield"] + + @property + def hullRR(self): + if self.__remoteReps["Hull"] is None: + self.calculateRemoteReps() + + return self.__remoteReps["Hull"] + + @property + def capTransfer(self): + if self.__remoteReps["Capacitor"] is None: + self.calculateRemoteReps() + + return self.__remoteReps["Capacitor"] + @property def maxTargets(self): return min(self.extraAttributes["maxTargetsLockedFromSkills"], @@ -400,7 +428,7 @@ class Fit(object): self.commandBonuses = {} for remoterep_type in self.__remoteReps: - self.__remoteReps[remoterep_type] = 0 + self.__remoteReps[remoterep_type] = None del self.__calculatedTargets[:] del self.__extraDrains[:] @@ -1157,8 +1185,7 @@ class Fit(object): self.__capStable = True self.__capState = 100 - @property - def remoteReps(self): + def calculateRemoteReps(self): def amount_per_second(module_amount, module_duration, module_reload, module_chargerate, module_capacity, module_volume): numcycles = math.floor(module_capacity / (module_volume * module_chargerate)) @@ -1167,15 +1194,19 @@ class Fit(object): return module_amount / module_duration + for remoterep_type in self.__remoteReps: + # Set all to 0 + self.__remoteReps[remoterep_type] = 0 + for module in self.modules: # Skip empty modules if module.isEmpty: continue - module_group = getattr(module.item.group, "name") + module_group = module.item.group.name # Skip modules that aren't online - if getattr(module, "state", 0) < 1: + if module.state < State.ACTIVE: continue if module_group in ("Remote Armor Repairer", "Ancillary Remote Armor Repairer"): @@ -1230,8 +1261,6 @@ class Fit(object): self.__remoteReps["Capacitor"] += hp_per_s - return self.__remoteReps - @property def hp(self): hp = {} diff --git a/gui/builtinStatsViews/outgoingViewFull.py b/gui/builtinStatsViews/outgoingViewFull.py index 945edd4fe..3b5240eba 100644 --- a/gui/builtinStatsViews/outgoingViewFull.py +++ b/gui/builtinStatsViews/outgoingViewFull.py @@ -83,10 +83,10 @@ class OutgoingViewFull(StatsView): # If we did anything intresting, we'd update our labels to reflect the new fit's stats here stats = [ - ("labelRemoteArmor", lambda: fit.remoteReps["Armor"], 3, 0, 0, u"%s HP/s", None), - ("labelRemoteShield", lambda: fit.remoteReps["Shield"], 3, 0, 0, u"%s HP/s", None), - ("labelRemoteHull", lambda: fit.remoteReps["Hull"], 3, 0, 0, u"%s HP/s", None), - ("labelRemoteCapacitor", lambda: fit.remoteReps["Capacitor"], 3, 0, 0, u"%s GJ/s", None), + ("labelRemoteArmor", lambda: fit.armorRR, 3, 0, 0, u"%s HP/s", None), + ("labelRemoteShield", lambda: fit.shieldRR, 3, 0, 0, u"%s HP/s", None), + ("labelRemoteHull", lambda: fit.hullRR, 3, 0, 0, u"%s HP/s", None), + ("labelRemoteCapacitor", lambda: fit.capTransfer, 3, 0, 0, u"%s GJ/s", None), ] counter = 0 diff --git a/gui/builtinStatsViews/outgoingViewMinimal.py b/gui/builtinStatsViews/outgoingViewMinimal.py index 945edd4fe..3b5240eba 100644 --- a/gui/builtinStatsViews/outgoingViewMinimal.py +++ b/gui/builtinStatsViews/outgoingViewMinimal.py @@ -83,10 +83,10 @@ class OutgoingViewFull(StatsView): # If we did anything intresting, we'd update our labels to reflect the new fit's stats here stats = [ - ("labelRemoteArmor", lambda: fit.remoteReps["Armor"], 3, 0, 0, u"%s HP/s", None), - ("labelRemoteShield", lambda: fit.remoteReps["Shield"], 3, 0, 0, u"%s HP/s", None), - ("labelRemoteHull", lambda: fit.remoteReps["Hull"], 3, 0, 0, u"%s HP/s", None), - ("labelRemoteCapacitor", lambda: fit.remoteReps["Capacitor"], 3, 0, 0, u"%s GJ/s", None), + ("labelRemoteArmor", lambda: fit.armorRR, 3, 0, 0, u"%s HP/s", None), + ("labelRemoteShield", lambda: fit.shieldRR, 3, 0, 0, u"%s HP/s", None), + ("labelRemoteHull", lambda: fit.hullRR, 3, 0, 0, u"%s HP/s", None), + ("labelRemoteCapacitor", lambda: fit.capTransfer, 3, 0, 0, u"%s GJ/s", None), ] counter = 0 From b3c72736815c2d8332cebd2c56b3681d05e0b8f4 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Fri, 24 Feb 2017 16:10:54 -0800 Subject: [PATCH 08/13] implement a suggestion or six from @blitzmann. Fix a bunch of low level bugs (unlikely to have been noticed since we don't really expose those stats). Add some properties instead of referencing the attribute directly. --- eos/saveddata/fit.py | 100 ++++++++----------- eos/saveddata/module.py | 75 ++++++++++---- gui/builtinStatsViews/outgoingViewFull.py | 6 +- gui/builtinStatsViews/outgoingViewMinimal.py | 6 +- 4 files changed, 106 insertions(+), 81 deletions(-) diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 5e40aff80..82dc8b56f 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -129,10 +129,10 @@ class Fit(object): self.__capRecharge = None self.__calculatedTargets = [] self.__remoteReps = { - "Armor": 0, - "Shield": 0, - "Hull": 0, - "Capacitor": 0, + "Armor": None, + "Shield": None, + "Hull": None, + "Capacitor": None, } self.factorReload = False self.boostsFits = set() @@ -400,7 +400,7 @@ class Fit(object): self.commandBonuses = {} for remoterep_type in self.__remoteReps: - self.__remoteReps[remoterep_type] = 0 + self.__remoteReps[remoterep_type] = None del self.__calculatedTargets[:] del self.__extraDrains[:] @@ -1159,76 +1159,64 @@ class Fit(object): @property def remoteReps(self): - def amount_per_second(module_amount, module_duration, module_reload, module_chargerate, module_capacity, module_volume): - numcycles = math.floor(module_capacity / (module_volume * module_chargerate)) + force_recalc = False + for remoterep_type in self.__remoteReps: + if self.__remoteReps[remoterep_type] is None: + force_recalc = True + break - module_amount *= numcycles - module_duration = module_chargerate * numcycles + module_reload - - return module_amount / module_duration + if force_recalc is False: + return self.__remoteReps for module in self.modules: # Skip empty modules if module.isEmpty: continue - module_group = getattr(module.item.group, "name") - # Skip modules that aren't online if getattr(module, "state", 0) < 1: continue - if module_group in ("Remote Armor Repairer", "Ancillary Remote Armor Repairer"): - # Remote Armor Reppers - hp = module.getModifiedItemAttr("armorDamageAmount", 0) - duration = module.getModifiedItemAttr("duration", 0) / 1000 - reloadTime = module.getModifiedItemAttr("reloadTime", 0) / 1000 - chargeRate = module.getModifiedItemAttr("chargeRate", 1) - fueledMultiplier = module.getModifiedItemAttr("chargedArmorDamageMultiplier", 1) - capacity = module.getModifiedItemAttr("capacity", 0) - volume = module.getModifiedChargeAttr("volume", 0) + duration = module.cycleTime / 1000 - if module.charge: - hp *= fueledMultiplier - hp_per_s = amount_per_second(hp, duration, reloadTime, chargeRate, capacity, volume) - else: - hp_per_s = hp / duration + # Skip modules with no duration. + if not duration: + continue - self.__remoteReps["Armor"] += hp_per_s + fueledMultiplier = module.getModifiedItemAttr("chargedArmorDamageMultiplier", 1) - elif module_group in ("Remote Hull Repairer",): - # Remote Hull Reppers + remote_module_groups = { + "Remote Armor Repairer" : "Armor", + "Ancillary Remote Armor Repairer": "Armor", + "Remote Hull Repairer" : "Hull", + "Remote Shield Booster" : "Shield", + "Ancillary Remote Shield Booster": "Shield", + "Remote Capacitor Transmitter" : "Capacitor", + } + + module_group = module.item.group.name + + if module_group in remote_module_groups: + remote_type = remote_module_groups[module_group] + else: + # Module isn't in our list of remote rep modules, bail + continue + + if remote_type == "Hull": hp = module.getModifiedItemAttr("structureDamageAmount", 0) - duration = module.getModifiedItemAttr("duration", 0) / 1000 - - hp_per_s = hp / duration - - self.__remoteReps["Hull"] += hp_per_s - - elif module_group in ("Remote Shield Booster", "Ancillary Remote Shield Booster"): - # Remote Shield Reppers + elif remote_type == "Armor": + hp = module.getModifiedItemAttr("armorDamageAmount", 0) + elif remote_type == "Shield": hp = module.getModifiedItemAttr("shieldBonus", 0) - duration = module.getModifiedItemAttr("duration", 0) / 1000 - reloadTime = module.getModifiedItemAttr("reloadTime", 0) / 1000 - chargeRate = module.getModifiedItemAttr("chargeRate", 1) - capacity = module.getModifiedItemAttr("capacity", 0) - volume = module.getModifiedChargeAttr("volume", 0) - - if module.charge: - hp_per_s = amount_per_second(hp, duration, reloadTime, chargeRate, capacity, volume) - else: - hp_per_s = hp / duration - - self.__remoteReps["Shield"] += hp_per_s - - elif module_group in ("Remote Capacitor Transmitter",): - # Remote Capacitor Boosters + elif remote_type == "Capacitor": hp = module.getModifiedItemAttr("powerTransferAmount", 0) - duration = module.getModifiedItemAttr("duration", 0) / 1000 + else: + hp = 0 - hp_per_s = hp / duration + if self.__remoteReps[remote_type] is None: + self.__remoteReps[remote_type] = 0 - self.__remoteReps["Capacitor"] += hp_per_s + self.__remoteReps[remote_type] += (hp * fueledMultiplier) / duration return self.__remoteReps diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index ba41d559d..1fddabd9d 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -20,6 +20,7 @@ import logging from sqlalchemy.orm import validates, reconstructor +from math import floor import eos.db from eos.effectHandlerHelpers import HandledItem, HandledCharge @@ -172,7 +173,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): if chargeVolume is None or containerCapacity is None: charges = 0 else: - charges = floorFloat(float(containerCapacity) / chargeVolume) + charges = floor(containerCapacity / chargeVolume) return charges @property @@ -216,9 +217,10 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): def __calculateAmmoShots(self): if self.charge is not None: # Set number of cycles before reload is needed + # numcycles = math.floor(module_capacity / (module_volume * module_chargerate)) chargeRate = self.getModifiedItemAttr("chargeRate") numCharges = self.numCharges - numShots = floorFloat(float(numCharges) / chargeRate) + numShots = floor(numCharges / chargeRate) else: numShots = None return numShots @@ -665,32 +667,67 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @property def cycleTime(self): - reactivation = (self.getModifiedItemAttr("moduleReactivationDelay") or 0) - # Reactivation time starts counting after end of module cycle - speed = self.rawCycleTime + reactivation - if self.charge: - reload = self.reloadTime - else: - reload = 0.0 # Determine if we'll take into account reload time or not factorReload = self.owner.factorReload if self.forceReload is None else self.forceReload - # If reactivation is longer than 10 seconds then module can be reloaded - # during reactivation time, thus we may ignore reload - if factorReload and reactivation < reload: - numShots = self.numShots - # Time it takes to reload module after end of reactivation time, - # given that we started when module cycle has just over - additionalReloadTime = (reload - reactivation) - # Speed here already takes into consideration reactivation time - speed = (speed * numShots + additionalReloadTime) / numShots if numShots > 0 else speed + + numShots = self.numShots + speed = self.rawCycleTime + + if factorReload and self.charge: + raw_reload_time = self.reloadTime + else: + raw_reload_time = 0.0 + + # Module can only fire one shot at a time, think bomb launchers or defender launchers + if self.disallowRepeatingAction: + if numShots > 1: + """ + 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. + + 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) + raw_reload_time) / numShots + else: + """ + Applies to MJD/MJFG + """ + effective_reload_time = max(raw_reload_time, self.reactivationDelay, 0) + else: + """ + Currently no other modules would have a reactivation delay, so for sanities sake don't try and account for it. + """ + effective_reload_time = raw_reload_time + + if numShots > 0 and self.charge: + speed = (speed * numShots + effective_reload_time) / numShots return speed @property def rawCycleTime(self): - speed = self.getModifiedItemAttr("speed") or self.getModifiedItemAttr("duration") + speed = max( + self.getModifiedItemAttr("speed"), # Most weapons + self.getModifiedItemAttr("duration"), # Most average modules + self.getModifiedItemAttr("durationSensorDampeningBurstProjector"), + self.getModifiedItemAttr("durationTargetIlluminationBurstProjector"), + self.getModifiedItemAttr("durationECMJammerBurstProjector"), + self.getModifiedItemAttr("durationWeaponDisruptionBurstProjector"), + 0, # Return 0 if none of the above are valid + ) return speed + @property + def disallowRepeatingAction(self): + return self.getModifiedItemAttr("disallowRepeatingAction", 0) + + @property + def reactivationDelay(self): + return self.getModifiedItemAttr("moduleReactivationDelay", 0) + @property def capUse(self): capNeed = self.getModifiedItemAttr("capacitorNeed") diff --git a/gui/builtinStatsViews/outgoingViewFull.py b/gui/builtinStatsViews/outgoingViewFull.py index 945edd4fe..9e92f2db9 100644 --- a/gui/builtinStatsViews/outgoingViewFull.py +++ b/gui/builtinStatsViews/outgoingViewFull.py @@ -53,10 +53,10 @@ class OutgoingViewFull(StatsView): counter = 0 rr_list = [ - ("RemoteArmor", "Armor:", "armorActive", "Armor hitpoints per second repaired remotely."), - ("RemoteShield", "Shield:", "shieldActive", "Shield hitpoints per second repaired remotely."), - ("RemoteHull", "Hull:", "hullActive", "Hull hitpoints per second repaired remotely."), ("RemoteCapacitor", "Capacitor:", "capacitorInfo", "Capacitor GJ/s per second transferred remotely."), + ("RemoteShield", "Shield:", "shieldActive", "Shield hitpoints per second repaired remotely."), + ("RemoteArmor", "Armor:", "armorActive", "Armor hitpoints per second repaired remotely."), + ("RemoteHull", "Hull:", "hullActive", "Hull hitpoints per second repaired remotely."), ] for outgoingType, label, image, tooltip in rr_list: diff --git a/gui/builtinStatsViews/outgoingViewMinimal.py b/gui/builtinStatsViews/outgoingViewMinimal.py index 945edd4fe..9e92f2db9 100644 --- a/gui/builtinStatsViews/outgoingViewMinimal.py +++ b/gui/builtinStatsViews/outgoingViewMinimal.py @@ -53,10 +53,10 @@ class OutgoingViewFull(StatsView): counter = 0 rr_list = [ - ("RemoteArmor", "Armor:", "armorActive", "Armor hitpoints per second repaired remotely."), - ("RemoteShield", "Shield:", "shieldActive", "Shield hitpoints per second repaired remotely."), - ("RemoteHull", "Hull:", "hullActive", "Hull hitpoints per second repaired remotely."), ("RemoteCapacitor", "Capacitor:", "capacitorInfo", "Capacitor GJ/s per second transferred remotely."), + ("RemoteShield", "Shield:", "shieldActive", "Shield hitpoints per second repaired remotely."), + ("RemoteArmor", "Armor:", "armorActive", "Armor hitpoints per second repaired remotely."), + ("RemoteHull", "Hull:", "hullActive", "Hull hitpoints per second repaired remotely."), ] for outgoingType, label, image, tooltip in rr_list: From 43073069c7461ccbe9d05ea15a056ff78468ec78 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Fri, 24 Feb 2017 16:25:31 -0800 Subject: [PATCH 09/13] Fix merge conflict. --- eos/saveddata/module.py | 1 + gui/builtinStatsViews/outgoingViewFull.py | 8 ++++---- gui/builtinStatsViews/outgoingViewMinimal.py | 8 ++++---- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index 1fddabd9d..4735c95c6 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -699,6 +699,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): 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 diff --git a/gui/builtinStatsViews/outgoingViewFull.py b/gui/builtinStatsViews/outgoingViewFull.py index d18f84678..9e92f2db9 100644 --- a/gui/builtinStatsViews/outgoingViewFull.py +++ b/gui/builtinStatsViews/outgoingViewFull.py @@ -83,10 +83,10 @@ class OutgoingViewFull(StatsView): # If we did anything intresting, we'd update our labels to reflect the new fit's stats here stats = [ - ("labelRemoteArmor", lambda: fit.armorRR, 3, 0, 0, u"%s HP/s", None), - ("labelRemoteShield", lambda: fit.shieldRR, 3, 0, 0, u"%s HP/s", None), - ("labelRemoteHull", lambda: fit.hullRR, 3, 0, 0, u"%s HP/s", None), - ("labelRemoteCapacitor", lambda: fit.capTransfer, 3, 0, 0, u"%s GJ/s", None), + ("labelRemoteArmor", lambda: fit.remoteReps["Armor"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteShield", lambda: fit.remoteReps["Shield"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteHull", lambda: fit.remoteReps["Hull"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteCapacitor", lambda: fit.remoteReps["Capacitor"], 3, 0, 0, u"%s GJ/s", None), ] counter = 0 diff --git a/gui/builtinStatsViews/outgoingViewMinimal.py b/gui/builtinStatsViews/outgoingViewMinimal.py index d18f84678..9e92f2db9 100644 --- a/gui/builtinStatsViews/outgoingViewMinimal.py +++ b/gui/builtinStatsViews/outgoingViewMinimal.py @@ -83,10 +83,10 @@ class OutgoingViewFull(StatsView): # If we did anything intresting, we'd update our labels to reflect the new fit's stats here stats = [ - ("labelRemoteArmor", lambda: fit.armorRR, 3, 0, 0, u"%s HP/s", None), - ("labelRemoteShield", lambda: fit.shieldRR, 3, 0, 0, u"%s HP/s", None), - ("labelRemoteHull", lambda: fit.hullRR, 3, 0, 0, u"%s HP/s", None), - ("labelRemoteCapacitor", lambda: fit.capTransfer, 3, 0, 0, u"%s GJ/s", None), + ("labelRemoteArmor", lambda: fit.remoteReps["Armor"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteShield", lambda: fit.remoteReps["Shield"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteHull", lambda: fit.remoteReps["Hull"], 3, 0, 0, u"%s HP/s", None), + ("labelRemoteCapacitor", lambda: fit.remoteReps["Capacitor"], 3, 0, 0, u"%s GJ/s", None), ] counter = 0 From 3411eca1e703b35ced86ab10cfbb29a61d32b498 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Fri, 24 Feb 2017 16:34:32 -0800 Subject: [PATCH 10/13] Fix a couple pep8 issues, and clean up other folks pep8 misses. :) --- eos/saveddata/fit.py | 1 - eos/saveddata/module.py | 2 +- gui/builtinStatsViews/outgoingViewFull.py | 2 -- gui/builtinStatsViews/outgoingViewMinimal.py | 2 -- service/crest.py | 1 - service/server.py | 1 + 6 files changed, 2 insertions(+), 7 deletions(-) diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index df6652d27..113ff98b5 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -18,7 +18,6 @@ # =============================================================================== import time -import math from copy import deepcopy from itertools import chain from math import sqrt, log, asinh diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index 4735c95c6..55da98d63 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -723,7 +723,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): @property def disallowRepeatingAction(self): - return self.getModifiedItemAttr("disallowRepeatingAction", 0) + return self.getModifiedItemAttr("disallowRepeatingAction", 0) @property def reactivationDelay(self): diff --git a/gui/builtinStatsViews/outgoingViewFull.py b/gui/builtinStatsViews/outgoingViewFull.py index 9e92f2db9..346aacc7a 100644 --- a/gui/builtinStatsViews/outgoingViewFull.py +++ b/gui/builtinStatsViews/outgoingViewFull.py @@ -44,8 +44,6 @@ class OutgoingViewFull(StatsView): parent = self.panel = contentPanel self.headerPanel = headerPanel - panel = "full" - sizerOutgoing = wx.GridSizer(1, 4) contentSizer.Add(sizerOutgoing, 0, wx.EXPAND, 0) diff --git a/gui/builtinStatsViews/outgoingViewMinimal.py b/gui/builtinStatsViews/outgoingViewMinimal.py index 9e92f2db9..346aacc7a 100644 --- a/gui/builtinStatsViews/outgoingViewMinimal.py +++ b/gui/builtinStatsViews/outgoingViewMinimal.py @@ -44,8 +44,6 @@ class OutgoingViewFull(StatsView): parent = self.panel = contentPanel self.headerPanel = headerPanel - panel = "full" - sizerOutgoing = wx.GridSizer(1, 4) contentSizer.Add(sizerOutgoing, 0, wx.EXPAND, 0) diff --git a/service/crest.py b/service/crest.py index bbe8cd1bb..f968df7a3 100644 --- a/service/crest.py +++ b/service/crest.py @@ -1,6 +1,5 @@ # noinspection PyPackageRequirements import wx -import thread import logging import threading import copy diff --git a/service/server.py b/service/server.py index 38ecebfe4..c75892d70 100644 --- a/service/server.py +++ b/service/server.py @@ -55,6 +55,7 @@ else {{ ''' + # https://github.com/fuzzysteve/CREST-Market-Downloader/ class AuthHandler(BaseHTTPServer.BaseHTTPRequestHandler): def do_GET(self): From c24798ad2ffd5abecec41e2d453557d742ab2b80 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Fri, 24 Feb 2017 17:07:05 -0800 Subject: [PATCH 11/13] Clean up last reference and finish nuking floatfloor. One less method! (ouch my test!) --- eos/mathUtils.py | 31 ------------------------------- eos/saveddata/fit.py | 4 ++-- eos/saveddata/module.py | 3 +-- 3 files changed, 3 insertions(+), 35 deletions(-) delete mode 100644 eos/mathUtils.py diff --git a/eos/mathUtils.py b/eos/mathUtils.py deleted file mode 100644 index 5de12c60f..000000000 --- a/eos/mathUtils.py +++ /dev/null @@ -1,31 +0,0 @@ -# =============================================================================== -# Copyright (C) 2010 Anton Vorobyov -# -# 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 . -# =============================================================================== - -import decimal - - -def floorFloat(value): - """Round float down to integer""" - # We have to convert float to str to keep compatibility with - # decimal module in python 2.6 - value = str(value) - # Do the conversions for proper rounding down, avoiding float - # representation errors - result = int(decimal.Decimal(value).to_integral_value(rounding=decimal.ROUND_DOWN)) - return result diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index 113ff98b5..de6e8cc58 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -1159,8 +1159,8 @@ class Fit(object): @property def remoteReps(self): force_recalc = False - for remoterep_type in self.__remoteReps: - if self.__remoteReps[remoterep_type] is None: + for remote_type in self.__remoteReps: + if self.__remoteReps[remote_type] is None: force_recalc = True break diff --git a/eos/saveddata/module.py b/eos/saveddata/module.py index 55da98d63..a3f85ed5b 100644 --- a/eos/saveddata/module.py +++ b/eos/saveddata/module.py @@ -25,7 +25,6 @@ from math import floor import eos.db from eos.effectHandlerHelpers import HandledItem, HandledCharge from eos.enum import Enum -from eos.mathUtils import floorFloat from eos.modifiedAttributeDict import ModifiedAttributeDict, ItemAttrShortcut, ChargeAttrShortcut from eos.saveddata.citadel import Citadel @@ -233,7 +232,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): chance = self.getModifiedChargeAttr("crystalVolatilityChance") damage = self.getModifiedChargeAttr("crystalVolatilityDamage") crystals = self.numCharges - numShots = floorFloat(float(crystals * hp) / (damage * chance)) + numShots = floor((crystals * hp) / (damage * chance)) else: # Set 0 (infinite) for permanent crystals like t1 laser crystals numShots = 0 From e4d0f2dc6f5e07637a9e0ae033faf92fdd8d00f4 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sun, 26 Feb 2017 08:46:23 -0800 Subject: [PATCH 12/13] Fix case where property gets reran multiple times. --- eos/saveddata/fit.py | 7 ++++--- service/crest.py | 1 - 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/eos/saveddata/fit.py b/eos/saveddata/fit.py index b46a2aa6c..aa92ff21a 100644 --- a/eos/saveddata/fit.py +++ b/eos/saveddata/fit.py @@ -1171,6 +1171,10 @@ class Fit(object): if force_recalc is False: return self.__remoteReps + # We are rerunning the recalcs. Explicitly set to 0 to make sure we don't duplicate anything and correctly set all values to 0. + for remote_type in self.__remoteReps: + self.__remoteReps[remote_type] = 0 + for module in self.modules: # Skip empty and non-Active modules if module.isEmpty or module.state < State.ACTIVE: @@ -1213,9 +1217,6 @@ class Fit(object): else: hp = 0 - if self.__remoteReps[remote_type] is None: - self.__remoteReps[remote_type] = 0 - self.__remoteReps[remote_type] += (hp * fueledMultiplier) / duration return self.__remoteReps diff --git a/service/crest.py b/service/crest.py index 8ef51ac3a..27f5b6c5e 100644 --- a/service/crest.py +++ b/service/crest.py @@ -1,7 +1,6 @@ # noinspection PyPackageRequirements import wx from logbook import Logger -import logging import threading import copy import uuid From 7eb193cbbb016a75263a0b84f591c37035f59c38 Mon Sep 17 00:00:00 2001 From: Ebag333 Date: Sun, 26 Feb 2017 08:52:27 -0800 Subject: [PATCH 13/13] Delete test, the method being tested no longer exists. --- tests/test_modules/eos/test_mathUtils.py | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 tests/test_modules/eos/test_mathUtils.py diff --git a/tests/test_modules/eos/test_mathUtils.py b/tests/test_modules/eos/test_mathUtils.py deleted file mode 100644 index c5cf2b0bb..000000000 --- a/tests/test_modules/eos/test_mathUtils.py +++ /dev/null @@ -1,12 +0,0 @@ -from eos.mathUtils import floorFloat - - -def test_floorFloat(): - assert type(floorFloat(1)) is not float - assert type(floorFloat(1)) is int - assert type(floorFloat(1.1)) is not float - assert type(floorFloat(1.1)) is int - assert floorFloat(1.1) == 1 - assert floorFloat(1.9) == 1 - assert floorFloat(1.5) == 1 - assert floorFloat(-1.5) == -2