diff --git a/gui/builtinStatsViews/priceViewFull.py b/gui/builtinStatsViews/priceViewFull.py index ebb6acac8..0e17ed85c 100644 --- a/gui/builtinStatsViews/priceViewFull.py +++ b/gui/builtinStatsViews/priceViewFull.py @@ -22,7 +22,7 @@ import wx from gui.statsView import StatsView from gui.bitmap_loader import BitmapLoader from gui.utils.numberFormatter import formatAmount -from service.price import Price +from service.price import Fit, Price from service.settings import PriceMenuSettings @@ -79,11 +79,8 @@ class PriceViewFull(StatsView): def refreshPanel(self, fit): if fit is not None: self.fit = fit - - fit_items = Price.fitItemsList(fit) - - sPrice = Price.getInstance() - sPrice.getPrices(fit_items, self.processPrices, fetchTimeout=30) + fit_items = set(Fit.fitItemIter(fit)) + Price.getInstance().getPrices(fit_items, self.processPrices, fetchTimeout=30) self.labelEMStatus.SetLabel("Updating prices...") self.refreshPanelPrices(fit) diff --git a/gui/builtinStatsViews/priceViewMinimal.py b/gui/builtinStatsViews/priceViewMinimal.py index 41c837c04..4506f2686 100644 --- a/gui/builtinStatsViews/priceViewMinimal.py +++ b/gui/builtinStatsViews/priceViewMinimal.py @@ -22,7 +22,7 @@ import wx from gui.statsView import StatsView from gui.bitmap_loader import BitmapLoader from gui.utils.numberFormatter import formatAmount -from service.price import Price +from service.price import Fit, Price from service.settings import PriceMenuSettings @@ -73,11 +73,8 @@ class PriceViewMinimal(StatsView): def refreshPanel(self, fit): if fit is not None: self.fit = fit - - fit_items = Price.fitItemsList(fit) - - sPrice = Price.getInstance() - sPrice.getPrices(fit_items, self.processPrices, fetchTimeout=30) + fit_items = set(Fit.fitItemIter(fit)) + Price.getInstance().getPrices(fit_items, self.processPrices, fetchTimeout=30) self.labelEMStatus.SetLabel("Updating prices...") self.refreshPanelPrices(fit) diff --git a/gui/fitCommands/__init__.py b/gui/fitCommands/__init__.py index 42b718c5d..f1e3a4de8 100644 --- a/gui/fitCommands/__init__.py +++ b/gui/fitCommands/__init__.py @@ -35,3 +35,4 @@ from .guiToggleDrone import GuiToggleDroneCommand from .guiFitRename import GuiFitRenameCommand from .guiChangeImplantLocation import GuiChangeImplantLocation from .guiImportMutatedModule import GuiImportMutatedModuleCommand +from .guiRebaseItems import GuiRebaseItemsCommand diff --git a/gui/fitCommands/calc/fitRebaseItem.py b/gui/fitCommands/calc/fitRebaseItem.py new file mode 100644 index 000000000..1fb44b266 --- /dev/null +++ b/gui/fitCommands/calc/fitRebaseItem.py @@ -0,0 +1,31 @@ +import wx + +from logbook import Logger + +import eos.db + + +pyfalog = Logger(__name__) + + +class FitRebaseItemCommand(wx.Command): + + def __init__(self, fitID, containerName, position, newTypeID): + wx.Command.__init__(self, True, "Rebase Item") + self.fitID = fitID + self.containerName = containerName + self.position = position + self.newTypeID = newTypeID + self.oldTypeID = None + + def Do(self): + fit = eos.db.getFit(self.fitID) + obj = getattr(fit, self.containerName)[self.position] + self.oldTypeID = getattr(obj.item, "ID", None) + newItem = eos.db.getItem(self.newTypeID) + obj.rebase(newItem) + return True + + def Undo(self): + cmd = FitRebaseItemCommand(self.fitID, self.containerName, self.position, self.oldTypeID) + return cmd.Do() diff --git a/gui/fitCommands/guiOptimizePrice.py b/gui/fitCommands/guiOptimizePrice.py deleted file mode 100644 index e41edab81..000000000 --- a/gui/fitCommands/guiOptimizePrice.py +++ /dev/null @@ -1,12 +0,0 @@ -import wx - - -class GuiOptimizePriceCommand(wx.Command): - def __init__(self): - wx.Command.__init__(self, True, "Optimize Price") - - def Do(self): - pass - - def Undo(self): - pass diff --git a/gui/fitCommands/guiRebaseItems.py b/gui/fitCommands/guiRebaseItems.py new file mode 100644 index 000000000..8a69a78f5 --- /dev/null +++ b/gui/fitCommands/guiRebaseItems.py @@ -0,0 +1,46 @@ +import wx + +import eos.db +import gui.mainFrame +from gui import globalEvents as GE +from service.fit import Fit +from .calc.fitRebaseItem import FitRebaseItemCommand +from .calc.fitSetCharge import FitSetChargeCommand + + +class GuiRebaseItemsCommand(wx.Command): + + def __init__(self, fitID, rebaseMap): + wx.Command.__init__(self, True, "Mass Rebase Item") + self.mainFrame = gui.mainFrame.MainFrame.getInstance() + self.fitID = fitID + self.rebaseMap = rebaseMap + self.internal_history = wx.CommandProcessor() + + def Do(self): + fit = eos.db.getFit(self.fitID) + for mod in fit.modules: + if mod.item is not None and mod.item.ID in self.rebaseMap: + self.internal_history.Submit(FitRebaseItemCommand(self.fitID, "modules", mod.modPosition, self.rebaseMap[mod.item.ID])) + if mod.charge is not None and mod.charge.ID in self.rebaseMap: + self.internal_history.Submit(FitSetChargeCommand(self.fitID, [mod.modPosition], self.rebaseMap[mod.charge.ID])) + for containerName in ("drones", "fighters", "implants", "boosters", "cargo"): + container = getattr(fit, containerName) + for obj in container: + if obj.item is not None and obj.item.ID in self.rebaseMap: + self.internal_history.Submit(FitRebaseItemCommand(self.fitID, containerName, container.index(obj), self.rebaseMap[obj.item.ID])) + if self.internal_history.Commands: + eos.db.commit() + Fit.getInstance().recalc(self.fitID) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) + return True + else: + return False + + def Undo(self): + for _ in self.internal_history.Commands: + self.internal_history.Undo() + eos.db.commit() + Fit.getInstance().recalc(self.fitID) + wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.fitID)) + return True diff --git a/gui/mainFrame.py b/gui/mainFrame.py index 45dd20e35..61fe7ceac 100644 --- a/gui/mainFrame.py +++ b/gui/mainFrame.py @@ -659,16 +659,19 @@ class MainFrame(wx.Frame): wx.PostEvent(self, GE.CharListUpdated()) def optimizeFitPrice(self, event): - sPrice = Price.getInstance() fitID = self.getActiveFit() - fit = Fit.getInstance().getFit(fitID) + sFit = Fit.getInstance() + fit = sFit.getFit(fitID) if fit: - # TODO: block/unblock UI while pyfa is working - def cb(changes): - if changes: - wx.PostEvent(self, GE.FitChanged(fitID=fitID)) - sPrice.optimizeFitPrice(fit, cb, fetchTimeout=10) + def updateFitCb(replacementsCheaper): + rebaseMap = {k.ID: v.ID for k, v in replacementsCheaper.items()} + self.command.Submit(cmd.GuiRebaseItemsCommand(fitID, rebaseMap)) + + # TODO: block/unblock UI while pyfa is working + fitItems = {i for i in Fit.fitItemIter(fit) if i is not fit.ship.item} + Price.getInstance().findCheaperReplacements(fitItems, updateFitCb, fetchTimeout=10) + def AdditionsTabSelect(self, event): selTab = self.additionsSelect.index(event.GetId()) diff --git a/service/fit.py b/service/fit.py index 035bb50ee..d3bc0a0c1 100644 --- a/service/fit.py +++ b/service/fit.py @@ -549,9 +549,26 @@ class Fit(FitDeprecated): changed = True return changed - # If any state was changed, recalculate attributes again - # if changed: - # self.recalc(fit) + + @classmethod + def fitObjectIter(cls, fit): + yield fit.ship + + for mod in fit.modules: + if not mod.isEmpty: + yield mod + + for container in (fit.drones, fit.fighters, fit.implants, fit.boosters, fit.cargo): + for obj in container: + yield obj + + @classmethod + def fitItemIter(cls, fit): + for fitobj in cls.fitObjectIter(fit): + yield fitobj.item + charge = getattr(fitobj, 'charge', None) + if charge: + yield charge def refreshFit(self, fitID): pyfalog.debug("Refresh fit for fit ID: {0}", fitID) diff --git a/service/price.py b/service/price.py index 0f0f11ce6..5cfdf09c8 100644 --- a/service/price.py +++ b/service/price.py @@ -28,6 +28,7 @@ from logbook import Logger from eos import db from eos.saveddata.price import PriceStatus +from gui.fitCommands.guiRebaseItems import GuiRebaseItemsCommand from service.fit import Fit from service.market import Market from service.network import TimeoutError @@ -144,30 +145,6 @@ class Price: for typeID in priceMap.keys(): priceMap[typeID].update(PriceStatus.fetchFail) - @classmethod - def fitItemsList(cls, fit): - return list(set(cls.fitItemIter(fit))) - - @classmethod - def fitObjectIter(cls, fit): - yield fit.ship - - for mod in fit.modules: - if not mod.isEmpty: - yield mod - - for container in (fit.drones, fit.fighters, fit.implants, fit.boosters, fit.cargo): - for obj in container: - yield obj - - @classmethod - def fitItemIter(cls, fit): - for fitobj in cls.fitObjectIter(fit): - yield fitobj.item - charge = getattr(fitobj, 'charge', None) - if charge: - yield charge - def getPriceNow(self, objitem): """Get price for provided typeID""" sMkt = Market.getInstance() @@ -230,32 +207,7 @@ class Price: validityOverride = 2 * 60 * 60 self.getPrices(itemsToFetch, makeCheapMapCb, fetchTimeout=fetchTimeout, validityOverride=validityOverride) - def optimizeFitPrice(self, fit, callback, fetchTimeout=10): - def updateFitCb(replacementsCheaper): - changes = False - for mod in fit.modules: - if mod.item in replacementsCheaper: - mod.rebase(replacementsCheaper[mod.item]) - changes = True - if mod.charge in replacementsCheaper: - mod.charge = replacementsCheaper[mod.charge] - changes = True - for container in (fit.drones, fit.fighters, fit.implants, fit.boosters, fit.cargo): - for obj in container: - if obj.item in replacementsCheaper: - obj.rebase(replacementsCheaper[obj.item]) - changes = True - if changes: - Fit.getInstance().refreshFit(fit.ID) - try: - callback(changes) - except Exception as e: - pyfalog.critical("Execution of callback from optimizeFitPrice failed.") - pyfalog.critical(e) - - fitItems = {i for i in self.fitItemIter(fit) if i is not fit.ship.item} - self.findCheaperReplacements(fitItems, updateFitCb, fetchTimeout=fetchTimeout) class PriceWorkerThread(threading.Thread):