Merge branch 'akosiaris_miningyeild'

This commit is contained in:
blitzmann
2014-06-12 19:22:50 -04:00
9 changed files with 270 additions and 5 deletions

View File

@@ -23,6 +23,7 @@ from sqlalchemy.orm import validates, reconstructor
class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
DAMAGE_ATTRIBUTES = ("emDamage", "kineticDamage", "explosiveDamage", "thermalDamage") DAMAGE_ATTRIBUTES = ("emDamage", "kineticDamage", "explosiveDamage", "thermalDamage")
MINING_ATTRIBUTES = ("miningAmount",)
def __init__(self, item): def __init__(self, item):
if item.category.name != "Drone": if item.category.name != "Drone":
@@ -34,6 +35,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
self.amount = 0 self.amount = 0
self.amountActive = 0 self.amountActive = 0
self.__dps = None self.__dps = None
self.__miningyield = None
self.projected = False self.projected = False
self.__itemModifiedAttributes = ModifiedAttributeDict() self.__itemModifiedAttributes = ModifiedAttributeDict()
self.itemModifiedAttributes.original = self.item.attributes self.itemModifiedAttributes.original = self.item.attributes
@@ -41,6 +43,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
@reconstructor @reconstructor
def init(self): def init(self):
self.__dps = None self.__dps = None
self.__miningyield = None
self.__item = None self.__item = None
self.__charge = None self.__charge = None
@@ -97,6 +100,11 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
if attr in self.itemModifiedAttributes or attr in self.chargeModifiedAttributes: if attr in self.itemModifiedAttributes or attr in self.chargeModifiedAttributes:
return True return True
@property
def mines(self):
if "miningAmount" in self.itemModifiedAttributes:
return True
@property @property
def hasAmmo(self): def hasAmmo(self):
return self.charge is not None return self.charge is not None
@@ -121,6 +129,21 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
return self.__dps return self.__dps
@property
def miningStats(self):
if self.__miningyield == None:
if self.mines is True and self.amountActive > 0:
attr = "duration"
getter = self.getModifiedItemAttr
cycleTime = self.getModifiedItemAttr(attr)
volley = sum(map(lambda d: getter(d), self.MINING_ATTRIBUTES)) * self.amountActive
self.__miningyield = volley / (cycleTime / 1000.0)
else:
self.__miningyield = 0
return self.__miningyield
@property @property
def maxRange(self): def maxRange(self):
attrs = ("shieldTransferRange", "powerTransferRange", attrs = ("shieldTransferRange", "powerTransferRange",
@@ -158,6 +181,7 @@ class Drone(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def clear(self): def clear(self):
self.__dps = None self.__dps = None
self.__miningyield = None
self.itemModifiedAttributes.clear() self.itemModifiedAttributes.clear()
self.chargeModifiedAttributes.clear() self.chargeModifiedAttributes.clear()

View File

@@ -76,8 +76,10 @@ class Fit(object):
self.__extraDrains = [] self.__extraDrains = []
self.__ehp = None self.__ehp = None
self.__weaponDPS = None self.__weaponDPS = None
self.__minerYield = None
self.__weaponVolley = None self.__weaponVolley = None
self.__droneDPS = None self.__droneDPS = None
self.__droneYield = None
self.__sustainableTank = None self.__sustainableTank = None
self.__effectiveSustainableTank = None self.__effectiveSustainableTank = None
self.__effectiveTank = None self.__effectiveTank = None
@@ -179,6 +181,24 @@ class Fit(object):
def totalDPS(self): def totalDPS(self):
return self.droneDPS + self.weaponDPS return self.droneDPS + self.weaponDPS
@property
def minerYield(self):
if self.__minerYield is None:
self.calculateMiningStats()
return self.__minerYield
@property
def droneYield(self):
if self.__droneYield is None:
self.calculateMiningStats()
return self.__droneYield
@property
def totalYield(self):
return self.droneYield + self.minerYield
@property @property
def maxTargets(self): def maxTargets(self):
return min(self.extraAttributes["maxTargetsLockedFromSkills"], self.ship.getModifiedItemAttr("maxLockedTargets")) return min(self.extraAttributes["maxTargetsLockedFromSkills"], self.ship.getModifiedItemAttr("maxLockedTargets"))
@@ -237,10 +257,12 @@ class Fit(object):
def clear(self): def clear(self):
self.__effectiveTank = None self.__effectiveTank = None
self.__weaponDPS = None self.__weaponDPS = None
self.__minerYield = None
self.__weaponVolley = None self.__weaponVolley = None
self.__effectiveSustainableTank = None self.__effectiveSustainableTank = None
self.__sustainableTank = None self.__sustainableTank = None
self.__droneDPS = None self.__droneDPS = None
self.__droneYield = None
self.__ehp = None self.__ehp = None
self.__calculated = False self.__calculated = False
self.__capStable = None self.__capStable = None
@@ -763,6 +785,19 @@ class Fit(object):
else: else:
return self.ship.getModifiedItemAttr("scanSpeed") / 1000.0 return self.ship.getModifiedItemAttr("scanSpeed") / 1000.0
def calculateMiningStats(self):
minerYield = 0
droneYield = 0
for mod in self.modules:
minerYield += mod.miningStats
for drone in self.drones:
droneYield += drone.miningStats
self.__minerYield = minerYield
self.__droneYield = droneYield
def calculateWeaponStats(self): def calculateWeaponStats(self):
weaponDPS = 0 weaponDPS = 0
droneDPS = 0 droneDPS = 0

View File

@@ -45,6 +45,7 @@ class Hardpoint(Enum):
class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut): class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
"""An instance of this class represents a module together with its charge and modified attributes""" """An instance of this class represents a module together with its charge and modified attributes"""
DAMAGE_ATTRIBUTES = ("emDamage", "kineticDamage", "explosiveDamage", "thermalDamage") DAMAGE_ATTRIBUTES = ("emDamage", "kineticDamage", "explosiveDamage", "thermalDamage")
MINING_ATTRIBUTES = ("miningAmount", )
def __init__(self, item): def __init__(self, item):
self.__item = item if item != None else 0 self.__item = item if item != None else 0
@@ -53,6 +54,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
self.projected = False self.projected = False
self.state = State.ONLINE self.state = State.ONLINE
self.__dps = None self.__dps = None
self.__miningyield = None
self.__volley = None self.__volley = None
self.__reloadTime = None self.__reloadTime = None
self.__reloadForce = None self.__reloadForce = None
@@ -74,6 +76,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
self.__charge = None self.__charge = None
self.__volley = None self.__volley = None
self.__dps = None self.__dps = None
self.__miningyield = None
self.__reloadTime = None self.__reloadTime = None
self.__reloadForce = None self.__reloadForce = None
self.__chargeCycles = None self.__chargeCycles = None
@@ -82,6 +85,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
self.__item = 0 self.__item = 0
self.__charge = 0 self.__charge = 0
self.__dps = 0 self.__dps = 0
self.__miningyield = 0
self.__volley = 0 self.__volley = 0
self.__reloadTime = 0 self.__reloadTime = 0
self.__reloadForce = None self.__reloadForce = None
@@ -330,6 +334,24 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
return self.__dps, self.__volley return self.__dps, self.__volley
@property
def miningStats(self):
if self.__miningyield == None:
if self.isEmpty:
self.__miningyield = 0
else:
if self.state >= State.ACTIVE:
volley = sum(map(lambda attr: self.getModifiedItemAttr(attr) or 0, self.MINING_ATTRIBUTES))
if volley:
cycleTime = self.cycleTime
self.__miningyield = volley / (cycleTime / 1000.0)
else:
self.__miningyield = 0
else:
self.__miningyield = 0
return self.__miningyield
@property @property
def dps(self): def dps(self):
return self.damageStats[0] return self.damageStats[0]
@@ -552,6 +574,7 @@ class Module(HandledItem, HandledCharge, ItemAttrShortcut, ChargeAttrShortcut):
def clear(self): def clear(self):
self.__dps = None self.__dps = None
self.__miningyield = None
self.__volley = None self.__volley = None
self.__reloadTime = None self.__reloadTime = None
self.__reloadForce = None self.__reloadForce = None

View File

@@ -1,3 +1,3 @@
__all__ = ["resourcesViewFull", "resistancesViewFull", __all__ = ["resourcesViewFull", "resistancesViewFull",
"rechargeViewFull", "firepowerViewFull", "capacitorViewFull", "rechargeViewFull", "firepowerViewFull", "capacitorViewFull",
"targetingMiscViewFull", "priceViewFull"] "targetingMiscViewFull", "priceViewFull", "miningyieldViewFull"]

View File

@@ -18,8 +18,9 @@
#=============================================================================== #===============================================================================
import wx import wx
import service
import gui.mainFrame
from gui.statsView import StatsView from gui.statsView import StatsView
from gui import builtinStatsViews
from gui import bitmapLoader from gui import bitmapLoader
from gui.utils.numberFormatter import formatAmount from gui.utils.numberFormatter import formatAmount
@@ -43,9 +44,9 @@ class FirepowerViewFull(StatsView):
panel = "full" panel = "full"
sizerFirepower = wx.FlexGridSizer(1, 3) sizerFirepower = wx.FlexGridSizer(1, 4)
sizerFirepower.AddGrowableCol(1) sizerFirepower.AddGrowableCol(1)
contentSizer.Add( sizerFirepower, 0, wx.EXPAND, 0) contentSizer.Add( sizerFirepower, 0, wx.EXPAND, 0)
counter = 0 counter = 0
@@ -97,6 +98,35 @@ class FirepowerViewFull(StatsView):
gridS.Add(lbl, 0, wx.ALIGN_LEFT) gridS.Add(lbl, 0, wx.ALIGN_LEFT)
image = bitmapLoader.getBitmap("mining_small", "icons")
self.miningyield = wx.BitmapButton(contentPanel, -1, image)
self.miningyield.SetToolTip(wx.ToolTip("Click to toggle to Mining Yield "))
self.miningyield.Bind(wx.EVT_BUTTON, self.switchToMiningYieldView)
sizerFirepower.Add(self.miningyield, 0, wx.ALIGN_LEFT)
self._cachedValues.append(0)
def switchToMiningYieldView(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("miningyieldViewFull")(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): 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
@@ -104,6 +134,11 @@ class FirepowerViewFull(StatsView):
("labelFullDpsDrone", lambda: fit.droneDPS, 3, 0, 0, "%s DPS", None), ("labelFullDpsDrone", lambda: fit.droneDPS, 3, 0, 0, "%s DPS", None),
("labelFullVolleyTotal", lambda: fit.weaponVolley, 3, 0, 0, "%s", "Volley: %.1f"), ("labelFullVolleyTotal", lambda: fit.weaponVolley, 3, 0, 0, "%s", "Volley: %.1f"),
("labelFullDpsTotal", lambda: fit.totalDPS, 3, 0, 0, "%s", None)) ("labelFullDpsTotal", lambda: fit.totalDPS, 3, 0, 0, "%s", None))
# See GH issue #
#if fit is not None and fit.totalYield > 0:
# self.miningyield.Show()
#else:
# self.miningyield.Hide()
counter = 0 counter = 0
for labelName, value, prec, lowest, highest, valueFormat, altFormat in stats: for labelName, value, prec, lowest, highest, valueFormat, altFormat in stats:
@@ -117,6 +152,7 @@ class FirepowerViewFull(StatsView):
label.SetToolTip(wx.ToolTip(tipStr)) label.SetToolTip(wx.ToolTip(tipStr))
self._cachedValues[counter] = value self._cachedValues[counter] = value
counter +=1 counter +=1
self.panel.Layout() self.panel.Layout()
self.headerPanel.Layout() self.headerPanel.Layout()

View File

@@ -0,0 +1,146 @@
#===============================================================================
# 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 <http://www.gnu.org/licenses/>.
#===============================================================================
import wx
import service
import gui.mainFrame
from gui.statsView import StatsView
from gui import bitmapLoader
from gui.utils.numberFormatter import formatAmount
class MiningYieldViewFull(StatsView):
name = "miningyieldViewFull"
def __init__(self, parent):
StatsView.__init__(self)
self.parent = parent
self._cachedValues = []
def getHeaderText(self, fit):
return "Mining Yield"
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"
sizerMiningYield = wx.FlexGridSizer(1, 4)
sizerMiningYield.AddGrowableCol(1)
contentSizer.Add( sizerMiningYield, 0, wx.EXPAND, 0)
counter = 0
for miningType, image in (("miner", "mining") , ("drone", "drones")):
baseBox = wx.BoxSizer(wx.HORIZONTAL)
sizerMiningYield.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, miningType.capitalize()), 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 m\u00B3/s")
setattr(self, "label%sminingyield%s" % (panel.capitalize() ,miningType.capitalize()), lbl)
hbox.Add(lbl, 0, wx.ALIGN_CENTER)
self._cachedValues.append(0)
counter += 1
targetSizer = sizerMiningYield
baseBox = wx.BoxSizer(wx.HORIZONTAL)
targetSizer.Add(baseBox, 0, wx.ALIGN_LEFT)
baseBox.Add(bitmapLoader.getStaticBitmap("cargoBay_big", parent, "icons"), 0, wx.ALIGN_CENTER)
box = wx.BoxSizer(wx.VERTICAL)
baseBox.Add(box, 0, wx.EXPAND)
box.Add(wx.StaticText(parent, wx.ID_ANY, "Total"), 0, wx.ALIGN_LEFT)
hbox = wx.BoxSizer(wx.HORIZONTAL)
box.Add(hbox, 1, wx.EXPAND)
lbl = wx.StaticText(parent, wx.ID_ANY, u"0.0 m\u00B3/s")
setattr(self, "label%sminingyieldTotal" % panel.capitalize(), lbl)
hbox.Add(lbl, 0, wx.ALIGN_LEFT)
self._cachedValues.append(0)
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)
sizerMiningYield.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 = (("labelFullminingyieldMiner", lambda: fit.minerYield, 3, 0, 0, u"%s m\u00B3/s",None),
("labelFullminingyieldDrone", lambda: fit.droneYield, 3, 0, 0, u"%s m\u00B3/s", None),
("labelFullminingyieldTotal", lambda: fit.totalYield, 3, 0, 0, u"%s m\u00B3/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()
MiningYieldViewFull.register()

View File

@@ -29,7 +29,8 @@ import gui.globalEvents as GE
class StatsPane(wx.Panel): class StatsPane(wx.Panel):
DEFAULT_VIEWS = ["resourcesViewFull", "resistancesViewFull" ,"rechargeViewFull", "firepowerViewFull", DEFAULT_VIEWS = ["resourcesViewFull", "resistancesViewFull" ,"rechargeViewFull", "firepowerViewFull",
"capacitorViewFull", "targetingmiscViewFull", "priceViewFull"] "capacitorViewFull", "targetingmiscViewFull",
"priceViewFull",]
def fitChanged(self, event): def fitChanged(self, event):
cFit = service.Fit.getInstance() cFit = service.Fit.getInstance()

BIN
icons/mining_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

BIN
icons/turret_small.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 777 B