Added a crude data exporter for effs

Known to be quite buggy and needs formating adjustments.
In order to export fit data it first requires data to be exported with pyfas minimal html exporter.
The resulting pyfaFits.html file should be placed in the project directory before running effs_stat_export.py.
This commit is contained in:
Maru Maru
2018-03-11 03:28:48 -04:00
parent 373e0a390b
commit 0de950862b

474
effs_stat_export.py Executable file
View File

@@ -0,0 +1,474 @@
import inspect
import os
import platform
import re
import sys
import traceback
from optparse import AmbiguousOptionError, BadOptionError, OptionParser
from logbook import CRITICAL, DEBUG, ERROR, FingersCrossedHandler, INFO, Logger, NestedSetup, NullHandler, StreamHandler, TimedRotatingFileHandler, WARNING, \
__version__ as logbook_version
import config
try:
import wxversion
except ImportError:
wxversion = None
try:
import sqlalchemy
except ImportError:
sqlalchemy = None
pyfalog = Logger(__name__)
class PassThroughOptionParser(OptionParser):
def _process_args(self, largs, rargs, values):
while rargs:
try:
OptionParser._process_args(self, largs, rargs, values)
except (BadOptionError, AmbiguousOptionError) as e:
pyfalog.error("Bad startup option passed.")
largs.append(e.opt_str)
usage = "usage: %prog [--root]"
parser = PassThroughOptionParser(usage=usage)
parser.add_option("-r", "--root", action="store_true", dest="rootsavedata", help="if you want pyfa to store its data in root folder, use this option", default=False)
parser.add_option("-w", "--wx28", action="store_true", dest="force28", help="Force usage of wxPython 2.8", default=False)
parser.add_option("-d", "--debug", action="store_true", dest="debug", help="Set logger to debug level.", default=False)
parser.add_option("-t", "--title", action="store", dest="title", help="Set Window Title", default=None)
parser.add_option("-s", "--savepath", action="store", dest="savepath", help="Set the folder for savedata", default=None)
parser.add_option("-l", "--logginglevel", action="store", dest="logginglevel", help="Set desired logging level [Critical|Error|Warning|Info|Debug]", default="Error")
(options, args) = parser.parse_args()
if options.rootsavedata is True:
config.saveInRoot = True
# set title if it wasn't supplied by argument
if options.title is None:
options.title = "pyfa %s%s - Python Fitting Assistant" % (config.version, "" if config.tag.lower() != 'git' else " (git)")
config.debug = options.debug
# convert to unicode if it is set
if options.savepath is not None:
options.savepath = unicode(options.savepath)
config.defPaths(options.savepath)
try:
# noinspection PyPackageRequirements
import wx
except:
exit_message = "Cannot import wxPython. You can download wxPython (2.8+) from http://www.wxpython.org/"
raise PreCheckException(exit_message)
try:
import requests
config.requestsVersion = requests.__version__
except ImportError:
raise PreCheckException("Cannot import requests. You can download requests from https://pypi.python.org/pypi/requests.")
import eos.db
#if config.saVersion[0] > 0 or config.saVersion[1] >= 7:
# <0.7 doesn't have support for events ;_; (mac-deprecated)
config.sa_events = True
import eos.events
# noinspection PyUnresolvedReferences
import service.prefetch # noqa: F401
# Make sure the saveddata db exists
if not os.path.exists(config.savePath):
os.mkdir(config.savePath)
eos.db.saveddata_meta.create_all()
armorLinkShip = eos.db.searchFits('armor links')[0]
infoLinkShip = eos.db.searchFits('information links')[0]
shieldLinkShip = eos.db.searchFits('shield links')[0]
skirmishLinkShip = eos.db.searchFits('skirmish links')[0]
import json
def processExportedHtml(fileLocation):
output = open('./jsonShipStatExport.js', 'w')
output.write('let shipJSON = JSON.stringify([')
outputBaseline = open('./jsonShipBaseStatExport.js', 'w')
outputBaseline.write('let shipBaseJSON = JSON.stringify([')
shipCata = eos.db.getItemsByCategory('Ship')
#shipCata = eos.db.getItem(638)
#shipCata = eos.db.getMetaGroup(638)
#shipCata = eos.db.getAttributeInfo(638)
#shipCata = eos.db.getItemsByCategory('Traits')
#shipCata = eos.db.getGroup('invtraits')
#shipCata = eos.db.getCategory('Traits')
from sqlalchemy import Column, String, Integer, ForeignKey, Boolean, Table
from sqlalchemy.orm import relation, mapper, synonym, deferred
from eos.db import gamedata_session
from eos.db import gamedata_meta
from eos.db.gamedata.metaGroup import metatypes_table, items_table
from eos.db.gamedata.group import groups_table
from eos.gamedata import AlphaClone, Attribute, Category, Group, Item, MarketGroup, \
MetaGroup, AttributeInfo, MetaData, Effect, ItemEffect, Traits
from eos.db.gamedata.traits import traits_table
#shipCata = traits_table #categories_table
#print shipCata
#print shipCata.columns
#print shipCata.categoryName
#print vars(shipCata)
data = category = gamedata_session.query(Category).all()
#print data
#print iter(data)
eff = gamedata_session.query(Category).get(53) #Bonus (id14) #Effects (id 53)
data = eff;
#print eff
#print vars(eff)
things = []#[Category, MetaGroup, AttributeInfo, MetaData, Item, Attribute, Effect, ItemEffect, Traits]#, Attribute]
if False:
for dataTab in things :
print 'Data for: ' + str(dataTab)
try:
filter = dataTab.typeID == 638
except:
filter = dataTab.ID == 638
data = gamedata_session.query(dataTab).options().filter(filter).all()
print data
try:
varDict = vars(data)
print varDict
except:
print 'Not a Dict'
try:
varDict = data.__doc__
print varDict
except:
print 'No items()'
try:
for varDict in data:
print varDict
print vars(varDict)
except:
print 'Not a list of dicts'
#print vars(shipCata._sa_instance_state)
baseLimit = 500
baseN = 0
for ship in iter(shipCata):
if baseN < baseLimit:
#print ship
#print ship.ID
#print ship.categoryName
#print vars(ship)
dna = str(ship.ID)
stats = setFitFromString(dna, ship.name, ship.groupID)
outputBaseline.write(stats)
outputBaseline.write(',\n')
baseN += 1;
limit = 500
skipTill = 0
n = 0
try:
with open('pyfaFits.html'):
fileLocation = 'pyfaFits.html'
except:
try:
with open('.pyfa/pyfaFits.html'):
fileLocation = '.pyfa/pyfaFits.html'
except:
try:
with open('../.pyfa/pyfaFits.html'):
fileLocation = '../.pyfa/pyfaFits.html'
except:
try:
with open('../../.pyfa/pyfaFits.html'):
fileLocation = '../../.pyfa/pyfaFits.html'
except:
fileLocation = None;
if fileLocation != None:
with open(fileLocation) as f:
for fullLine in f:
if limit == None or n < limit:
n += 1
startInd = fullLine.find('/dna/') + 5
line = fullLine[startInd:len(fullLine)]
endInd = line.find('::')
dna = line[0:endInd]
name = line[line.find('>') + 1:line.find('<')]
if n >= skipTill:
print 'name: ' + name + ' DNA: ' + dna
stats = setFitFromString(dna, name, 0)
output.write(stats)
output.write(',\n')
output.write(']);\nexport {shipJSON};')
output.close()
outputBaseline.write(']);\nexport {shipBaseJSON};')
outputBaseline.close()
def parseNeededFitDetails(fit, groupID):
singleRunPrintPreformed = False
weaponSystems = []
groups = {}
#help(fit.modules)
#help(fit.modules[0])
for mod in fit.modules:
if mod.dps > 0:
keystr = str(mod.itemID) + '-' + str(mod.chargeID)
if keystr in groups:
groups[keystr][1] += 1
else:
groups[keystr] = [mod, 1]
for wepGroup in groups:
stats = groups[wepGroup][0]
c = groups[wepGroup][1]
tracking = 0
maxVelocity = 0
explosionDelay = 0
damageReductionFactor = 0
explosionRadius = 0
explosionVelocity = 0
aoeFieldRange = 0
if stats.hardpoint == 2:
tracking = stats.itemModifiedAttributes['trackingSpeed']
typeing = 'Turret'
name = stats.item.name + ', ' + stats.charge.name
elif stats.hardpoint == 1:
maxVelocity = stats.chargeModifiedAttributes['maxVelocity']
explosionDelay = stats.chargeModifiedAttributes['explosionDelay']
damageReductionFactor = stats.chargeModifiedAttributes['aoeDamageReductionFactor']
explosionRadius = stats.chargeModifiedAttributes['aoeCloudSize']
explosionVelocity = stats.chargeModifiedAttributes['aoeVelocity']
typeing = 'Missile'
name = stats.item.name + ', ' + stats.charge.name
elif stats.hardpoint == 0:
aoeFieldRange = stats.itemModifiedAttributes['empFieldRange']
typeing = 'SmartBomb'
name = stats.item.name
statDict = {'dps': stats.dps * c, 'capUse': stats.capUse * c, 'falloff': stats.falloff,\
'type': typeing, 'name': name, 'optimal': stats.maxRange,\
'numCharges': stats.numCharges, 'numShots': stats.numShots, 'reloadTime': stats.reloadTime,\
'cycleTime': stats.cycleTime, 'volley': stats.volley * c, 'tracking': tracking,\
'maxVelocity': maxVelocity, 'explosionDelay': explosionDelay, 'damageReductionFactor': damageReductionFactor,\
'explosionRadius': explosionRadius, 'explosionVelocity': explosionVelocity, 'aoeFieldRange': aoeFieldRange\
}
weaponSystems.append(statDict)
#if fit.droneDPS > 0:
for drone in fit.drones:
if drone.dps[0] > 0 and drone.amountActive > 0:
newTracking = drone.itemModifiedAttributes['trackingSpeed'] / (drone.itemModifiedAttributes['optimalSigRadius'] / 40000)
statDict = {'dps': drone.dps[0], 'cycleTime': drone.cycleTime, 'type': 'Drone',\
'optimal': drone.maxRange, 'name': drone.item.name, 'falloff': drone.falloff,\
'maxSpeed': drone.itemModifiedAttributes['maxVelocity'], 'tracking': newTracking,\
'volley': drone.dps[1]\
}
weaponSystems.append(statDict)
for fighter in fit.fighters:
if fighter.dps[0] > 0 and fighter.amountActive > 0:
abilities = []
#for ability in fighter.abilities:
if 'fighterAbilityAttackMissileDamageEM' in fighter.itemModifiedAttributes:
baseRef = 'fighterAbilityAttackMissile'
baseRefDam = baseRef + 'Damage'
abBaseDamage = fighter.itemModifiedAttributes[baseRefDam + 'EM'] + fighter.itemModifiedAttributes[baseRefDam + 'Therm'] + fighter.itemModifiedAttributes[baseRefDam + 'Exp'] + fighter.itemModifiedAttributes[baseRefDam + 'Kin']
abDamage = abBaseDamage * fighter.itemModifiedAttributes[baseRefDam + 'Multiplier']
ability = {'name': 'RegularAttack', 'volley': abDamage * fighter.amountActive, 'explosionRadius': fighter.itemModifiedAttributes[baseRef + 'ExplosionRadius'],\
'explosionVelocity': fighter.itemModifiedAttributes[baseRef + 'ExplosionVelocity'], 'optimal': fighter.itemModifiedAttributes[baseRef + 'RangeOptimal'],\
'damageReductionFactor': fighter.itemModifiedAttributes[baseRef + 'ReductionFactor'], 'rof': fighter.itemModifiedAttributes[baseRef + 'Duration'],\
}
abilities.append(ability)
if 'fighterAbilityMissilesDamageEM' in fighter.itemModifiedAttributes:
baseRef = 'fighterAbilityMissiles'
baseRefDam = baseRef + 'Damage'
abBaseDamage = fighter.itemModifiedAttributes[baseRefDam + 'EM'] + fighter.itemModifiedAttributes[baseRefDam + 'Therm'] + fighter.itemModifiedAttributes[baseRefDam + 'Exp'] + fighter.itemModifiedAttributes[baseRefDam + 'Kin']
abDamage = abBaseDamage * fighter.itemModifiedAttributes[baseRefDam + 'Multiplier']
ability = {'name': 'MissileAttack', 'volley': abDamage * fighter.amountActive, 'explosionRadius': fighter.itemModifiedAttributes[baseRef + 'ExplosionRadius'],\
'explosionVelocity': fighter.itemModifiedAttributes[baseRef + 'ExplosionVelocity'], 'optimal': fighter.itemModifiedAttributes[baseRef + 'Range'],\
'damageReductionFactor': fighter.itemModifiedAttributes[baseRefDam + 'ReductionFactor'], 'rof': fighter.itemModifiedAttributes[baseRef + 'Duration'],\
}
abilities.append(ability)
statDict = {'dps': fighter.dps[0], 'type': 'Fighter', 'name': fighter.item.name,\
'maxSpeed': fighter.itemModifiedAttributes['maxVelocity'], 'abilities': abilities, 'ehp': fighter.itemModifiedAttributes['shieldCapacity'] / 0.8875 * fighter.amountActive,\
'volley': fighter.dps[1], 'signatureRadius': fighter.itemModifiedAttributes['signatureRadius']\
}
weaponSystems.append(statDict)
turretSlots = fit.ship.itemModifiedAttributes['turretSlotsLeft']
launcherSlots = fit.ship.itemModifiedAttributes['launcherSlotsLeft']
droneBandwidth = fit.ship.itemModifiedAttributes['droneBandwidth']
if turretSlots == None:
turretSlots = 0
if launcherSlots == None:
launcherSlots = 0
if droneBandwidth == None:
droneBandwidth = 0
effectiveTurretSlots = turretSlots
effectiveLauncherSlots = launcherSlots
effectiveDroneBandwidth = droneBandwidth
from eos.db import gamedata_session
from eos.gamedata import Traits
filter = Traits.typeID == fit.shipID
data = gamedata_session.query(Traits).options().filter(filter).all()
roleBonusMode = False
if len(data) != 0:
print data[0].traitText
for bonusText in data[0].traitText.splitlines():
bonusText = bonusText.lower()
#print 'bonus text line: ' + bonusText
if 'per skill level' in bonusText:
roleBonusMode = False
if 'role bonus' in bonusText:
roleBonusMode = True
multi = 1
if 'damage' in bonusText and not 'control' in bonusText:
splitText = bonusText.split('%')
if float(splitText[0]) > 0 == False:
pyfalog.error('damage bonus split did not parse correctly!')
if roleBonusMode:
addedMulti = float(splitText[0])
else:
addedMulti = float(splitText[0]) * 5
multi = 1 + (addedMulti / 100)
elif 'rate of fire' in bonusText:
splitText = bonusText.split('%')
if splitText[0] > 0 == False:
pyfalog.error('rate of fire bonus split did not parse correctly!')
if roleBonusMode:
rofMulti = float(splitText[0])
else:
rofMulti = float(splitText[0]) * 5
multi = 1 / (1 - (rofMulti / 100))
if multi > 1:
if 'drone' in bonusText.lower():
effectiveDroneBandwidth *= multi
elif 'turret' in bonusText.lower():
effectiveTurretSlots *= multi
elif 'missile' in bonusText.lower():
effectiveLauncherSlots *= multi
effectiveTurretSlots = round(effectiveTurretSlots, 2);
effectiveLauncherSlots = round(effectiveLauncherSlots, 2);
effectiveDroneBandwidth = round(effectiveDroneBandwidth, 2);
hullResonance = {'exp': fit.ship.itemModifiedAttributes['explosiveDamageResonance'], 'kin': fit.ship.itemModifiedAttributes['kineticDamageResonance'], \
'therm': fit.ship.itemModifiedAttributes['thermalDamageResonance'], 'em': fit.ship.itemModifiedAttributes['emDamageResonance']}
armorResonance = {'exp': fit.ship.itemModifiedAttributes['armorExplosiveDamageResonance'], 'kin': fit.ship.itemModifiedAttributes['armorKineticDamageResonance'], \
'therm': fit.ship.itemModifiedAttributes['armorThermalDamageResonance'], 'em': fit.ship.itemModifiedAttributes['armorEmDamageResonance']}
shieldResonance = {'exp': fit.ship.itemModifiedAttributes['shieldExplosiveDamageResonance'], 'kin': fit.ship.itemModifiedAttributes['shieldKineticDamageResonance'], \
'therm': fit.ship.itemModifiedAttributes['shieldThermalDamageResonance'], 'em': fit.ship.itemModifiedAttributes['shieldEmDamageResonance']}
resonance = {'hull': hullResonance, 'armor': armorResonance, 'shield': shieldResonance}
shipSizes = ['Frigate', 'Destroyer', 'Cruiser', 'Battlecruiser', 'Battleship', 'Capital', 'Industrial', 'Misc']
if groupID in [25, 31, 237, 324, 830, 831, 834, 893, 1283, 1527]:
shipSize = shipSizes[0]
elif groupID in [420, 541, 1305, 1534]:
shipSize = shipSizes[1]
elif groupID in [26, 358, 832, 833, 894, 906, 963]:
shipSize = shipSizes[2]
elif groupID in [419, 540, 1201]:
shipSize = shipSizes[3]
elif groupID in [27, 381, 898, 900]:
shipSize = shipSizes[4]
elif groupID in [30, 485, 513, 547, 659, 883, 902, 1538]:
shipSize = shipSizes[5]
elif groupID in [28, 380, 1202, 463, 543, 941]:
shipSize = shipSizes[6]
elif groupID in [29, 1022]:
shipSize = shipSizes[7]
else:
shipSize = 'ShipSize not found for ' + fit.name + ' groupID: ' + str(groupID)
print shipSize
try:
parsable = {'name': fit.name, 'ehp': fit.ehp, 'droneDPS': fit.droneDPS, \
'droneVolley': fit.droneVolley, 'hp': fit.hp, 'maxTargets': fit.maxTargets, \
'maxSpeed': fit.maxSpeed, 'weaponVolley': fit.weaponVolley, 'totalVolley': fit.totalVolley,\
'maxTargetRange': fit.maxTargetRange, 'scanStrength': fit.scanStrength,\
'weaponDPS': fit.weaponDPS, 'alignTime': fit.alignTime, 'signatureRadius': fit.ship.itemModifiedAttributes['signatureRadius'],\
'weapons': weaponSystems, 'scanRes': fit.ship.itemModifiedAttributes['scanResolution'],\
'projectedModules': fit.projectedModules, 'capUsed': fit.capUsed, 'capRecharge': fit.capRecharge,\
'rigSlots': fit.ship.itemModifiedAttributes['rigSlots'], 'lowSlots': fit.ship.itemModifiedAttributes['lowSlots'],\
'midSlots': fit.ship.itemModifiedAttributes['medSlots'], 'highSlots': fit.ship.itemModifiedAttributes['hiSlots'],\
'turretSlots': fit.ship.itemModifiedAttributes['turretSlotsLeft'], 'launcherSlots': fit.ship.itemModifiedAttributes['launcherSlotsLeft'],\
'powerOutput': fit.ship.itemModifiedAttributes['powerOutput'], 'rigSize': fit.ship.itemModifiedAttributes['rigSize'],\
'effectiveTurrets': effectiveTurretSlots, 'effectiveLaunchers': effectiveLauncherSlots, 'effectiveDroneBandwidth': effectiveDroneBandwidth,\
'resonance': resonance, 'typeID': fit.shipID, 'groupID': groupID, 'shipSize': shipSize\
}
except TypeError:
print 'Error parsing fit:' + str(fit)
print TypeError
parsable = {'name': fit.name + 'Fit could not be correctly parsed'}
#print fit.ship.itemModifiedAttributes.items()
#help(fit)
#if len(fit.fighters) > 5:
#print fit.fighters
#help(fit.fighters[0])
stringified = json.dumps(parsable, skipkeys=True)
return stringified
def setFitFromString(dnaString, fitName, groupID) :
modArray = dnaString.split(':')
fitL = Fit()
print modArray[0]
fitID = fitL.newFit(int(modArray[0]), fitName)
fit = eos.db.getFit(fitID)
ammoArray = []
n = -1
for mod in iter(modArray):
n = n + 1
if n > 0:
#print n
#print mod
modSp = mod.split(';')
if len(modSp) == 2:
k = 0
while k < int(modSp[1]):
k = k + 1
itemID = int(modSp[0])
item = eos.db.getItem(int(modSp[0]), eager=("attributes", "group.category"))
cat = item.category.name
if cat == 'Drone':
fitL.addDrone(fitID, itemID, int(modSp[1]), recalc=False)
k += int(modSp[1])
if cat == 'Fighter':
fitL.addFighter(fitID, itemID, recalc=False)
#fit.fighters.last.abilities.active = True
k += 100
if fitL.isAmmo(int(modSp[0])):
k += 100
ammoArray.append(int(modSp[0]));
fitL.appendModule(fitID, int(modSp[0]))
fit = eos.db.getFit(fitID)
#nonEmptyModules = fit.modules
#while nonEmptyModules.find(None) >= 0:
# print 'ssssssssssssssss'
# nonEmptyModules.remove(None)
for ammo in iter(ammoArray):
fitL.setAmmo(fitID, ammo, fit.modules)
if len(fit.drones) > 0:
fit.drones[0].amountActive = fit.drones[0].amount
eos.db.commit()
for fighter in iter(fit.fighters):
for ability in fighter.abilities:
if ability.effect.handlerName == u'fighterabilityattackm' and ability.active == True:
for abilityAltRef in fighter.abilities:
if abilityAltRef.effect.isImplemented:
abilityAltRef.active = True
fitL.recalc(fit)
fit = eos.db.getFit(fitID)
#print fit.modules
#fit.calculateWeaponStats()
fitL.addCommandFit(fit.ID, armorLinkShip)
fitL.addCommandFit(fit.ID, shieldLinkShip)
fitL.addCommandFit(fit.ID, skirmishLinkShip)
fitL.addCommandFit(fit.ID, infoLinkShip)
#def anonfunc(unusedArg): True
jsonStr = parseNeededFitDetails(fit, groupID)
#print vars(fit.ship._Ship__item)
#help(fit)
Fit.deleteFit(fitID)
return jsonStr
launchUI = False
#launchUI = True
if launchUI == False:
from service.fit import Fit
#setFitFromString(dnaChim, 'moMachsD')
#help(eos.db.getItem)
#ship = es_Ship(eos.db.getItem(27))
processExportedHtml('../.pyfa/pyfaFits.html')