Implemented copying the currently open fit stats to the clipboard.

This commit is contained in:
Alexander Maryanovsky
2018-09-08 15:06:31 +03:00
committed by Gochim
parent 9e78cd1076
commit 58f853de5b
3 changed files with 189 additions and 0 deletions

View File

@@ -78,6 +78,15 @@ class DamagePattern:
"exp" : "explosive"
}
@classmethod
def oneType(cls, damageType, amount=100):
pattern = DamagePattern()
pattern.update(amount if damageType == "em" else 0,
amount if damageType == "thermal" else 0,
amount if damageType == "kinetic" else 0,
amount if damageType == "explosive" else 0)
return pattern
@classmethod
def importPatterns(cls, text):
lines = re.split('[\n\r]+', text)

View File

@@ -81,6 +81,8 @@ except ImportError as e:
pyfalog.warning("Error loading Attribute Editor: %s.\nAccess to Attribute Editor is disabled." % e.message)
disableOverrideEditor = True
pyfalog = Logger(__name__)
pyfalog.debug("Done loading mainframe imports")
@@ -549,6 +551,7 @@ class MainFrame(wx.Frame):
# Clipboard exports
self.Bind(wx.EVT_MENU, self.exportToClipboard, id=wx.ID_COPY)
self.Bind(wx.EVT_MENU, self.exportFitStatsToClipboard, id=menuBar.fitStatsToClipboardId)
# Fitting Restrictions
self.Bind(wx.EVT_MENU, self.toggleIgnoreRestriction, id=menuBar.toggleIgnoreRestrictionID)
@@ -780,6 +783,12 @@ class MainFrame(wx.Frame):
with CopySelectDialog(self) as dlg:
dlg.ShowModal()
def exportFitStatsToClipboard(self, event):
""" Puts fit stats in textual format into the clipboard"""
fit = db_getFit(self.getActiveFit())
if fit:
toClipboard(statsExportText(fit))
def exportSkillsNeeded(self, event):
""" Exports skills needed for active fit and active character """
sCharacter = Character.getInstance()

171
gui/utils/exportStats.py Normal file
View File

