Merge remote-tracking branch 'origin/master' into spoolup_support
This commit is contained in:
@@ -210,8 +210,10 @@ class Market(object):
|
||||
"Fiend" : self.les_grp, # AT13 prize
|
||||
"Caedes" : self.les_grp, # AT14 prize
|
||||
"Rabisu" : self.les_grp, # AT14 prize
|
||||
"Victor" : self.les_grp, # AT prize
|
||||
"Virtuoso" : self.les_grp, # AT prize
|
||||
"Victor" : self.les_grp, # AT15 prize
|
||||
"Virtuoso" : self.les_grp, # AT15 prize
|
||||
"Hydra" : self.les_grp, # AT16 prize
|
||||
"Tiamat" : self.les_grp, # AT16 prize
|
||||
}
|
||||
|
||||
self.ITEMS_FORCEGROUP_R = self.__makeRevDict(self.ITEMS_FORCEGROUP)
|
||||
|
||||
@@ -22,7 +22,7 @@ import re
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
from eos.db.gamedata.queries import getAttributeInfo, getDynamicItem
|
||||
from eos.db.gamedata.queries import getDynamicItem
|
||||
from eos.saveddata.cargo import Cargo
|
||||
from eos.saveddata.citadel import Citadel
|
||||
from eos.saveddata.booster import Booster
|
||||
@@ -32,10 +32,10 @@ from eos.saveddata.implant import Implant
|
||||
from eos.saveddata.module import Module, State, Slot
|
||||
from eos.saveddata.ship import Ship
|
||||
from eos.saveddata.fit import Fit
|
||||
from gui.utils.numberFormatter import roundToPrec
|
||||
from service.fit import Fit as svcFit
|
||||
from service.market import Market
|
||||
from service.port.shared import IPortUser, processing_notify
|
||||
from service.port.muta import parseMutant, renderMutant
|
||||
from service.port.shared import IPortUser, fetchItem, processing_notify
|
||||
from enum import Enum
|
||||
|
||||
|
||||
@@ -157,17 +157,7 @@ def exportEft(fit, options):
|
||||
if mutants and options & Options.MUTATIONS.value:
|
||||
for mutantReference in sorted(mutants):
|
||||
mutant = mutants[mutantReference]
|
||||
mutatedAttrs = {}
|
||||
for attrID, mutator in mutant.mutators.items():
|
||||
attrName = getAttributeInfo(attrID).name
|
||||
mutatedAttrs[attrName] = mutator.value
|
||||
mutationLines.append('[{}] {}'.format(mutantReference, mutant.baseItem.name))
|
||||
mutationLines.append(' {}'.format(mutant.mutaplasmid.item.name))
|
||||
# Round to 7th significant number to avoid exporting float errors
|
||||
customAttrsLine = ', '.join(
|
||||
'{} {}'.format(a, roundToPrec(mutatedAttrs[a], 7))
|
||||
for a in sorted(mutatedAttrs))
|
||||
mutationLines.append(' {}'.format(customAttrsLine))
|
||||
mutationLines.append(renderMutant(mutant, firstPrefix='[{}] '.format(mutantReference), prefix=' '))
|
||||
if mutationLines:
|
||||
sections.append('\n'.join(mutationLines))
|
||||
|
||||
@@ -507,59 +497,48 @@ def _importPrepareString(eftString):
|
||||
return lines
|
||||
|
||||
|
||||
mutantHeaderPattern = re.compile('^\[(?P<ref>\d+)\](?P<tail>.*)')
|
||||
|
||||
|
||||
def _importGetMutationData(lines):
|
||||
data = {}
|
||||
# Format: {ref: [lines]}
|
||||
mutaLinesMap = {}
|
||||
currentMutaRef = None
|
||||
currentMutaLines = []
|
||||
consumedIndices = set()
|
||||
for i in range(len(lines)):
|
||||
line = lines[i]
|
||||
m = re.match('^\[(?P<ref>\d+)\]', line)
|
||||
|
||||
def completeMutaLines():
|
||||
if currentMutaRef is not None and currentMutaLines:
|
||||
mutaLinesMap[currentMutaRef] = currentMutaLines
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
m = mutantHeaderPattern.match(line)
|
||||
# Start and reset at header 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
|
||||
completeMutaLines()
|
||||
currentMutaRef = int(m.group('ref'))
|
||||
currentMutaLines = []
|
||||
currentMutaLines.append(m.group('tail'))
|
||||
consumedIndices.add(i)
|
||||
# Reset at blank line
|
||||
elif not line:
|
||||
completeMutaLines()
|
||||
currentMutaRef = None
|
||||
currentMutaLines = []
|
||||
elif currentMutaRef is not None:
|
||||
currentMutaLines.append(line)
|
||||
consumedIndices.add(i)
|
||||
else:
|
||||
completeMutaLines()
|
||||
# Clear mutant info from source
|
||||
for i in sorted(consumedIndices, reverse=True):
|
||||
del lines[i]
|
||||
# Run parsing
|
||||
data = {}
|
||||
for ref, mutaLines in mutaLinesMap.items():
|
||||
_, mutaType, mutaAttrs = parseMutant(mutaLines)
|
||||
data[ref] = (mutaType, mutaAttrs)
|
||||
return data
|
||||
|
||||
|
||||
@@ -587,7 +566,7 @@ def _importCreateFit(lines):
|
||||
shipType = m.group('shipType').strip()
|
||||
fitName = m.group('fitName').strip()
|
||||
try:
|
||||
ship = _fetchItem(shipType)
|
||||
ship = fetchItem(shipType)
|
||||
try:
|
||||
fit.ship = Ship(ship)
|
||||
except ValueError:
|
||||
@@ -599,20 +578,6 @@ def _importCreateFit(lines):
|
||||
return fit
|
||||
|
||||
|
||||
def _fetchItem(typeName, eagerCat=False):
|
||||
sMkt = Market.getInstance()
|
||||
eager = 'group.category' if eagerCat else None
|
||||
try:
|
||||
item = sMkt.getItem(typeName, eager=eager)
|
||||
except:
|
||||
pyfalog.warning('service.port.eft: unable to fetch item "{}"'.format(typeName))
|
||||
return None
|
||||
if sMkt.getPublicityByItem(item):
|
||||
return item
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def _clearTail(lst):
|
||||
while lst and lst[-1] is None:
|
||||
del lst[-1]
|
||||
@@ -667,7 +632,7 @@ class Section:
|
||||
class BaseItemSpec:
|
||||
|
||||
def __init__(self, typeName):
|
||||
item = _fetchItem(typeName, eagerCat=True)
|
||||
item = fetchItem(typeName, eagerCat=True)
|
||||
if item is None:
|
||||
raise EftImportError
|
||||
self.typeName = typeName
|
||||
@@ -704,7 +669,7 @@ class RegularItemSpec(BaseItemSpec):
|
||||
|
||||
def __fetchCharge(self, chargeName):
|
||||
if chargeName:
|
||||
charge = _fetchItem(chargeName, eagerCat=True)
|
||||
charge = fetchItem(chargeName, eagerCat=True)
|
||||
if not charge or charge.category.name != 'Charge':
|
||||
charge = None
|
||||
else:
|
||||
|
||||
79
service/port/muta.py
Normal file
79
service/port/muta.py
Normal file
@@ -0,0 +1,79 @@
|
||||
# =============================================================================
|
||||
# Copyright (C) 2014 Ryan Holmes
|
||||
#
|
||||
# This file is part of pyfa.
|
||||
#
|
||||
# pyfa is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# pyfa is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with pyfa. If not, see <http://www.gnu.org/licenses/>.
|
||||
# =============================================================================
|
||||
|
||||
|
||||
from eos.db.gamedata.queries import getAttributeInfo
|
||||
from gui.utils.numberFormatter import roundToPrec
|
||||
from service.port.shared import fetchItem
|
||||
|
||||
|
||||
def renderMutant(mutant, firstPrefix='', prefix=''):
|
||||
exportLines = []
|
||||
mutatedAttrs = {}
|
||||
for attrID, mutator in mutant.mutators.items():
|
||||
attrName = getAttributeInfo(attrID).name
|
||||
mutatedAttrs[attrName] = mutator.value
|
||||
exportLines.append('{}{}'.format(firstPrefix, mutant.baseItem.name))
|
||||
exportLines.append('{}{}'.format(prefix, mutant.mutaplasmid.item.name))
|
||||
# Round to 7th significant number to avoid exporting float errors
|
||||
customAttrsLine = ', '.join(
|
||||
'{} {}'.format(a, roundToPrec(mutatedAttrs[a], 7))
|
||||
for a in sorted(mutatedAttrs))
|
||||
exportLines.append('{}{}'.format(prefix, customAttrsLine))
|
||||
return '\n'.join(exportLines)
|
||||
|
||||
|
||||
def parseMutant(lines):
|
||||
# Fetch base item type
|
||||
try:
|
||||
baseName = lines[0]
|
||||
except IndexError:
|
||||
return None
|
||||
baseType = fetchItem(baseName.strip())
|
||||
if baseType is None:
|
||||
return None, None, {}
|
||||
# Fetch mutaplasmid item type and actual item
|
||||
try:
|
||||
mutaName = lines[1]
|
||||
except IndexError:
|
||||
return baseType, None, {}
|
||||
mutaType = fetchItem(mutaName.strip())
|
||||
if mutaType is None:
|
||||
return baseType, None, {}
|
||||
# Process mutated attribute values
|
||||
try:
|
||||
mutaAttrsLine = lines[2]
|
||||
except IndexError:
|
||||
return baseType, mutaType, {}
|
||||
mutaAttrs = {}
|
||||
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
|
||||
return baseType, mutaType, mutaAttrs
|
||||
@@ -37,6 +37,7 @@ from service.port.esi import exportESI, importESI
|
||||
from service.port.multibuy import exportMultiBuy
|
||||
from service.port.shared import IPortUser, UserCancelException, processing_notify
|
||||
from service.port.xml import importXml, exportXml
|
||||
from service.port.muta import parseMutant
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
@@ -188,18 +189,20 @@ class Port(object):
|
||||
# TODO: catch the exception?
|
||||
# activeFit is reserved?, bufferStr is unicode? (assume only clipboard string?
|
||||
sFit = svcFit.getInstance()
|
||||
_, fits = Port.importAuto(bufferStr, activeFit=activeFit)
|
||||
for fit in fits:
|
||||
fit.character = sFit.character
|
||||
fit.damagePattern = sFit.pattern
|
||||
fit.targetResists = sFit.targetResists
|
||||
if len(fit.implants) > 0:
|
||||
fit.implantLocation = ImplantLocation.FIT
|
||||
else:
|
||||
useCharImplants = sFit.serviceFittingOptions["useCharacterImplantsByDefault"]
|
||||
fit.implantLocation = ImplantLocation.CHARACTER if useCharImplants else ImplantLocation.FIT
|
||||
db.save(fit)
|
||||
return fits
|
||||
importType, importData = Port.importAuto(bufferStr, activeFit=activeFit)
|
||||
|
||||
if importType != "MutatedItem":
|
||||
for fit in importData:
|
||||
fit.character = sFit.character
|
||||
fit.damagePattern = sFit.pattern
|
||||
fit.targetResists = sFit.targetResists
|
||||
if len(fit.implants) > 0:
|
||||
fit.implantLocation = ImplantLocation.FIT
|
||||
else:
|
||||
useCharImplants = sFit.serviceFittingOptions["useCharacterImplantsByDefault"]
|
||||
fit.implantLocation = ImplantLocation.CHARACTER if useCharImplants else ImplantLocation.FIT
|
||||
db.save(fit)
|
||||
return importType, importData
|
||||
|
||||
@classmethod
|
||||
def importAuto(cls, string, path=None, activeFit=None, iportuser=None):
|
||||
@@ -228,8 +231,16 @@ class Port(object):
|
||||
if re.match("\[.*,.*\]", firstLine):
|
||||
return "EFT", (cls.importEft(string),)
|
||||
|
||||
# Use DNA format for all other cases
|
||||
return "DNA", (cls.importDna(string),)
|
||||
# Check if string is in DNA format
|
||||
if re.match("\d+(:\d+(;\d+))*::", firstLine):
|
||||
return "DNA", (cls.importDna(string),)
|
||||
|
||||
# Assume that we import stand-alone abyssal module if all else fails
|
||||
try:
|
||||
return "MutatedItem", (parseMutant(string.split("\n")),)
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
# EFT-related methods
|
||||
@staticmethod
|
||||
|
||||
@@ -20,6 +20,13 @@
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
from logbook import Logger
|
||||
|
||||
from service.market import Market
|
||||
|
||||
|
||||
pyfalog = Logger(__name__)
|
||||
|
||||
|
||||
class UserCancelException(Exception):
|
||||
"""when user cancel on port processing."""
|
||||
@@ -68,3 +75,17 @@ class IPortUser(metaclass=ABCMeta):
|
||||
def processing_notify(iportuser, flag, data):
|
||||
if not iportuser.on_port_processing(flag, data):
|
||||
raise UserCancelException
|
||||
|
||||
|
||||
def fetchItem(typeName, eagerCat=False):
|
||||
sMkt = Market.getInstance()
|
||||
eager = 'group.category' if eagerCat else None
|
||||
try:
|
||||
item = sMkt.getItem(typeName, eager=eager)
|
||||
except:
|
||||
pyfalog.warning('service.port.shared: unable to fetch item "{}"'.format(typeName))
|
||||
return None
|
||||
if sMkt.getPublicityByItem(item):
|
||||
return item
|
||||
else:
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user