From b9e68504ed8e52ae961712cdfba4d84cfb2d5e90 Mon Sep 17 00:00:00 2001 From: DarkPhoenix Date: Mon, 25 Feb 2019 08:35:35 +0300 Subject: [PATCH] Add support for multibuy price optimization option --- gui/mainFrame.py | 54 +++++++++++++++++++++++----------------- service/port/dna.py | 9 +++++-- service/port/efs.py | 8 ++++-- service/port/eft.py | 9 +++++-- service/port/esi.py | 9 +++++-- service/port/multibuy.py | 51 +++++++++++++++++++++++-------------- service/port/port.py | 20 +++++++-------- service/port/xml.py | 10 +++++--- 8 files changed, 107 insertions(+), 63 deletions(-) diff --git a/gui/mainFrame.py b/gui/mainFrame.py index d5bc8f0e9..c56986944 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -699,29 +699,29 @@ class MainFrame(wx.Frame): else: self.marketBrowser.search.Focus() - def clipboardEft(self, options): + def exportEft(self, options, callback): fit = db_getFit(self.getActiveFit()) - toClipboard(Port.exportEft(fit, options)) + Port.exportEft(fit, options, callback) - def clipboardDna(self, options): + def exportDna(self, options, callback): fit = db_getFit(self.getActiveFit()) - toClipboard(Port.exportDna(fit)) + Port.exportDna(fit, callback) - def clipboardEsi(self, options): + def exportEsi(self, options, callback): fit = db_getFit(self.getActiveFit()) - toClipboard(Port.exportESI(fit)) + Port.exportESI(fit, callback) - def clipboardXml(self, options): + def exportXml(self, options, callback): fit = db_getFit(self.getActiveFit()) - toClipboard(Port.exportXml(None, fit)) + Port.exportXml(None, fit, callback) - def clipboardMultiBuy(self, options): + def exportMultiBuy(self, options, callback): fit = db_getFit(self.getActiveFit()) - toClipboard(Port.exportMultiBuy(fit, options)) + Port.exportMultiBuy(fit, options, callback) - def clipboardEfs(self, options): + def exportEfs(self, options, callback): fit = db_getFit(self.getActiveFit()) - toClipboard(EfsPort.exportEfs(fit, 0)) + EfsPort.exportEfs(fit, 0, callback) def importFromClipboard(self, event): clipboard = fromClipboard() @@ -739,15 +739,21 @@ class MainFrame(wx.Frame): self._openAfterImport(importData) def exportToClipboard(self, event): - CopySelectDict = {CopySelectDialog.copyFormatEft: self.clipboardEft, - CopySelectDialog.copyFormatXml: self.clipboardXml, - CopySelectDialog.copyFormatDna: self.clipboardDna, - CopySelectDialog.copyFormatEsi: self.clipboardEsi, - CopySelectDialog.copyFormatMultiBuy: self.clipboardMultiBuy, - CopySelectDialog.copyFormatEfs: self.clipboardEfs} + CopySelectDict = {CopySelectDialog.copyFormatEft: self.exportEft, + CopySelectDialog.copyFormatXml: self.exportXml, + CopySelectDialog.copyFormatDna: self.exportDna, + CopySelectDialog.copyFormatEsi: self.exportEsi, + CopySelectDialog.copyFormatMultiBuy: self.exportMultiBuy, + CopySelectDialog.copyFormatEfs: self.exportEfs} dlg = CopySelectDialog(self) btnPressed = dlg.ShowModal() + def killDialog(): + try: + dlg.Destroy() + except RuntimeError: + pyfalog.error("Tried to destroy an object that doesn't exist in .") + if btnPressed == wx.ID_OK: selected = dlg.GetSelected() options = dlg.GetOptions() @@ -755,12 +761,14 @@ class MainFrame(wx.Frame): settings = SettingsProvider.getInstance().getSettings("pyfaExport") settings["format"] = selected settings["options"] = options - CopySelectDict[selected](options.get(selected)) - try: - dlg.Destroy() - except RuntimeError: - pyfalog.error("Tried to destroy an object that doesn't exist in .") + def cb(text): + toClipboard(text) + killDialog() + + CopySelectDict[selected](options.get(selected), callback=cb) + else: + killDialog() def exportSkillsNeeded(self, event): """ Exports skills needed for active fit and active character """ diff --git a/service/port/dna.py b/service/port/dna.py index bc64e9e99..7e310f936 100644 --- a/service/port/dna.py +++ b/service/port/dna.py @@ -123,7 +123,7 @@ def importDna(string): return f -def exportDna(fit): +def exportDna(fit, callback): dna = str(fit.shipID) subsystems = [] # EVE cares which order you put these in mods = OrderedDict() @@ -173,4 +173,9 @@ def exportDna(fit): for charge in charges: dna += ":{0};{1}".format(charge, charges[charge]) - return dna + "::" + text = dna + "::" + + if callback: + callback(text) + else: + return text diff --git a/service/port/efs.py b/service/port/efs.py index c93c7d87d..94e6471f3 100755 --- a/service/port/efs.py +++ b/service/port/efs.py @@ -583,7 +583,7 @@ class EfsPort: return sizeNotFoundMsg @staticmethod - def exportEfs(fit, typeNotFitFlag): + def exportEfs(fit, typeNotFitFlag, callback): sFit = Fit.getInstance() includeShipTypeData = typeNotFitFlag > 0 if includeShipTypeData: @@ -680,4 +680,8 @@ class EfsPort: pyfalog.error(e) dataDict = {"name": fitName + "Fit could not be correctly parsed"} export = json.dumps(dataDict, skipkeys=True) - return export + + if callback: + callback(export) + else: + return export diff --git a/service/port/eft.py b/service/port/eft.py index 8407e3ae7..5dfec9968 100644 --- a/service/port/eft.py +++ b/service/port/eft.py @@ -61,7 +61,7 @@ SLOT_ORDER = (Slot.LOW, Slot.MED, Slot.HIGH, Slot.RIG, Slot.SUBSYSTEM, Slot.SERV OFFLINE_SUFFIX = '/OFFLINE' -def exportEft(fit, options): +def exportEft(fit, options, callback): # EFT formatted export is split in several sections, each section is # separated from another using 2 blank lines. Sections might have several # sub-sections, which are separated by 1 blank line @@ -157,7 +157,12 @@ def exportEft(fit, options): if mutationLines: sections.append('\n'.join(mutationLines)) - return '{}\n\n{}'.format(header, '\n\n\n'.join(sections)) + text = '{}\n\n{}'.format(header, '\n\n\n'.join(sections)) + + if callback: + callback(text) + else: + return text def importEft(lines): diff --git a/service/port/esi.py b/service/port/esi.py index a97480624..9847cbf05 100644 --- a/service/port/esi.py +++ b/service/port/esi.py @@ -54,7 +54,7 @@ INV_FLAG_DRONEBAY = 87 INV_FLAG_FIGHTER = 158 -def exportESI(ofit): +def exportESI(ofit, callback): # A few notes: # max fit name length is 50 characters # Most keys are created simply because they are required, but bogus data is okay @@ -134,7 +134,12 @@ def exportESI(ofit): if len(fit['items']) == 0: raise ESIExportException("Cannot export fitting: module list cannot be empty.") - return json.dumps(fit) + text = json.dumps(fit) + + if callback: + callback(text) + else: + return text def importESI(string): diff --git a/service/port/multibuy.py b/service/port/multibuy.py index 05beaaedc..392b656ed 100644 --- a/service/port/multibuy.py +++ b/service/port/multibuy.py @@ -39,52 +39,65 @@ MULTIBUY_OPTIONS = ( ) -def exportMultiBuy(fit, options): - itemCounts = {} - - def addItem(item, quantity=1): - if item not in itemCounts: - itemCounts[item] = 0 - itemCounts[item] += quantity +def exportMultiBuy(fit, options, callback): + itemAmounts = {} for module in fit.modules: if module.item: # Mutated items are of no use for multibuy if module.isMutated: continue - addItem(module.item) + _addItem(itemAmounts, module.item) if module.charge and options[Options.LOADED_CHARGES.value]: - addItem(module.charge, module.numCharges) + _addItem(itemAmounts, module.charge, module.numCharges) for drone in fit.drones: - addItem(drone.item, drone.amount) + _addItem(itemAmounts, drone.item, drone.amount) for fighter in fit.fighters: - addItem(fighter.item, fighter.amountActive) + _addItem(itemAmounts, fighter.item, fighter.amountActive) if options[Options.CARGO.value]: for cargo in fit.cargo: - addItem(cargo.item, cargo.amount) + _addItem(itemAmounts, cargo.item, cargo.amount) if options[Options.IMPLANTS.value]: for implant in fit.implants: - addItem(implant.item) + _addItem(itemAmounts, implant.item) for booster in fit.boosters: - addItem(booster.item) + _addItem(itemAmounts, booster.item) if options[Options.OPTIMIZE_PRICES.value]: def cb(replacements): - pass + updatedAmounts = {} + for item, itemAmount in itemAmounts.items(): + _addItem(updatedAmounts, replacements.get(item, item), itemAmount) + string = _prepareString(fit.ship.item, updatedAmounts) + callback(string) priceSvc = sPrc.getInstance() - priceSvc.findCheaperReplacements(itemCounts, cb) + priceSvc.findCheaperReplacements(itemAmounts, cb) + else: + string = _prepareString(fit.ship.item, itemAmounts) + if callback: + callback(string) + else: + return string + +def _addItem(container, item, quantity=1): + if item not in container: + container[item] = 0 + container[item] += quantity + + +def _prepareString(shipItem, itemAmounts): exportLines = [] - exportLines.append(fit.ship.item.name) - for item in sorted(itemCounts, key=lambda i: (i.group.category.name, i.group.name, i.name)): - count = itemCounts[item] + exportLines.append(shipItem.name) + for item in sorted(itemAmounts, key=lambda i: (i.group.category.name, i.group.name, i.name)): + count = itemAmounts[item] if count == 1: exportLines.append(item.name) else: diff --git a/service/port/port.py b/service/port/port.py index 8038cab8e..0b2420003 100644 --- a/service/port/port.py +++ b/service/port/port.py @@ -257,8 +257,8 @@ class Port(object): return importEftCfg(shipname, lines, iportuser) @classmethod - def exportEft(cls, fit, options): - return exportEft(fit, options) + def exportEft(cls, fit, options, callback=None): + return exportEft(fit, options, callback=callback) # DNA-related methods @staticmethod @@ -266,8 +266,8 @@ class Port(object): return importDna(string) @staticmethod - def exportDna(fit): - return exportDna(fit) + def exportDna(fit, callback=None): + return exportDna(fit, callback=callback) # ESI-related methods @staticmethod @@ -275,8 +275,8 @@ class Port(object): return importESI(string) @staticmethod - def exportESI(fit): - return exportESI(fit) + def exportESI(fit, callback=None): + return exportESI(fit, callback=callback) # XML-related methods @staticmethod @@ -284,10 +284,10 @@ class Port(object): return importXml(text, iportuser) @staticmethod - def exportXml(iportuser=None, *fits): - return exportXml(iportuser, *fits) + def exportXml(iportuser=None, callback=None, *fits): + return exportXml(iportuser, callback=callback, *fits) # Multibuy-related methods @staticmethod - def exportMultiBuy(fit, options): - return exportMultiBuy(fit, options) + def exportMultiBuy(fit, options, callback=None): + return exportMultiBuy(fit, options, callback=callback) diff --git a/service/port/xml.py b/service/port/xml.py index 432bbcdd8..01da634c2 100644 --- a/service/port/xml.py +++ b/service/port/xml.py @@ -225,14 +225,13 @@ def importXml(text, iportuser): return fit_list -def exportXml(iportuser, *fits): +def exportXml(iportuser, callback, *fits): doc = xml.dom.minidom.Document() fittings = doc.createElement("fittings") # fit count fit_count = len(fits) fittings.setAttribute("count", "%s" % fit_count) doc.appendChild(fittings) - sFit = svcFit.getInstance() for i, fit in enumerate(fits): try: @@ -323,4 +322,9 @@ def exportXml(iportuser, *fits): iportuser, IPortUser.PROCESS_EXPORT | IPortUser.ID_UPDATE, (i, "convert to xml (%s/%s) %s" % (i + 1, fit_count, fit.ship.name)) ) - return doc.toprettyxml() + text = doc.toprettyxml() + + if callback: + callback(text) + else: + return text