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()]) 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): def getRequiredFor(itemID, attrMapping):
Attribute1 = aliased(Attribute) Attribute1 = aliased(Attribute)
Attribute2 = aliased(Attribute) Attribute2 = aliased(Attribute)

View File

@@ -22,7 +22,7 @@ import re
from logbook import Logger 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.cargo import Cargo
from eos.saveddata.citadel import Citadel from eos.saveddata.citadel import Citadel
from eos.saveddata.booster import Booster 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' OFFLINE_SUFFIX = ' /OFFLINE'
def fetchItem(typeName, eagerCat=True): def fetchItem(typeName, eagerCat=False):
sMkt = Market.getInstance() sMkt = Market.getInstance()
eager = 'group.category' if eagerCat else None eager = 'group.category' if eagerCat else None
try: try:
@@ -150,7 +150,7 @@ class RegularItemSpec(BaseItemSpec):
def __fetchCharge(self, chargeName): def __fetchCharge(self, chargeName):
if chargeName: if chargeName:
charge = fetchItem(chargeName, eagerCat=True) charge = fetchItem(chargeName, eagerCat=True)
if charge.category.name != 'Charge': if not charge or charge.category.name != 'Charge':
charge = None charge = None
else: else:
charge = None charge = None
@@ -203,6 +203,8 @@ class AbstractFit:
self.drones = {} # Format: {item: Drone} self.drones = {} # Format: {item: Drone}
self.fighters = [] self.fighters = []
self.cargo = {} # Format: {item: Cargo} self.cargo = {} # Format: {item: Cargo}
# Other stuff
self.mutations = {} # Format: {reference: (mutaplamid item, {attr ID: attr value})}
@property @property
def __slotContainerMap(self): def __slotContainerMap(self):
@@ -259,10 +261,28 @@ class AbstractFit:
self.getContainerBySlot(m.slot).append(m) self.getContainerBySlot(m.slot).append(m)
def __makeModule(self, itemSpec): def __makeModule(self, itemSpec):
try: # Mutate item if needed
m = Module(itemSpec.item) m = None
except ValueError: if itemSpec.mutationIdx in self.mutations:
return None 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): if itemSpec.charge is not None and m.isValidCharge(itemSpec.charge):
m.charge = itemSpec.charge m.charge = itemSpec.charge
if itemSpec.offline and m.isValidState(State.OFFLINE): if itemSpec.offline and m.isValidState(State.OFFLINE):
@@ -425,10 +445,13 @@ class EftPort:
return return
aFit = AbstractFit() aFit = AbstractFit()
aFit.mutations = cls.__getMutationData(lines)
pyfalog.error('{}'.format(aFit.mutations))
nameChars = '[^,/\[\]]' # Characters which are allowed to be used in name
stubPattern = '^\[.+\]$' stubPattern = '^\[.+\]$'
modulePattern = '^(?P<typeName>[^,/]+)(, (?P<chargeName>[^,/]+))?(?P<offline>{})?( \[(?P<mutation>\d+)\])?$'.format(OFFLINE_SUFFIX) modulePattern = '^(?P<typeName>{0}+)(, (?P<chargeName>{0}+))?(?P<offline>{1})?( \[(?P<mutation>\d+)\])?$'.format(nameChars, OFFLINE_SUFFIX)
droneCargoPattern = '^(?P<typeName>[^,/]+) x(?P<amount>\d+)$' droneCargoPattern = '^(?P<typeName>{}+) x(?P<amount>\d+)$'.format(nameChars)
sections = [] sections = []
for section in cls.__importSectionIter(lines): for section in cls.__importSectionIter(lines):
@@ -467,6 +490,7 @@ class EftPort:
clearTail(section.itemSpecs) clearTail(section.itemSpecs)
sections.append(section) sections.append(section)
hasDroneBay = any(s.isDroneBay for s in sections) hasDroneBay = any(s.isDroneBay for s in sections)
hasFighterBay = any(s.isFighterBay for s in sections) hasFighterBay = any(s.isFighterBay for s in sections)
for section in sections: for section in sections:
@@ -555,28 +579,61 @@ class EftPort:
del lines[-1] del lines[-1]
return lines return lines
@classmethod @staticmethod
def __createFit(cls, lines): def __getMutationData(lines):
"""Create fit and set top-level entity (ship or citadel).""" data = {}
fit = Fit() consumedIndices = set()
header = lines.pop(0) for i in range(len(lines)):
m = re.match('\[(?P<shipType>[\w\s]+), (?P<fitName>.+)\]', header) line = lines[i]
if not m: m = re.match('^\[(?P<ref>\d+)\]', line)
pyfalog.warning('EftPort.importEft: corrupted fit header') if m:
raise EftImportError ref = int(m.group('ref'))
shipType = m.group('shipType').strip() # Attempt to apply mutation is useless w/o mutaplasmid, so skip it
fitName = m.group('fitName').strip() # altogether if we have no info on it
try: try:
ship = fetchItem(shipType, eagerCat=False) mutaName = lines[i + 1]
try: except IndexError:
fit.ship = Ship(ship) continue
except ValueError: else:
fit.ship = Citadel(ship) consumedIndices.add(i)
fit.name = fitName consumedIndices.add(i + 1)
except: # Get custom attribute values
pyfalog.warning('EftPort.importEft: exception caught when parsing header') mutaAttrs = {}
raise EftImportError try:
return fit 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 @staticmethod
def __importSectionIter(lines): def __importSectionIter(lines):
@@ -590,3 +647,26 @@ class EftPort:
section.lines.append(line) section.lines.append(line)
if section.lines: if section.lines:
yield section 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 return fit_list
@classmethod @classmethod
def exportEft(cls, fit): def exportEft(cls, fit):
return EftPort.exportEft(fit, mutations=False, implants=False) return EftPort.exportEft(fit, mutations=False, implants=False)