From dd0fbfddb94843897247ad2135decf51e18cce31 Mon Sep 17 00:00:00 2001 From: DarkPhoenix Date: Thu, 30 Aug 2018 15:57:59 +0300 Subject: [PATCH] Split ESI stuff into its own file --- gui/esiFittings.py | 2 +- service/port/esi.py | 208 +++++++++++++++++++++++++++++++++++++++++++ service/port/port.py | 180 +++---------------------------------- 3 files changed, 219 insertions(+), 171 deletions(-) create mode 100644 service/port/esi.py diff --git a/gui/esiFittings.py b/gui/esiFittings.py index 5b7dec36d..c471a1334 100644 --- a/gui/esiFittings.py +++ b/gui/esiFittings.py @@ -15,7 +15,7 @@ import gui.globalEvents as GE from logbook import Logger from service.esi import Esi from service.esiAccess import APIException -from service.port.port import ESIExportException +from service.port.esi import ESIExportException pyfalog = Logger(__name__) diff --git a/service/port/esi.py b/service/port/esi.py new file mode 100644 index 000000000..f1e02d13a --- /dev/null +++ b/service/port/esi.py @@ -0,0 +1,208 @@ +# ============================================================================= +# 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 . +# ============================================================================= + + +import collections +import json + +from logbook import Logger + +from eos.saveddata.cargo import Cargo +from eos.saveddata.citadel import Citadel +from eos.saveddata.drone import Drone +from eos.saveddata.fighter import Fighter +from eos.saveddata.fit import Fit +from eos.saveddata.module import Module, State, Slot +from eos.saveddata.ship import Ship +from service.fit import Fit as svcFit +from service.market import Market + + +class ESIExportException(Exception): + pass + + +pyfalog = Logger(__name__) + +INV_FLAGS = { + Slot.LOW: 11, + Slot.MED: 19, + Slot.HIGH: 27, + Slot.RIG: 92, + Slot.SUBSYSTEM: 125, + Slot.SERVICE: 164 +} + +INV_FLAG_CARGOBAY = 5 +INV_FLAG_DRONEBAY = 87 +INV_FLAG_FIGHTER = 158 + + +def exportESI(ofit): + # A few notes: + # max fit name length is 50 characters + # Most keys are created simply because they are required, but bogus data is okay + + nested_dict = lambda: collections.defaultdict(nested_dict) + fit = nested_dict() + sFit = svcFit.getInstance() + + # max length is 50 characters + name = ofit.name[:47] + '...' if len(ofit.name) > 50 else ofit.name + fit['name'] = name + fit['ship_type_id'] = ofit.ship.item.ID + + # 2017/03/29 NOTE: "<" or "<" is Ignored + # fit['description'] = "" % ofit.ID + fit['description'] = ofit.notes[:397] + '...' if len(ofit.notes) > 400 else ofit.notes if ofit.notes is not None else "" + fit['items'] = [] + + slotNum = {} + charges = {} + for module in ofit.modules: + if module.isEmpty: + continue + + item = nested_dict() + slot = module.slot + + if slot == Slot.SUBSYSTEM: + # Order of subsystem matters based on this attr. See GH issue #130 + slot = int(module.getModifiedItemAttr("subSystemSlot")) + item['flag'] = slot + else: + if slot not in slotNum: + slotNum[slot] = INV_FLAGS[slot] + + item['flag'] = slotNum[slot] + slotNum[slot] += 1 + + item['quantity'] = 1 + item['type_id'] = module.item.ID + fit['items'].append(item) + + if module.charge and sFit.serviceFittingOptions["exportCharges"]: + if module.chargeID not in charges: + charges[module.chargeID] = 0 + # `or 1` because some charges (ie scripts) are without qty + charges[module.chargeID] += module.numCharges or 1 + + for cargo in ofit.cargo: + item = nested_dict() + item['flag'] = INV_FLAG_CARGOBAY + item['quantity'] = cargo.amount + item['type_id'] = cargo.item.ID + fit['items'].append(item) + + for chargeID, amount in list(charges.items()): + item = nested_dict() + item['flag'] = INV_FLAG_CARGOBAY + item['quantity'] = amount + item['type_id'] = chargeID + fit['items'].append(item) + + for drone in ofit.drones: + item = nested_dict() + item['flag'] = INV_FLAG_DRONEBAY + item['quantity'] = drone.amount + item['type_id'] = drone.item.ID + fit['items'].append(item) + + for fighter in ofit.fighters: + item = nested_dict() + item['flag'] = INV_FLAG_FIGHTER + item['quantity'] = fighter.amountActive + item['type_id'] = fighter.item.ID + fit['items'].append(item) + + if len(fit['items']) == 0: + raise ESIExportException("Cannot export fitting: module list cannot be empty.") + + return json.dumps(fit) + + +def importESI(str_): + + sMkt = Market.getInstance() + fitobj = Fit() + refobj = json.loads(str_) + items = refobj['items'] + # "<" and ">" is replace to "<", ">" by EVE client + fitobj.name = refobj['name'] + # 2017/03/29: read description + fitobj.notes = refobj['description'] + + try: + ship = refobj['ship_type_id'] + try: + fitobj.ship = Ship(sMkt.getItem(ship)) + except ValueError: + fitobj.ship = Citadel(sMkt.getItem(ship)) + except: + pyfalog.warning("Caught exception in importESI") + return None + + items.sort(key=lambda k: k['flag']) + + moduleList = [] + for module in items: + try: + item = sMkt.getItem(module['type_id'], eager="group.category") + if not item.published: + continue + if module['flag'] == INV_FLAG_DRONEBAY: + d = Drone(item) + d.amount = module['quantity'] + fitobj.drones.append(d) + elif module['flag'] == INV_FLAG_CARGOBAY: + c = Cargo(item) + c.amount = module['quantity'] + fitobj.cargo.append(c) + elif module['flag'] == INV_FLAG_FIGHTER: + fighter = Fighter(item) + fitobj.fighters.append(fighter) + else: + try: + m = Module(item) + # When item can't be added to any slot (unknown item or just charge), ignore it + except ValueError: + pyfalog.debug("Item can't be added to any slot (unknown item or just charge)") + continue + # Add subsystems before modules to make sure T3 cruisers have subsystems installed + if item.category.name == "Subsystem": + if m.fits(fitobj): + fitobj.modules.append(m) + else: + if m.isValidState(State.ACTIVE): + m.state = State.ACTIVE + + moduleList.append(m) + + except: + pyfalog.warning("Could not process module.") + continue + + # Recalc to get slot numbers correct for T3 cruisers + svcFit.getInstance().recalc(fitobj) + + for module in moduleList: + if module.fits(fitobj): + fitobj.modules.append(module) + + return fitobj diff --git a/service/port/port.py b/service/port/port.py index 29b5eba81..97acaba98 100644 --- a/service/port/port.py +++ b/service/port/port.py @@ -47,30 +47,15 @@ from eos.saveddata.fit import Fit, ImplantLocation from service.market import Market from utils.strfunctions import sequential_rep, replace_ltgt -from service.esi import Esi from service.port.dna import exportDna, importDna from service.port.eft import EftPort, SLOT_ORDER as EFT_SLOT_ORDER +from service.port.esi import importESI, exportESI from service.port.shared import IPortUser, UserCancelException, processing_notify -class ESIExportException(Exception): - pass - pyfalog = Logger(__name__) -INV_FLAGS = { - Slot.LOW: 11, - Slot.MED: 19, - Slot.HIGH: 27, - Slot.RIG: 92, - Slot.SUBSYSTEM: 125, - Slot.SERVICE: 164 -} - -INV_FLAG_CARGOBAY = 5 -INV_FLAG_DRONEBAY = 87 -INV_FLAG_FIGHTER = 158 # 2017/04/05 NOTE: simple validation, for xml file RE_XML_START = r'<\?xml\s+version="1.0"\s*\?>' @@ -320,89 +305,6 @@ class Port(object): db.save(fit) return fits - @classmethod - def exportESI(cls, ofit, callback=None): - # A few notes: - # max fit name length is 50 characters - # Most keys are created simply because they are required, but bogus data is okay - - nested_dict = lambda: collections.defaultdict(nested_dict) - fit = nested_dict() - sFit = svcFit.getInstance() - - # max length is 50 characters - name = ofit.name[:47] + '...' if len(ofit.name) > 50 else ofit.name - fit['name'] = name - fit['ship_type_id'] = ofit.ship.item.ID - - # 2017/03/29 NOTE: "<" or "<" is Ignored - # fit['description'] = "" % ofit.ID - fit['description'] = ofit.notes[:397] + '...' if len(ofit.notes) > 400 else ofit.notes if ofit.notes is not None else "" - fit['items'] = [] - - slotNum = {} - charges = {} - for module in ofit.modules: - if module.isEmpty: - continue - - item = nested_dict() - slot = module.slot - - if slot == Slot.SUBSYSTEM: - # Order of subsystem matters based on this attr. See GH issue #130 - slot = int(module.getModifiedItemAttr("subSystemSlot")) - item['flag'] = slot - else: - if slot not in slotNum: - slotNum[slot] = INV_FLAGS[slot] - - item['flag'] = slotNum[slot] - slotNum[slot] += 1 - - item['quantity'] = 1 - item['type_id'] = module.item.ID - fit['items'].append(item) - - if module.charge and sFit.serviceFittingOptions["exportCharges"]: - if module.chargeID not in charges: - charges[module.chargeID] = 0 - # `or 1` because some charges (ie scripts) are without qty - charges[module.chargeID] += module.numCharges or 1 - - for cargo in ofit.cargo: - item = nested_dict() - item['flag'] = INV_FLAG_CARGOBAY - item['quantity'] = cargo.amount - item['type_id'] = cargo.item.ID - fit['items'].append(item) - - for chargeID, amount in list(charges.items()): - item = nested_dict() - item['flag'] = INV_FLAG_CARGOBAY - item['quantity'] = amount - item['type_id'] = chargeID - fit['items'].append(item) - - for drone in ofit.drones: - item = nested_dict() - item['flag'] = INV_FLAG_DRONEBAY - item['quantity'] = drone.amount - item['type_id'] = drone.item.ID - fit['items'].append(item) - - for fighter in ofit.fighters: - item = nested_dict() - item['flag'] = INV_FLAG_FIGHTER - item['quantity'] = fighter.amountActive - item['type_id'] = fighter.item.ID - fit['items'].append(item) - - if len(fit['items']) == 0: - raise ESIExportException("Cannot export fitting: module list cannot be empty.") - - return json.dumps(fit) - @classmethod def importAuto(cls, string, path=None, activeFit=None, iportuser=None): # type: (basestring, basestring, object, IPortUser, basestring) -> object @@ -433,77 +335,6 @@ class Port(object): # Use DNA format for all other cases return "DNA", (cls.importDna(string),) - @staticmethod - def importESI(str_): - - sMkt = Market.getInstance() - fitobj = Fit() - refobj = json.loads(str_) - items = refobj['items'] - # "<" and ">" is replace to "<", ">" by EVE client - fitobj.name = refobj['name'] - # 2017/03/29: read description - fitobj.notes = refobj['description'] - - try: - ship = refobj['ship_type_id'] - try: - fitobj.ship = Ship(sMkt.getItem(ship)) - except ValueError: - fitobj.ship = Citadel(sMkt.getItem(ship)) - except: - pyfalog.warning("Caught exception in importESI") - return None - - items.sort(key=lambda k: k['flag']) - - moduleList = [] - for module in items: - try: - item = sMkt.getItem(module['type_id'], eager="group.category") - if not item.published: - continue - if module['flag'] == INV_FLAG_DRONEBAY: - d = Drone(item) - d.amount = module['quantity'] - fitobj.drones.append(d) - elif module['flag'] == INV_FLAG_CARGOBAY: - c = Cargo(item) - c.amount = module['quantity'] - fitobj.cargo.append(c) - elif module['flag'] == INV_FLAG_FIGHTER: - fighter = Fighter(item) - fitobj.fighters.append(fighter) - else: - try: - m = Module(item) - # When item can't be added to any slot (unknown item or just charge), ignore it - except ValueError: - pyfalog.debug("Item can't be added to any slot (unknown item or just charge)") - continue - # Add subsystems before modules to make sure T3 cruisers have subsystems installed - if item.category.name == "Subsystem": - if m.fits(fitobj): - fitobj.modules.append(m) - else: - if m.isValidState(State.ACTIVE): - m.state = State.ACTIVE - - moduleList.append(m) - - except: - pyfalog.warning("Could not process module.") - continue - - # Recalc to get slot numbers correct for T3 cruisers - svcFit.getInstance().recalc(fitobj) - - for module in moduleList: - if module.fits(fitobj): - fitobj.modules.append(module) - - return fitobj - @staticmethod def importXml(text, iportuser=None): # type: (str, IPortUser) -> list[eos.saveddata.fit.Fit] @@ -771,3 +602,12 @@ class Port(object): @staticmethod def exportDna(fit): return exportDna(fit) + + # ESI-related methods + @staticmethod + def importESI(string): + importESI(string) + + @staticmethod + def exportESI(fit): + exportESI(fit)