Partially cleaned up efs utilities

This commit is contained in:
Maru Maru
2018-05-27 04:07:21 -04:00
parent 2a410a13a0
commit 05e76a884a
6 changed files with 614 additions and 474 deletions

View File

@@ -4,249 +4,49 @@ 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
from math import log
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()
import json
from service.fit import Fit
def processExportedHtml():
basePath = config.savePath + os.sep
output = open(basePath + 'shipJSON.js', 'w')
output.write('let shipJSON = JSON.stringify([')
outputBaseline = open(basePath + 'shipBaseJSON.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().list(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 = 0
baseN = 0
nameReqBase = '';
for ship in iter(shipCata):
if baseN < baseLimit and nameReqBase in ship.name:
dna = str(ship.ID)
stats = setFitFromString(dna, ship.name, ship.groupID)
outputBaseline.write(stats)
outputBaseline.write(',\n')
baseN += 1;
limit = 10
skipTill = 0
nameReq = ''
n = 0
try:
with open('pyfaFits.html'):
fileLocation = 'pyfaFits.html'
except:
try:
d = config.savePath + os.sep + 'pyfaFits.html'
print(d)
with open(d):
fileLocation = d
except:
fileLocation = None;
fitList = eos.db.getFitList()
with open(fileLocation) as f:
for fit in fitList:
if limit == None or n < limit:
n += 1
name = fit.ship.name + ': ' + fit.name
if n >= skipTill and nameReq in name:
stats = parseNeededFitDetails(fit, 0)
output.write(stats)
output.write(',\n')
if False and 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 and nameReq in name:
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 attrDirectMap(values, target, source):
for val in values:
target[val] = source.itemModifiedAttributes[val]
def parseNeededFitDetails(fit, groupID):
singleRunPrintPreformed = False
weaponSystems = []
groups = {}
moduleNames = []
fitID = fit.ID
if len(fit.modules) > 0:
fitName = fit.ship.name + ': ' + fit.name
else:
fitName = fit.name
print('')
print('name: ' + fit.name)
fitL = Fit()
fitL.recalc(fit)
fit = eos.db.getFit(fitID)
if False:
from eos.db import gamedata_session
from eos.gamedata import Group, Category
filterVal = Group.categoryID == 6
data = gamedata_session.query(Group).options().list(filter(filterVal).all())
for group in data:
print(group.groupName + ' groupID: ' + str(group.groupID))
#print(group.categoryName + ' categoryID: ' + str(group.categoryID) + ', published: ' + str(group.published)
#print(vars(group)
#print(''
return ''
projectedModGroupIds = [
41, 52, 65, 67, 68, 71, 80, 201, 208, 291, 325, 379, 585,
842, 899, 1150, 1154, 1189, 1306, 1672, 1697, 1698, 1815, 1894
]
projectedMods = list(filter(lambda mod: mod.item and mod.item.groupID in projectedModGroupIds, fit.modules))
unpropedSpeed = fit.maxSpeed
unpropedSig = fit.ship.itemModifiedAttributes['signatureRadius']
usingMWD = False
def getT2MwdSpeed(fit, fitL):
fitID = fit.ID
propID = None
rigSize = fit.ship.itemModifiedAttributes['rigSize']
if rigSize == 1 and fit.ship.itemModifiedAttributes['medSlots'] > 0:
propID = 440
elif rigSize == 2 and fit.ship.itemModifiedAttributes['medSlots'] > 0:
propID = 12076
elif rigSize == 3 and fit.ship.itemModifiedAttributes['medSlots'] > 0:
propID = 12084
elif rigSize == 4 and fit.ship.itemModifiedAttributes['medSlots'] > 0:
if fit.ship.itemModifiedAttributes['powerOutput'] > 60000:
propID = 41253
else:
propID = 12084
elif rigSize == None and fit.ship.itemModifiedAttributes['medSlots'] > 0:
propID = 440
if propID:
fitL.appendModule(fitID, propID)
fitL.recalc(fit)
fit = eos.db.getFit(fitID)
mwdPropSpeed = fit.maxSpeed
mwdPosition = list(filter(lambda mod: mod.item and mod.item.ID == propID, fit.modules))[0].position
fitL.removeModule(fitID, mwdPosition)
fitL.recalc(fit)
fit = eos.db.getFit(fitID)
return mwdPropSpeed
def getPropData(fit, fitL):
fitID = fit.ID
propMods = list(filter(lambda mod: mod.item and mod.item.groupID in [46], fit.modules))
possibleMWD = list(filter(lambda mod: 'signatureRadiusBonus' in mod.item.attributes, propMods))
if len(possibleMWD) > 0 and possibleMWD[0].state > 0:
@@ -255,42 +55,21 @@ def parseNeededFitDetails(fit, groupID):
mwd.state = 0
fitL.recalc(fit)
fit = eos.db.getFit(fitID)
unpropedSpeed = fit.maxSpeed
unpropedSig = fit.ship.itemModifiedAttributes['signatureRadius']
sp = fit.maxSpeed
sig = fit.ship.itemModifiedAttributes['signatureRadius']
mwd.state = oldMwdState
fitL.recalc(fit)
fit = eos.db.getFit(fitID)
usingMWD = True
print(fit.ship.itemModifiedAttributes['rigSize'])
print(propMods)
mwdPropSpeed = fit.maxSpeed
if groupID > 0:
propID = None
rigSize = fit.ship.itemModifiedAttributes['rigSize']
if rigSize == 1 and fit.ship.itemModifiedAttributes['medSlots'] > 0:
propID = 440
elif rigSize == 2 and fit.ship.itemModifiedAttributes['medSlots'] > 0:
propID = 12076
elif rigSize == 3 and fit.ship.itemModifiedAttributes['medSlots'] > 0:
propID = 12084
elif rigSize == 4 and fit.ship.itemModifiedAttributes['medSlots'] > 0:
if fit.ship.itemModifiedAttributes['powerOutput'] > 60000:
propID = 41253
else:
propID = 12084
elif rigSize == None and fit.ship.itemModifiedAttributes['medSlots'] > 0:
propID = 440
if propID:
fitL.appendModule(fitID, propID)
fitL.recalc(fit)
fit = eos.db.getFit(fitID)
mwdPropSpeed = fit.maxSpeed
mwdPosition = list(filter(lambda mod: mod.item and mod.item.ID == propID, fit.modules))[0].position
fitL.removeModule(fitID, mwdPosition)
fitL.recalc(fit)
fit = eos.db.getFit(fitID)
return {'usingMWD': True, 'unpropedSpeed': sp, 'unpropedSig': sig}
return {'usingMWD': False, 'unpropedSpeed': fit.maxSpeed, 'unpropedSig': fit.ship.itemModifiedAttributes['signatureRadius']}
def getOutgoingProjectionData(fit):
# This is a subset of module groups capable of projection and a superset of those currently used by efs
projectedModGroupIds = [
41, 52, 65, 67, 68, 71, 80, 201, 208, 291, 325, 379, 585,
842, 899, 1150, 1154, 1189, 1306, 1672, 1697, 1698, 1815, 1894
]
projectedMods = list(filter(lambda mod: mod.item and mod.item.groupID in projectedModGroupIds, fit.modules))
projections = []
for mod in projectedMods:
stats = {}
@@ -356,15 +135,10 @@ def parseNeededFitDetails(fit, groupID):
stats['falloff'] = mod.itemModifiedAttributes['falloffEffectiveness'] or 0
attrDirectMap(['duration', 'capacitorNeed'], stats, mod)
projections.append(stats)
#print(''
#print(stats
#print(mod.item.name
#print(mod.itemModifiedAttributes.items()
#print(''
#print(vars(mod.item)
#print(vars(web.itemModifiedAttributes)
#print(vars(fit.modules)
#print(vars(fit.modules[0])
return projections
def getModuleNames(fit):
moduleNames = []
highSlotNames = []
midSlotNames = []
lowSlotNames = []
@@ -393,12 +167,6 @@ def parseNeededFitDetails(fit, groupID):
print(vars(mod))
print('could not find name for module')
print(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 modInfo in [['High Slots:'], highSlotNames, ['', 'Med Slots:'], midSlotNames, ['', 'Low Slots:'], lowSlotNames, ['', 'Rig Slots:'], rigSlotNames]:
moduleNames.extend(modInfo)
if len(miscSlotNames) > 0:
@@ -409,10 +177,10 @@ def parseNeededFitDetails(fit, groupID):
fighterNames = []
for drone in fit.drones:
if drone.amountActive > 0:
droneNames.append(drone.item.name)
droneNames.append("%s x%s" % (drone.item.name, drone.amount))
for fighter in fit.fighters:
if fighter.amountActive > 0:
fighterNames.append(fighter.item.name)
fighterNames.append("%s x%s" % (fighter.item.name, fighter.amountActive))
if len(droneNames) > 0:
moduleNames.append('')
moduleNames.append('Drones:')
@@ -431,7 +199,18 @@ def parseNeededFitDetails(fit, groupID):
moduleNames.append('Command Fits:')
for commandFit in fit.commandFits:
moduleNames.append(commandFit.name)
return moduleNames
def getWeaponSystemData(fit):
weaponSystems = []
groups = {}
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]
@@ -507,216 +286,161 @@ def parseNeededFitDetails(fit, groupID):
'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
return weaponSystems
def getWeaponBonusMultipliers(fit):
multipliers = {'turret': 1, 'launcher': 1, 'droneBandwidth': 1}
from eos.db import gamedata_session
from eos.gamedata import Traits
filterVal = Traits.typeID == fit.shipID
data = gamedata_session.query(Traits).options().filter(filterVal).all()
roleBonusMode = False
if len(data) != 0:
#print(data[0].traitText
previousTypedBonus = 0
previousDroneTypeBonus = 0
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 or 'misc bonus' in bonusText:
roleBonusMode = True
multi = 1
if 'damage' in bonusText and not any(e in bonusText for e in ['control', 'heat']):#'control' in bonusText and not 'heat' in bonusText:
splitText = bonusText.split('%')
if (float(splitText[0]) > 0) == False:
print('damage bonus split did not parse correctly!')
print(float(splitText[0]))
if roleBonusMode:
addedMulti = float(splitText[0])
if len(data) == 0:
return multipliers
previousTypedBonus = 0
previousDroneTypeBonus = 0
for bonusText in data[0].traitText.splitlines():
bonusText = bonusText.lower()
if 'per skill level' in bonusText:
roleBonusMode = False
if 'role bonus' in bonusText or 'misc bonus' in bonusText:
roleBonusMode = True
multi = 1
if 'damage' in bonusText and not any(e in bonusText for e in ['control', 'heat']):
splitText = bonusText.split('%')
if (float(splitText[0]) > 0) == False:
print('damage bonus split did not parse correctly!')
print(float(splitText[0]))
if roleBonusMode:
addedMulti = float(splitText[0])
else:
addedMulti = float(splitText[0]) * 5
if any(e in bonusText for e in [' em', 'thermal', 'kinetic', 'explosive']):
if addedMulti > previousTypedBonus:
previousTypedBonus = addedMulti
else:
addedMulti = float(splitText[0]) * 5
if any(e in bonusText for e in [' em', 'thermal', 'kinetic', 'explosive']):
if addedMulti > previousTypedBonus:
previousTypedBonus = addedMulti
else:
addedMulti = 0
if any(e in bonusText for e in ['heavy drone', 'medium drone', 'light drone', 'sentry drone']):
if addedMulti > previousDroneTypeBonus:
previousDroneTypeBonus = addedMulti
else:
addedMulti = 0
multi = 1 + (addedMulti / 100)
elif 'rate of fire' in bonusText:
splitText = bonusText.split('%')
if (float(splitText[0]) > 0) == False:
print('rate of fire bonus split did not parse correctly!')
print(float(splitText[0]))
if roleBonusMode:
rofMulti = float(splitText[0])
addedMulti = 0
if any(e in bonusText for e in ['heavy drone', 'medium drone', 'light drone', 'sentry drone']):
if addedMulti > previousDroneTypeBonus:
previousDroneTypeBonus = addedMulti
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 any(e in bonusText for e in ['missile', 'torpedo']):
effectiveLauncherSlots *= multi
addedMulti = 0
multi = 1 + (addedMulti / 100)
elif 'rate of fire' in bonusText:
splitText = bonusText.split('%')
if (float(splitText[0]) > 0) == False:
print('rate of fire bonus split did not parse correctly!')
print(float(splitText[0]))
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():
multipliers['droneBandwidth'] *= multi
elif 'turret' in bonusText.lower():
multipliers['turret'] *= multi
elif any(e in bonusText for e in ['missile', 'torpedo']):
multipliers['launcher'] *= multi
return multipliers
def getShipSize(groupID):
# Sizings are somewhat arbitrary but allow for a more managable number of top level groupings in a tree structure.
shipSizes = ['Frigate', 'Destroyer', 'Cruiser', 'Battlecruiser', 'Battleship', 'Capital', 'Industrial', 'Misc']
if groupID in [25, 31, 237, 324, 830, 831, 834, 893, 1283, 1527]:
return shipSizes[0]
elif groupID in [420, 541, 1305, 1534]:
return shipSizes[1]
elif groupID in [26, 358, 832, 833, 894, 906, 963]:
return shipSizes[2]
elif groupID in [419, 540, 1201]:
return shipSizes[3]
elif groupID in [27, 381, 898, 900]:
return shipSizes[4]
elif groupID in [30, 485, 513, 547, 659, 883, 902, 1538]:
return shipSizes[5]
elif groupID in [28, 380, 1202, 463, 543, 941]:
return shipSizes[6]
elif groupID in [29, 1022]:
return shipSizes[7]
else:
sizeNotFoundMsg = 'ShipSize not found for groupID: ' + str(groupID)
print(sizeNotFoundMsg)
return sizeNotFoundMsg
def parseNeededFitDetails(fit, groupID):
includeShipTypeData = groupID > 0
fitID = fit.ID
if len(fit.modules) > 0:
fitName = fit.ship.name + ': ' + fit.name
else:
fitName = fit.name
print('')
print('name: ' + fit.name)
fitL = Fit()
fitL.recalc(fit)
fit = eos.db.getFit(fitID)
fitModAttr = fit.ship.itemModifiedAttributes
propData = getPropData(fit, fitL)
print(fitModAttr['rigSize'])
print(propData)
mwdPropSpeed = fit.maxSpeed
if includeShipTypeData:
mwdPropSpeed = getT2MwdSpeed(fit, fitL)
projections = getOutgoingProjectionData(fit)
moduleNames = getModuleNames(fit)
weaponSystems = getWeaponSystemData(fit)
turretSlots = fitModAttr['turretSlotsLeft'] if fitModAttr['turretSlotsLeft'] is not None else 0
launcherSlots = fitModAttr['launcherSlotsLeft'] if fitModAttr['launcherSlotsLeft'] is not None else 0
droneBandwidth = fitModAttr['droneBandwidth'] if fitModAttr['droneBandwidth'] is not None else 0
weaponBonusMultipliers = getWeaponBonusMultipliers(fit)
effectiveTurretSlots = round(turretSlots * weaponBonusMultipliers['turret'], 2);
effectiveLauncherSlots = round(launcherSlots * weaponBonusMultipliers['launcher'], 2);
effectiveDroneBandwidth = round(droneBandwidth * weaponBonusMultipliers['droneBandwidth'], 2);
# Assume a T2 siege module for dreads
if groupID == 485:
effectiveTurretSlots *= 9.4
effectiveLauncherSlots *= 15
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']}
hullResonance = {
'exp': fitModAttr['explosiveDamageResonance'], 'kin': fitModAttr['kineticDamageResonance'], \
'therm': fitModAttr['thermalDamageResonance'], 'em': fitModAttr['emDamageResonance']
}
armorResonance = {
'exp': fitModAttr['armorExplosiveDamageResonance'], 'kin': fitModAttr['armorKineticDamageResonance'], \
'therm': fitModAttr['armorThermalDamageResonance'], 'em': fitModAttr['armorEmDamageResonance']
}
shieldResonance = {
'exp': fitModAttr['shieldExplosiveDamageResonance'], 'kin': fitModAttr['shieldKineticDamageResonance'], \
'therm': fitModAttr['shieldThermalDamageResonance'], 'em': fitModAttr['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 ' + fitName + ' groupID: ' + str(groupID)
print(shipSize)
shipSize = getShipSize(groupID)
try:
parsable = {'name': fitName, '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,\
'droneControlRange': fit.ship.itemModifiedAttributes['droneControlRange'], 'mass': fit.ship.itemModifiedAttributes['mass'],\
'moduleNames': moduleNames, 'projections': projections, 'unpropedSpeed': unpropedSpeed, 'unpropedSig': unpropedSig,\
'usingMWD': usingMWD, 'mwdPropSpeed': mwdPropSpeed
parsable = {
'name': fitName, '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': fitModAttr['signatureRadius'],\
'weapons': weaponSystems, 'scanRes': fitModAttr['scanResolution'],\
'projectedModules': fit.projectedModules, 'capUsed': fit.capUsed, 'capRecharge': fit.capRecharge,\
'rigSlots': fitModAttr['rigSlots'], 'lowSlots': fitModAttr['lowSlots'],\
'midSlots': fitModAttr['medSlots'], 'highSlots': fitModAttr['hiSlots'],\
'turretSlots': fitModAttr['turretSlotsLeft'], 'launcherSlots': fitModAttr['launcherSlotsLeft'],\
'powerOutput': fitModAttr['powerOutput'], 'rigSize': fitModAttr['rigSize'],\
'effectiveTurrets': effectiveTurretSlots, 'effectiveLaunchers': effectiveLauncherSlots,\
'effectiveDroneBandwidth': effectiveDroneBandwidth,\
'resonance': resonance, 'typeID': fit.shipID, 'groupID': groupID, 'shipSize': shipSize,\
'droneControlRange': fitModAttr['droneControlRange'], 'mass': fitModAttr['mass'],\
'moduleNames': moduleNames, 'projections': projections,\
'unpropedSpeed': propData['unpropedSpeed'], 'unpropedSig': propData['unpropedSig'],\
'usingMWD': propData['usingMWD'], 'mwdPropSpeed': mwdPropSpeed
}
except TypeError:
print('Error parsing fit:' + str(fit))
print(TypeError)
parsable = {'name': fitName + '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
try:
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]
except:
armorLinkShip = None
infoLinkShip = None
shieldLinkShip = None
skirmishLinkShip = None
def setFitFromString(dnaString, fitName, groupID) :
if armorLinkShip == None:
print('Cannot find correct link fits for base calculations')
return ''
modArray = dnaString.split(':')
additionalModeFit = ''
#if groupID == 485 and len(modArray) == 1:
#additionalModeFit = ',\n' + setFitFromString(dnaString + ':4292', fitName + ' (Sieged)', groupID)
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, list(filter(lambda mod: str(mod).find('name') > 0, 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(list(filter(lambda mod: mod.item.groupID in [1189, 658], 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 + additionalModeFit
launchUI = False
#launchUI = True
if launchUI == False:
from service.fit import Fit
processExportedHtml()

View File

View File

@@ -0,0 +1,247 @@
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
sys.path.append(os.getcwd())
import config
from math import log
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
config.debug = options.debug
config.defPaths(options.savepath)
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()
import json
from service.fit import Fit
from effs_stat_export import parseNeededFitDetails
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
from eos.saveddata.mode import Mode
def exportBaseShips(opts):
if opts:
if opts.outputpath:
basePath = opts.outputpath
elif opts.savepath:
basePath = opts.savepath
else:
basePath = config.savePath + os.sep
else:
basePath = config.savePath + os.sep
if basePath[len(basePath) - 1] != os.sep:
basePath = basePath + os.sep
outputBaseline = open(basePath + 'shipBaseJSON.js', 'w')
outputBaseline.write('let shipBaseJSON = JSON.stringify([')
shipCata = eos.db.getItemsByCategory('Ship')
baseLimit = 1000
baseN = 0
nameReqBase = '';
for ship in iter(shipCata):
if baseN < baseLimit and nameReqBase in ship.name:
print(ship.name)
print(ship.groupID)
dna = str(ship.ID)
if ship.groupID == 963:
stats = t3cGetStatSet(dna, ship.name, ship.groupID, ship.raceID)
elif ship.groupID == 1305:
stats = t3dGetStatSet(dna, ship.name, ship.groupID, ship.raceID)
else:
stats = setFitFromString(dna, ship.name, ship.groupID)
outputBaseline.write(stats)
outputBaseline.write(',\n')
baseN += 1
outputBaseline.write(']);\nexport {shipBaseJSON};')
outputBaseline.close()
def t3dGetStatSet(dnaString, shipName, groupID, raceID):
t3dModeGroupFilter = Group.groupID == 1306
data = list(gamedata_session.query(Group).options().filter(t3dModeGroupFilter).all())
#Normally we would filter this via the raceID,
#Unfortunately somebody fat fingered the Jackdaw modes raceIDs as 4 (Amarr) not 1 (Caldari)
# t3dModes = list(filter(lambda mode: mode.raceID == raceID, data[0].items)) #Line for if/when they fix it
t3dModes = list(filter(lambda mode: shipName in mode.name, data[0].items))
shipModeData = ''
n = 0
while n < len(t3dModes):
dna = dnaString + ':' + str(t3dModes[n].ID) + ';1'
shipModeData += setFitFromString(dna, t3dModes[n].name, groupID) + ',\n'
n += 1
return shipModeData
def t3cGetStatSet(dnaString, shipName, groupID, raceID):
subsystemFilter = Group.categoryID == 32
data = list(gamedata_session.query(Group).options().filter(subsystemFilter).all())
# multi dimension array to hold the t3c subsystems as ss[index of subsystem type][index subsystem item]
ss = [[], [], [], []]
s = 0
while s < 4:
ss[s] = list(filter(lambda subsystem: subsystem.raceID == raceID, data[s].items))
s += 1
print(shipName)
print(ss)
shipPermutationData = ''
n = 0
a = 0
while a < 3:
b = 0
while b < 3:
c = 0
while c < 3:
d = 0
while d < 3:
dna = dnaString + ':' + str(ss[0][a].ID) \
+ ';1:' + str(ss[1][b].ID) + ';1:' + str(ss[2][c].ID) \
+ ';1:' + str(ss[3][d].ID) + ';1'
name = shipName + str(a) + str(b) + str(c) + str(d)
shipPermutationData += setFitFromString(dna, name, groupID) + ',\n'
d += 1
n += 1
c += 1
b += 1
a += 1
print(str(n) + ' subsystem conbinations for ' + shipName)
return shipPermutationData
try:
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]
except:
armorLinkShip = None
infoLinkShip = None
shieldLinkShip = None
skirmishLinkShip = None
def setFitFromString(dnaString, fitName, groupID) :
if armorLinkShip == None:
print('Cannot find correct link fits for base calculations')
return ''
modArray = dnaString.split(':')
additionalModeFit = ''
fitL = Fit()
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:
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
print(cat)
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)
k += 100
if fitL.isAmmo(int(modSp[0])):
k += 100
ammoArray.append(int(modSp[0]));
# Set mode if module is a mode on a t3d
if item.groupID == 1306 and groupID == 1305:
fitL.setMode(fitID, Mode(item))
else:
fitL.appendModule(fitID, int(modSp[0]))
fit = eos.db.getFit(fitID)
for ammo in iter(ammoArray):
fitL.setAmmo(fitID, ammo, list(filter(lambda mod: str(mod).find('name') > 0, 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(list(filter(lambda mod: mod.item and mod.item.groupID in [1189, 658], fit.modules)))
fitL.addCommandFit(fit.ID, armorLinkShip)
fitL.addCommandFit(fit.ID, shieldLinkShip)
fitL.addCommandFit(fit.ID, skirmishLinkShip)
fitL.addCommandFit(fit.ID, infoLinkShip)
jsonStr = parseNeededFitDetails(fit, groupID)
Fit.deleteFit(fitID)
return jsonStr + additionalModeFit

View File

@@ -0,0 +1,53 @@
import inspect
import os
import platform
import re
import sys
import traceback
sys.path.append(os.getcwd())
import config
from pyfa import options
if options.rootsavedata is True:
config.saveInRoot = True
config.debug = options.debug
config.defPaths(options.savepath)
import eos.db
# Make sure the saveddata db exists
if not os.path.exists(config.savePath):
os.mkdir(config.savePath)
from effs_stat_export import parseNeededFitDetails
def exportPyfaFits(opts):
if opts:
if opts.outputpath:
basePath = opts.outputpath
elif opts.savepath:
basePath = opts.savepath
else:
basePath = config.savePath + os.sep
else:
basePath = config.savePath + os.sep
if basePath[len(basePath) - 1] != os.sep:
basePath = basePath + os.sep
output = open(basePath + 'shipJSON.js', 'w')
output.write('let shipJSON = JSON.stringify([')
#The current storage system isn't going to hold more than 2500 fits as local browser storage is limited
limit = 2500
skipTill = 0
nameReq = ''
n = 0
fitList = eos.db.getFitList()
for fit in fitList:
if limit == None or n < limit:
n += 1
name = fit.ship.name + ': ' + fit.name
if n >= skipTill and nameReq in name:
stats = parseNeededFitDetails(fit, 0)
output.write(stats)
output.write(',\n')
output.write(']);\nexport {shipJSON};')
output.close()

View File

@@ -0,0 +1,60 @@
from effs_export_base_fits import *
def effsFitsFromHTMLExport(opts):
if opts:
if opts.outputpath:
basePath = opts.outputpath
elif opts.savepath:
basePath = opts.savepath
else:
basePath = config.savePath + os.sep
else:
basePath = config.savePath + os.sep
if basePath[len(basePath) - 1] != os.sep:
basePath = basePath + os.sep
output = open(basePath + 'shipJSON.js', 'w')
output.write('let shipJSON = JSON.stringify([')
try:
with open('pyfaFits.html'):
fileLocation = 'pyfaFits.html'
except:
try:
d = config.savePath + os.sep + 'pyfaFits.html'
print(d)
with open(d):
fileLocation = d
except:
fileLocation = None;
limit = 10000
n = 0
skipTill = 0
nameReq = ''
minimalExport = True
if fileLocation != None:
with open(fileLocation) as f:
for fullLine in f:
if limit == None or n < limit:
if n <= 1 and '<!DOCTYPE html>' in fullLine:
minimalExport = False
n += 1
fullIndex = fullLine.find('data-dna="')
minimalIndex = fullLine.find('/dna/')
if fullIndex >= 0:
startInd = fullLine.find('data-dna="') + 10
elif minimalIndex >= 0 and minimalExport:
startInd = fullLine.find('/dna/') + 5
else:
startInd = -1
print(startInd)
if startInd >= 0:
line = fullLine[startInd:len(fullLine)]
endInd = line.find('::')
dna = line[0:endInd]
name = line[line.find('>') + 1:line.find('<')]
if n >= skipTill and nameReq in name:
print('name: ' + name + ' DNA: ' + dna + fullLine)
stats = setFitFromString(dna, name, 0)
output.write(stats)
output.write(',\n')
output.write(']);\nexport {shipJSON};')
output.close()

56
savedata/effs_util.py Normal file
View File

@@ -0,0 +1,56 @@
from optparse import AmbiguousOptionError, BadOptionError, OptionParser
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 [options]"
parser = PassThroughOptionParser(usage=usage)
parser.add_option(
"-f", "--exportfits", action="store_true", dest="exportfits", \
help="Export this copy of pyfa's local fits to a shipJSON file that Eve Fleet Simulator can import from", \
default=False)
parser.add_option(
"-b", "--exportbaseships", action="store_true", dest="exportbaseships", \
help="Export ship stats to a shipBaseJSON file used by Eve Fleet Simulator", \
default=False)
parser.add_option(
"-c", "--convertfitsfromhtml", action="store_true", dest="convertfitsfromhtml", \
help="Convert an exported pyfaFits.html file to a shipJSON file that Eve Fleet Simulator can import from\n"
+ " Note this process loses data like fleet boosters as the DNA format exported by to html contains limited data", \
default=False)
parser.add_option("-s", "--savepath", action="store", dest="savepath", help="Set the folder for savedata", default=None)
parser.add_option(
"-o", "--outputpath", action="store", dest="outputpath",
help="Output directory, defaults to the savepath", default=None)
(options, args) = parser.parse_args()
if options.exportfits:
from effs_export_pyfa_fits import exportPyfaFits
exportPyfaFits(options)
if options.exportbaseships:
from effs_export_base_fits import exportBaseShips
exportBaseShips(options)
if options.convertfitsfromhtml:
from effs_process_html_export import effsFitsFromHTMLExport
effsFitsFromHTMLExport(options)
#stuff bellow this point is purely scrap diagnostic stuff and should not be public (as it's scrawl)
def printGroupData():
from eos.db import gamedata_session
from eos.gamedata import Group, Category
filterVal = Group.categoryID == 6
data = gamedata_session.query(Group).options().list(filter(filterVal).all())
for group in data:
print(group.groupName + ' groupID: ' + str(group.groupID))
return ''