Implement mutated attributes import

This commit is contained in:
DarkPhoenix
2018-08-25 19:27:03 +03:00
parent 93f1a18b37
commit f2c2e2e65a
3 changed files with 126 additions and 32 deletions

View File

@@ -396,6 +396,21 @@ def getAbyssalTypes():
return set([r.resultingTypeID for r in gamedata_session.query(DynamicItem.resultingTypeID).distinct()])
@cachedQuery(1, "itemID")
def getDynamicItem(itemID, eager=None):
try:
if isinstance(itemID, int):
if eager is None:
result = gamedata_session.query(DynamicItem).filter(DynamicItem.ID == itemID).one()
else:
result = gamedata_session.query(DynamicItem).options(*processEager(eager)).filter(DynamicItem.ID == itemID).one()
else:
raise TypeError("Need integer as argument")
except exc.NoResultFound:
result = None
return result
def getRequiredFor(itemID, attrMapping):
Attribute1 = aliased(Attribute)
Attribute2 = aliased(Attribute)

View File

@@ -22,7 +22,7 @@ import re
from logbook import Logger
from eos.db.gamedata.queries import getAttributeInfo
from eos.db.gamedata.queries import getAttributeInfo, getDynamicItem
from eos.saveddata.cargo import Cargo
from eos.saveddata.citadel import Citadel
from eos.saveddata.booster import Booster
@@ -44,7 +44,7 @@ SLOT_ORDER = (Slot.LOW, Slot.MED, Slot.HIGH, Slot.RIG, Slot.SUBSYSTEM, Slot.SERV
OFFLINE_SUFFIX = ' /OFFLINE'
def fetchItem(typeName, eagerCat=True):
def fetchItem(typeName, eagerCat=False):
sMkt = Market.getInstance()
eager = 'group.category' if eagerCat else None
try:
@@ -150,7 +150,7 @@ class RegularItemSpec(BaseItemSpec):
def __fetchCharge(self, chargeName):
if chargeName:
charge = fetchItem(chargeName, eagerCat=True)
if charge.category.name != 'Charge':
if not charge or charge.category.name != 'Charge':
charge = None
else:
charge = None
@@ -203,6 +203,8 @@ class AbstractFit:
self.drones = {} # Format: {item: Drone}
self.fighters = []
self.cargo = {} # Format: {item: Cargo}
# Other stuff
self.mutations = {} # Format: {reference: (mutaplamid item, {attr ID: attr value})}
@property
def __slotContainerMap(self):
@@ -259,10 +261,28 @@ class AbstractFit:
self.getContainerBySlot(m.slot).append(m)
def __makeModule(self, itemSpec):
try:
m = Module(itemSpec.item)
except ValueError:
return None
# Mutate item if needed
m = None
if itemSpec.mutationIdx in self.mutations:
mutaItem, mutaAttrs = self.mutations[itemSpec.mutationIdx]
mutaplasmid = getDynamicItem(mutaItem.ID)
if mutaplasmid:
try:
m = Module(mutaplasmid.resultingItem, itemSpec.item, mutaplasmid)
except ValueError:
pass
else:
for attrID, mutator in m.mutators.items():
if attrID in mutaAttrs:
mutator.value = mutaAttrs[attrID]
# If we still don't have item (item is not mutated or we
# failed to construct mutated item), try to make regular item
if m is None:
try:
m = Module(itemSpec.item)
except ValueError:
return None
if itemSpec.charge is not None and m.isValidCharge(itemSpec.charge):
m.charge = itemSpec.charge
if itemSpec.offline and m.isValidState(State.OFFLINE):
@@ -425,10 +445,13 @@ class EftPort:
return
aFit = AbstractFit()
aFit.mutations = cls.__getMutationData(lines)
pyfalog.error('{}'.format(aFit.mutations))
nameChars = '[^,/\[\]]' # Characters which are allowed to be used in name
stubPattern = '^\[.+\]$'
modulePattern = '^(?P<typeName>[^,/]+)(, (?P<chargeName>[^,/]+))?(?P<offline>{})?( \[(?P<mutation>\d+)\])?$'.format(OFFLINE_SUFFIX)
droneCargoPattern = '^(?P<typeName>[^,/]+) x(?P<amount>\d+)$'
modulePattern = '^(?P<typeName>{0}+)(, (?P<chargeName>{0}+))?(?P<offline>{1})?( \[(?P<mutation>\d+)\])?$'.format(nameChars, OFFLINE_SUFFIX)
droneCargoPattern = '^(?P<typeName>{}+) x(?P<amount>\d+)$'.format(nameChars)
sections = []
for section in cls.__importSectionIter(lines):
@@ -467,6 +490,7 @@ class EftPort:
clearTail(section.itemSpecs)
sections.append(section)
hasDroneBay = any(s.isDroneBay for s in sections)
hasFighterBay = any(s.isFighterBay for s in sections)
for section in sections:
@@ -555,28 +579,61 @@ class EftPort:
del lines[-1]
return lines
@classmethod
def __createFit(cls, lines):
"""Create fit and set top-level entity (ship or citadel)."""
fit = Fit()
header = lines.pop(0)
m = re.match('\[(?P<shipType>[\w\s]+), (?P<fitName>.+)\]', header)
if not m:
pyfalog.warning('EftPort.importEft: corrupted fit header')
raise EftImportError
shipType = m.group('shipType').strip()
fitName = m.group('fitName').strip()
try:
ship = fetchItem(shipType, eagerCat=False)
try:
fit.ship = Ship(ship)
except ValueError:
fit.ship = Citadel(ship)
fit.name = fitName
except:
pyfalog.warning('EftPort.importEft: exception caught when parsing header')
raise EftImportError
return fit
@staticmethod
def __getMutationData(lines):
data = {}
consumedIndices = set()
for i in range(len(lines)):
line = lines[i]
m = re.match('^\[(?P<ref>\d+)\]', line)
if m:
ref = int(m.group('ref'))
# Attempt to apply mutation is useless w/o mutaplasmid, so skip it
# altogether if we have no info on it
try:
mutaName = lines[i + 1]
except IndexError:
continue
else:
consumedIndices.add(i)
consumedIndices.add(i + 1)
# Get custom attribute values
mutaAttrs = {}
try:
mutaAttrsLine = lines[i + 2]
except IndexError:
pass
else:
consumedIndices.add(i + 2)
pairs = [p.strip() for p in mutaAttrsLine.split(',')]
for pair in pairs:
try:
attrName, value = pair.split(' ')
except ValueError:
continue
try:
value = float(value)
except (ValueError, TypeError):
continue
attrInfo = getAttributeInfo(attrName.strip())
if attrInfo is None:
continue
mutaAttrs[attrInfo.ID] = value
mutaItem = fetchItem(mutaName)
if mutaItem is None:
continue
data[ref] = (mutaItem, mutaAttrs)
# If we got here, we have seen at least correct reference line and
# mutaplasmid name line
i += 2
# Bonus points for seeing correct attrs line. Worst case we
# will have to scan it once again
if mutaAttrs:
i += 1
# Cleanup the lines from mutaplasmid info
for i in sorted(consumedIndices, reverse=True):
del lines[i]
return data
@staticmethod
def __importSectionIter(lines):
@@ -590,3 +647,26 @@ class EftPort:
section.lines.append(line)
if section.lines:
yield section
@classmethod
def __createFit(cls, lines):
"""Create fit and set top-level entity (ship or citadel)."""
fit = Fit()
header = lines.pop(0)
m = re.match('\[(?P<shipType>[\w\s]+), (?P<fitName>.+)\]', header)
if not m:
pyfalog.warning('EftPort.importEft: corrupted fit header')
raise EftImportError
shipType = m.group('shipType').strip()
fitName = m.group('fitName').strip()
try:
ship = fetchItem(shipType)
try:
fit.ship = Ship(ship)
except ValueError:
fit.ship = Citadel(ship)
fit.name = fitName
except:
pyfalog.warning('EftPort.importEft: exception caught when parsing header')
raise EftImportError
return fit

View File

@@ -908,7 +908,6 @@ class Port(object):
return fit_list
@classmethod
def exportEft(cls, fit):
return EftPort.exportEft(fit, mutations=False, implants=False)