@@ -0,0 +1,171 @@
from functools import reduce
from eos.saveddata.damagePattern import DamagePattern
from gui.utils.numberFormatter import formatAmount
tankTypes = ("shield", "armor", "hull")
damageTypes = ("em", "thermal", "kinetic", "explosive")
damagePatterns = [DamagePattern.oneType(damageType) for damageType in damageTypes]
damageTypeResonanceNames = [damageType.capitalize() + "DamageResonance" for damageType in damageTypes]
resonanceNames = {"shield": ["shield" + s for s in damageTypeResonanceNames],
"armor": ["armor" + s for s in damageTypeResonanceNames],
"hull": [s[0].lower() + s[1:] for s in damageTypeResonanceNames]}
def firepowerSection(fit):
""" Returns the text of the firepower section"""
firepower = [fit.totalDPS, fit.weaponDPS, fit.droneDPS, fit.totalVolley]
firepowerStr = [formatAmount(dps, 3, 0, 0) for dps in firepower]
showWeaponAndDroneDps = (fit.weaponDPS > 0) and (fit.droneDPS > 0)
if sum(firepower) == 0:
return ""
return "DPS: {} (".format(firepowerStr[0]) + \
("Weapon: {}, Drone: {}, ".format(*firepowerStr[1:3]) if showWeaponAndDroneDps else "") + \
("Volley: {})\n".format(firepowerStr[3]))
def tankSection(fit):
""" Returns the text of the tank section"""
ehp = [fit.ehp[tank] for tank in tankTypes] if fit.ehp is not None else [0, 0, 0]
ehp.append(sum(ehp))
ehpStr = [formatAmount(ehpVal, 3, 0, 9) for ehpVal in ehp]
resists = {tankType: [1 - fit.ship.getModifiedItemAttr(s) for s in resonanceNames[tankType]] for tankType in tankTypes}
ehpAgainstDamageType = [sum(pattern.calculateEhp(fit).values()) for pattern in damagePatterns]
ehpAgainstDamageTypeStr = [formatAmount(ehpVal, 3, 0, 9) for ehpVal in ehpAgainstDamageType]
return \
" {:>7} {:>7} {:>7} {:>7} {:>7}\n".format("TOTAL", "EM", "THERM", "KIN", "EXP") + \
"EHP {:>7} {:>7} {:>7} {:>7} {:>7}\n".format(ehpStr[3], *ehpAgainstDamageTypeStr) + \
"Shield {:>7} {:>7.0%} {:>7.0%} {:>7.0%} {:>7.0%}\n".format(ehpStr[0], *resists["shield"]) + \
"Armor {:>7} {:>7.0%} {:>7.0%} {:>7.0%} {:>7.0%}\n".format(ehpStr[1], *resists["armor"]) + \
"Hull {:>7} {:>7.0%} {:>7.0%} {:>7.0%} {:>7.0%}\n".format(ehpStr[2], *resists["hull"])
def repsSection(fit):
""" Returns the text of the repairs section"""
selfRep = [fit.effectiveTank[tankType + "Repair"] for tankType in tankTypes]
sustainRep = [fit.effectiveSustainableTank[tankType + "Repair"] for tankType in tankTypes]
remoteRep = [fit.remoteReps[tankType.capitalize()] for tankType in tankTypes]
shieldRegen = [fit.effectiveSustainableTank["passiveShield"], 0, 0]
shieldRechargeModuleMultipliers = [module.item.attributes["shieldRechargeRateMultiplier"].value for module in
fit.modules if
module.item and "shieldRechargeRateMultiplier" in module.item.attributes]
shieldRechargeMultiplierByModules = reduce(lambda x, y: x * y, shieldRechargeModuleMultipliers, 1)
if shieldRechargeMultiplierByModules >= 0.9: # If the total affect of modules on the shield recharge is negative or insignificant, we don't care about it
shieldRegen[0] = 0
totalRep = list(zip(selfRep, remoteRep, shieldRegen))
totalRep = list(map(sum, totalRep))
selfRep.append(sum(selfRep))
sustainRep.append(sum(sustainRep))
remoteRep.append(sum(remoteRep))
shieldRegen.append(sum(shieldRegen))
totalRep.append(sum(totalRep))
totalSelfRep = selfRep[-1]
totalRemoteRep = remoteRep[-1]
totalShieldRegen = shieldRegen[-1]
text = ""
if sum(totalRep) > 0: # Most commonly, there are no reps at all; then we skip this section
singleTypeRep = None
singleTypeRepName = None
if totalRemoteRep == 0 and totalShieldRegen == 0: # Only self rep
singleTypeRep = selfRep[:-1]
singleTypeRepName = "Self"
if totalSelfRep == 0 and totalShieldRegen == 0: # Only remote rep
singleTypeRep = remoteRep[:-1]
singleTypeRepName = "Remote"
if totalSelfRep == 0 and totalRemoteRep == 0: # Only shield regen
singleTypeRep = shieldRegen[:-1]
singleTypeRepName = "Regen"
if singleTypeRep and sum(
x > 0 for x in singleTypeRep) == 1: # Only one type of reps and only one tank type is repaired
index = next(i for i, v in enumerate(singleTypeRep) if v > 0)
if singleTypeRepName == "Regen":
text += "Shield regeneration: {} EHP/s".format(formatAmount(singleTypeRep[index], 3, 0, 9))
else:
text += "{} {} repair: {} EHP/s".format(singleTypeRepName, tankTypes[index],
formatAmount(singleTypeRep[index], 3, 0, 9))
if (singleTypeRepName == "Self") and (sustainRep[index] != singleTypeRep[index]):
text += " (Sustained: {} EHP/s)".format(formatAmount(sustainRep[index], 3, 0, 9))
text += "\n"
else: # Otherwise show a table
selfRepStr = [formatAmount(rep, 3, 0, 9) for rep in selfRep]
sustainRepStr = [formatAmount(rep, 3, 0, 9) for rep in sustainRep]
remoteRepStr = [formatAmount(rep, 3, 0, 9) for rep in remoteRep]
shieldRegenStr = [formatAmount(rep, 3, 0, 9) if rep != 0 else "" for rep in shieldRegen]
totalRepStr = [formatAmount(rep, 3, 0, 9) for rep in totalRep]
header = "REPS "
lines = [
"Shield ",
"Armor ",
"Hull ",
"Total "
]
showSelfRepColumn = totalSelfRep > 0
showSustainRepColumn = sustainRep != selfRep
showRemoteRepColumn = totalRemoteRep > 0
showShieldRegenColumn = totalShieldRegen > 0
if showSelfRepColumn + showSustainRepColumn + showRemoteRepColumn + showShieldRegenColumn > 1:
header += "{:>7} ".format("TOTAL")
lines = [line + "{:>7} ".format(rep) for line, rep in zip(lines, totalRepStr)]
if showSelfRepColumn:
header += "{:>7} ".format("SELF")
lines = [line + "{:>7} ".format(rep) for line, rep in zip(lines, selfRepStr)]
if showSustainRepColumn:
header += "{:>7} ".format("SUST")
lines = [line + "{:>7} ".format(rep) for line, rep in zip(lines, sustainRepStr)]
if showRemoteRepColumn:
header += "{:>7} ".format("REMOTE")
lines = [line + "{:>7} ".format(rep) for line, rep in zip(lines, remoteRepStr)]
if showShieldRegenColumn:
header += "{:>7} ".format("REGEN")
lines = [line + "{:>7} ".format(rep) for line, rep in zip(lines, shieldRegenStr)]
text += header + "\n"
repsByTank = zip(totalRep, selfRep, sustainRep, remoteRep, shieldRegen)
for line in lines:
reps = next(repsByTank)
if sum(reps) > 0:
text += line + "\n"
return text
def miscSection(fit):
text = ""
text += "Speed: {} m/s\n".format(formatAmount(fit.maxSpeed, 3, 0, 0))
text += "Signature: {} m\n".format(formatAmount(fit.ship.getModifiedItemAttr("signatureRadius"), 3, 0, 9))
text += "Capacitor: {} GJ".format(formatAmount(fit.ship.getModifiedItemAttr("capacitorCapacity"), 3, 0, 9))
capState = fit.capState
if fit.capStable:
text += " (Stable at {0:.0f}%)".format(capState)
else:
text += " (Lasts {})".format("%ds" % capState if capState <= 60 else "%dm%ds" % divmod(capState, 60))
text += "\n"
text += "Targeting range: {} km\n".format(formatAmount(fit.maxTargetRange / 1000, 3, 0, 0))
text += "Scan resolution: {0:.0f} mm\n".format(fit.ship.getModifiedItemAttr("scanResolution"))
text += "Sensor strength: {}\n".format(formatAmount(fit.scanStrength, 3, 0, 0))
return text
def statsExportText(fit):
""" Returns the text of the stats export of the given fit"""
sections = filter(None, (firepowerSection(fit), # Prune empty sections
tankSection(fit),
repsSection(fit),
miscSection(fit)))
text = "{} ({})\n".format(fit.name, fit.ship.name) + "\n"
text += "\n".join(sections)
return text