Example #1
0
 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
Example #2
0
 def click(self, event):
     mainRow, _ = self.HitTest(event.Position)
     if mainRow != -1:
         col = self.getColumn(event.Position)
         if col == self.getColIndex(State):
             mainItem = self.get(mainRow)
             if mainItem is None:
                 return
             selection = self.getSelectedProjectors()
             if mainItem not in selection:
                 selection = [mainItem]
             modPressed = wx.GetMouseState().GetModifiers() == wx.MOD_ALT
             fitID = self.mainFrame.getActiveFit()
             if isinstance(mainItem, EosModule) and modPressed:
                 fit = Fit.getInstance().getFit(fitID)
                 positions = getSimilarModPositions(fit.projectedModules, mainItem)
                 selection = [fit.projectedModules[p] for p in positions]
             elif isinstance(mainItem, EosFighter) and modPressed:
                 fit = Fit.getInstance().getFit(fitID)
                 selection = getSimilarFighters(fit.projectedFighters, mainItem)
             self.mainFrame.command.Submit(cmd.GuiChangeProjectedItemStatesCommand(
                 fitID=fitID,
                 mainItem=mainItem,
                 items=selection,
                 click='right' if event.GetButton() == 3 else 'left'))
             return
     event.Skip()
Example #3
0
 def __handleProjectedItem(self, mainItem, selection):
     fitID = self.mainFrame.getActiveFit()
     if isinstance(mainItem, EosFit):
         self.mainFrame.command.Submit(cmd.GuiRemoveProjectedItemsCommand(
             fitID=fitID, items=selection, amount=math.inf))
     elif isinstance(mainItem, EosModule):
         if wx.GetMouseState().GetModifiers() == wx.MOD_ALT:
             fit = Fit.getInstance().getFit(fitID)
             positions = getSimilarModPositions(fit.projectedModules, mainItem)
             items = [fit.projectedModules[p] for p in positions]
         else:
             items = selection
         self.mainFrame.command.Submit(cmd.GuiRemoveProjectedItemsCommand(
             fitID=fitID, items=items, amount=math.inf))
     elif isinstance(mainItem, EosDrone):
         self.mainFrame.command.Submit(cmd.GuiRemoveProjectedItemsCommand(
             fitID=fitID, items=selection, amount=math.inf))
     elif isinstance(mainItem, EosFighter):
         if wx.GetMouseState().GetModifiers() == wx.MOD_ALT:
             fit = Fit.getInstance().getFit(fitID)
             items = getSimilarFighters(fit.projectedFighters, mainItem)
         else:
             items = selection
         self.mainFrame.command.Submit(cmd.GuiRemoveProjectedItemsCommand(
             fitID=fitID, items=items, amount=math.inf))
     else:
         self.mainFrame.command.Submit(cmd.GuiRemoveProjectedItemsCommand(
             fitID=fitID, items=selection, amount=math.inf))
Example #4
0
File: port.py Project: Ebag333/Pyfa
    def importCrest(str_):
        fit = json.loads(str_)
        sMkt = Market.getInstance()

        f = Fit()
        f.name = fit['name']

        try:
            try:
                f.ship = Ship(sMkt.getItem(fit['ship']['id']))
            except ValueError:
                f.ship = Citadel(sMkt.getItem(fit['ship']['id']))
        except:
            return None

        items = fit['items']
        items.sort(key=lambda k: k['flag'])

        moduleList = []
        for module in items:
            try:
                item = sMkt.getItem(module['type']['id'], eager="group.category")
                if module['flag'] == INV_FLAG_DRONEBAY:
                    d = Drone(item)
                    d.amount = module['quantity']
                    f.drones.append(d)
                elif module['flag'] == INV_FLAG_CARGOBAY:
                    c = Cargo(item)
                    c.amount = module['quantity']
                    f.cargo.append(c)
                elif module['flag'] == INV_FLAG_FIGHTER:
                    fighter = Fighter(item)
                    f.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:
                        continue
                    # Add subsystems before modules to make sure T3 cruisers have subsystems installed
                    if item.category.name == "Subsystem":
                        if m.fits(f):
                            f.modules.append(m)
                    else:
                        if m.isValidState(State.ACTIVE):
                            m.state = State.ACTIVE

                        moduleList.append(m)

            except:
                continue

        # Recalc to get slot numbers correct for T3 cruisers
        svcFit.getInstance().recalc(f)

        for module in moduleList:
            if module.fits(f):
                f.modules.append(module)

        return f
Example #5
0
    def getText(self, stuff):
        if isinstance(stuff, Drone):
            return "%dx %s" % (stuff.amount, stuff.item.name)
        elif isinstance(stuff, Fighter):
            return "%d/%d %s" % \
                   (stuff.amountActive, stuff.getModifiedItemAttr("fighterSquadronMaxSize"), stuff.item.name)
        elif isinstance(stuff, Cargo):
            return "%dx %s" % (stuff.amount, stuff.item.name)
        elif isinstance(stuff, Fit):
            if self.projectedView:
                # we need a little more information for the projected view
                fitID = self.mainFrame.getActiveFit()
                info = stuff.getProjectionInfo(fitID)

                if info:
                    return "%dx %s (%s)" % (stuff.getProjectionInfo(fitID).amount, stuff.name, stuff.ship.item.name)

                pyfalog.warning("Projected View trying to display things that aren't there. stuff: {}, info: {}", repr(stuff),
                                info)
                return "<unknown>"
            else:
                return "%s (%s)" % (stuff.name, stuff.ship.item.name)
        elif isinstance(stuff, Rack):
            if FitSvc.getInstance().serviceFittingOptions["rackLabels"]:
                if stuff.slot == FittingSlot.MODE:
                    return '─ Tactical Mode ─'
                else:
                    return '─ {} {} Slot{}─'.format(stuff.num, FittingSlot(stuff.slot).name.capitalize(), '' if stuff.num == 1 else 's')
            else:
                return ""
        elif isinstance(stuff, Module):
            if self.projectedView:
                # check for projected abyssal name
                name_check = stuff.item.name[0:-2]
                type = WhProjector.abyssal_mapping.get(name_check, None)
                if type:
                    sMkt = Market.getInstance()
                    type = sMkt.getItem(type)
                    return "{} {}".format(type.name, stuff.item.name[-1:])

            if stuff.isEmpty:
                return "%s Slot" % FittingSlot(stuff.slot).name.capitalize()
            else:
                return stuff.item.name
        elif isinstance(stuff, Implant):
            return stuff.item.name
        else:
            item = getattr(stuff, "item", stuff)

            if FitSvc.getInstance().serviceFittingOptions["showMarketShortcuts"]:
                marketShortcut = getattr(item, "marketShortcut", None)

                if marketShortcut:
                    # use unicode subscript to display shortcut value
                    shortcut = chr(marketShortcut + 8320) + " "
                    del item.marketShortcut
                    return shortcut + item.name

            return item.name
Example #6
0
def test_getAllFits(DB, RifterFit, KeepstarFit):
    assert len(Fit.getAllFits()) == 0

    DB['db'].save(RifterFit)
    DB['db'].save(KeepstarFit)

    # For some reason in Travis this adds the first fit twice.  WHY?!?
    assert len(Fit.getAllFits()) != 0

    # Cleanup after ourselves
    DB['db'].remove(RifterFit)
    DB['db'].remove(KeepstarFit)
Example #7
0
    def display(self, srcContext, mainItem):
        if not self.settings.get('changeAffectingSkills'):
            return False

        if srcContext not in (
            "fittingModule", "fittingCharge",
            "fittingShip", "droneItem",
            "fighterItem"
        ):
            return False

        fitID = self.mainFrame.getActiveFit()
        if fitID is None:
            return False

        if (mainItem is None or getattr(mainItem, "isEmpty", False)) and srcContext != "fittingShip":
            return False

        self.sChar = Character.getInstance()
        self.sFit = Fit.getInstance()
        fit = self.sFit.getFit(fitID)

        self.charID = fit.character.ID

        # if self.sChar.getCharName(self.charID) in ("All 0", "All 5"):
        #    return False

        if srcContext == "fittingShip":
            sFit = Fit.getInstance()
            self.stuff = sFit.getFit(fitID).ship
            cont = sFit.getFit(fitID).ship.itemModifiedAttributes
        elif srcContext == "fittingCharge":
            cont = mainItem.chargeModifiedAttributes
        else:
            cont = mainItem.itemModifiedAttributes

        skills = set()

        for attrName in cont.iterAfflictions():
            if cont[attrName] == 0:
                continue

            for fit, afflictors in cont.getAfflictions(attrName).items():
                for afflictor, modifier, amount, used in afflictors:
                    # only add Skills
                    if not isinstance(afflictor, Skill):
                        continue

                    skills.add(afflictor)

        self.skills = sorted(skills, key=lambda x: x.item.name)
        return len(self.skills) > 0
Example #8
0
    def getText(self, stuff):
        if isinstance(stuff, Drone):
            return "%dx %s" % (stuff.amount, stuff.item.name)
        elif isinstance(stuff, Fighter):
            return "%d/%d %s" % \
                   (stuff.amountActive, stuff.getModifiedItemAttr("fighterSquadronMaxSize"), stuff.item.name)
        elif isinstance(stuff, Cargo):
            return "%dx %s" % (stuff.amount, stuff.item.name)
        elif isinstance(stuff, Fit):
            if self.projectedView:
                # we need a little more information for the projected view
                fitID = self.mainFrame.getActiveFit()
                info = stuff.getProjectionInfo(fitID)

                if info:
                    return "%dx %s (%s)" % (stuff.getProjectionInfo(fitID).amount, stuff.name, stuff.ship.item.name)

                pyfalog.warning("Projected View trying to display things that aren't there. stuff: {}, info: {}", repr(stuff),
                                info)
                return "<unknown>"
            else:
                return "%s (%s)" % (stuff.name, stuff.ship.item.name)
        elif isinstance(stuff, Rack):
            if FitSvc.getInstance().serviceFittingOptions["rackLabels"]:
                if stuff.slot == Slot.MODE:
                    return u'─ Tactical Mode ─'
                else:
                    return u'─ {} Slots ─'.format(Slot.getName(stuff.slot).capitalize())
            else:
                return ""
        elif isinstance(stuff, Module):
            if stuff.isEmpty:
                return "%s Slot" % Slot.getName(stuff.slot).capitalize()
            else:
                return stuff.item.name
        elif isinstance(stuff, Implant):
            return stuff.item.name
        else:
            item = getattr(stuff, "item", stuff)

            if FitSvc.getInstance().serviceFittingOptions["showMarketShortcuts"]:
                marketShortcut = getattr(item, "marketShortcut", None)

                if marketShortcut:
                    # use unicode subscript to display shortcut value
                    shortcut = unichr(marketShortcut + 8320) + u" "
                    del item.marketShortcut
                    return shortcut + item.name

            return item.name
Example #9
0
 def __init__(self, fitID, position):
     wx.Command.__init__(self, True, "")
     self.mainFrame = gui.mainFrame.MainFrame.getInstance()
     self.sFit = Fit.getInstance()
     self.internal_history = wx.CommandProcessor()
     self.fitID = fitID
     self.position = position
Example #10
0
    def swapItems(self, x, y, srcIdx):
        """Swap two modules in fitting window"""
        mstate = wx.GetMouseState()
        sFit = Fit.getInstance()
        fit = sFit.getFit(self.activeFitID)

        dstRow, _ = self.HitTest((x, y))

        if dstRow != -1 and dstRow not in self.blanks:
            mod1 = fit.modules[srcIdx]
            mod2 = self.mods[dstRow]

            if not isinstance(mod2, Module):
                return

            # can't swap modules to different racks
            if mod1.slot != mod2.slot:
                return

            clone = mstate.CmdDown() and mod2.isEmpty

            fitID = self.mainFrame.getActiveFit()
            if getattr(mod2, "modPosition") is not None:
                self.mainFrame.command.Submit(cmd.GuiModuleSwapOrCloneCommand(fitID, srcIdx, mod2.modPosition, clone))
            else:
                pyfalog.error("Missing module position for: {0}", str(getattr(mod2, "ID", "Unknown")))
Example #11
0
    def run(self):
        # wait 1 second just in case a lot of modifications get made
        time.sleep(1)
        if self.stopRunning:
            return

        sMkt = Market.getInstance()
        sFit = Fit.getInstance()
        settings = HTMLExportSettings.getInstance()

        minimal = settings.getMinimalEnabled()
        dnaUrl = "https://o.smium.org/loadout/dna/"

        if minimal:
            HTML = self.generateMinimalHTML(sMkt, sFit, dnaUrl)
        else:
            HTML = self.generateFullHTML(sMkt, sFit, dnaUrl)

        try:
            FILE = open(settings.getPath(), "w", encoding='utf-8')
            FILE.write(HTML)
            FILE.close()
        except IOError as ex:
            print(("Failed to write to " + settings.getPath()))
            pass
        except Exception as ex:
            pass

        if self.callback:
            wx.CallAfter(self.callback, -1)
Example #12
0
    def fitSelected(self, event):
        count = -1
        # @todo pheonix: _pages is supposed to be private?
        for index, page in enumerate(self.multiSwitch._pages):
            if not isinstance(page, gui.builtinViews.emptyView.BlankPage):  # Don't try and process it if it's a blank page.
                try:
                    if page.activeFitID == event.fitID:
                        count += 1
                        self.multiSwitch.SetSelection(index)
                        wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=event.fitID))
                        break
                except Exception as e:
                    pyfalog.critical("Caught exception in fitSelected")
                    pyfalog.critical(e)
        if count < 0:
            startup = getattr(event, "startup", False)  # see OpenFitsThread in gui.mainFrame
            from_import = getattr(event, "from_import", False)  # always open imported into a new tab
            sFit = Fit.getInstance()
            openFitInNew = sFit.serviceFittingOptions["openFitInNew"]
            mstate = wx.GetMouseState()

            if from_import or (not openFitInNew and mstate.CmdDown()) or startup or (openFitInNew and not mstate.CmdDown()):
                self.multiSwitch.AddPage()

            view = self.multiSwitch.GetSelectedPage()

            if not isinstance(view, FittingView):
                view = FittingView(self.multiSwitch)
                pyfalog.debug("###################### Created new view:" + repr(view))
                self.multiSwitch.ReplaceActivePage(view)

            view.fitSelected(event)
Example #13
0
    def fitRemoved(self, event):
        """
        If fit is removed and active, the page is deleted.
        We also refresh the fit of the new current page in case
        delete fit caused change in stats (projected)
        todo: move this to the notebook, not the page. We don't want the page being responsible for deleting itself
        """
        pyfalog.debug("FittingView::fitRemoved")
        if not self:
            event.Skip()
            return
        if event.fitID == self.getActiveFit():
            pyfalog.debug("    Deleted fit is currently active")
            self.parent.DeletePage(self.parent.GetPageIndex(self))

            try:
                # Sometimes there is no active page after deletion, hence the try block
                sFit = Fit.getInstance()

                # stopgap for #1384
                fit = sFit.getFit(self.getActiveFit())
                if fit:
                    sFit.refreshFit(self.getActiveFit())
                    wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.activeFitID))
            except RuntimeError:
                pyfalog.warning("Caught dead object")
                pass

        event.Skip()
Example #14
0
    def appendItem(self, event):
        """
        Adds items that are double clicks from the market browser. We handle both modules and ammo
        """
        if not self:
            event.Skip()
            return
        if self.parent.IsActive(self):
            itemID = event.itemID
            fitID = self.activeFitID
            if fitID is not None:
                sFit = Fit.getInstance()
                if sFit.isAmmo(itemID):
                    # If we've selected ammo, then apply to the selected module(s)
                    modules = []
                    sel = self.GetFirstSelected()
                    while sel != -1 and sel not in self.blanks:
                        mod = self.mods[self.GetItemData(sel)]
                        if isinstance(mod, Module) and not mod.isEmpty:
                            modules.append(self.mods[self.GetItemData(sel)])
                        sel = self.GetNextSelected(sel)

                    if len(modules) > 0:
                        self.mainFrame.command.Submit(cmd.GuiModuleAddChargeCommand(fitID, itemID, modules))
                else:
                    self.mainFrame.command.Submit(cmd.GuiModuleAddCommand(fitID, itemID))

        event.Skip()
Example #15
0
    def spawnMenu(self):
        sel = self.GetFirstSelected()
        menu = None

        sFit = Fit.getInstance()
        fit = sFit.getFit(self.mainFrame.getActiveFit())

        if not fit:
            return

        if sel != -1:
            implant = fit.appliedImplants[sel]

            sMkt = Market.getInstance()
            sourceContext = "implantItem" if fit.implantSource == ImplantLocation.FIT else "implantItemChar"
            itemContext = sMkt.getCategoryByItem(implant.item).name

            menu = ContextMenu.getMenu((implant,), (sourceContext, itemContext))
        elif sel == -1 and fit.implantSource == ImplantLocation.FIT:
            fitID = self.mainFrame.getActiveFit()
            if fitID is None:
                return
            context = (("implantView",),)
            menu = ContextMenu.getMenu([], *context)
        if menu is not None:
            self.PopupMenu(menu)
Example #16
0
 def Do(self):
     pyfalog.debug('Doing removal of booster from position {} on fit {}'.format(self.position, self.fitID))
     fit = Fit.getInstance().getFit(self.fitID)
     booster = fit.boosters[self.position]
     self.savedBoosterInfo = BoosterInfo.fromBooster(booster)
     fit.boosters.remove(booster)
     return True
Example #17
0
    def getText(self, itmContext, selection):
        sDP = import_DamagePattern.getInstance()
        sFit = Fit.getInstance()
        fitID = self.mainFrame.getActiveFit()
        self.fit = sFit.getFit(fitID)

        self.patterns = sDP.getDamagePatternList()
        self.patterns.sort(key=lambda p: (p.name not in ["Uniform", "Selected Ammo"], p.name))

        self.patternIds = {}
        self.subMenus = OrderedDict()
        self.singles = []

        # iterate and separate damage patterns based on "[Parent] Child"
        for pattern in self.patterns:
            start, end = pattern.name.find('['), pattern.name.find(']')
            if start is not -1 and end is not -1:
                currBase = pattern.name[start + 1:end]
                # set helper attr
                setattr(pattern, "_name", pattern.name[end + 1:].strip())
                if currBase not in self.subMenus:
                    self.subMenus[currBase] = []
                self.subMenus[currBase].append(pattern)
            else:
                self.singles.append(pattern)

        # return list of names, with singles first followed by submenu names
        self.m = map(lambda p: p.name, self.singles) + self.subMenus.keys()
        return self.m
Example #18
0
    def fitChanged(self, event):
        sFit = Fit.getInstance()
        fit = sFit.getFit(event.fitID)

        self.Parent.Parent.Parent.DisablePage(self.Parent, not fit or fit.isStructure)

        # Clear list and get out if current fitId is None
        if event.fitID is None and self.lastFitId is not None:
            self.DeleteAllItems()
            self.lastFitId = None
            event.Skip()
            return

        self.original = fit.implants if fit is not None else None
        self.implants = stuff = fit.appliedImplants if fit is not None else None
        if stuff is not None:
            stuff.sort(key=lambda implant: implant.slot)

        if event.fitID != self.lastFitId:
            self.lastFitId = event.fitID

            item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)

            if item != -1:
                self.EnsureVisible(item)

            self.deselectItems()

        self.update(stuff)
        event.Skip()
Example #19
0
    def fitChanged(self, event):
        sFit = Fit.getInstance()
        fit = sFit.getFit(event.fitID)

        self.Parent.Parent.Parent.DisablePage(self.Parent, not fit)

        # Clear list and get out if current fitId is None
        if event.fitID is None and self.lastFitId is not None:
            self.DeleteAllItems()
            self.lastFitId = None
            event.Skip()
            return

        self.original = fit.fighters if fit is not None else None
        self.fighters = fit.fighters[:] if fit is not None else None

        if self.fighters is not None:
            self.fighters.sort(key=self.fighterKey)

        if event.fitID != self.lastFitId:
            self.lastFitId = event.fitID

            item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)

            if item != -1:
                self.EnsureVisible(item)

            self.deselectItems()

        self.update(self.fighters)
        event.Skip()
Example #20
0
    def fitChanged(self, event):
        sFit = Fit.getInstance()
        activeFitID = self.mainFrame.getActiveFit()
        fit = sFit.getFit(activeFitID)

        if fit:
            for x in self.labels:
                if fit.isStructure:
                    slot = getattr(FittingSlot, "FS_{}".format(x.upper()))
                else:
                    slot = getattr(FittingSlot, "F_{}".format(x.upper()))
                used = fit.getSlotsUsed(slot)
                total = fit.getNumSlots(slot)
                color = wx.Colour(204, 51, 51) if used > total else wx.SystemSettings.GetColour(
                    wx.SYS_COLOUR_WINDOWTEXT)

                lbl = getattr(self, "label%sUsed" % x.capitalize())
                lbl.SetLabel(str(int(used)))
                lbl.SetForegroundColour(color)

                lbl = getattr(self, "label%sTotal" % x.capitalize())
                lbl.SetLabel(str(int(total)))
                lbl.SetForegroundColour(color)

            self.Refresh()

        event.Skip()
    def refreshCharacterList(self, event=None):
        choice = self.charChoice
        sChar = Character.getInstance()
        activeChar = self.getActiveCharacter()

        choice.Clear()
        charList = sorted(sChar.getCharacterList(), key=lambda c: (not c.ro, c.name))
        picked = False

        for char in charList:
            currId = choice.Append(char.name, char.ID)
            if char.ID == activeChar:
                choice.SetSelection(currId)
                self.charChanged(None)
                picked = True

        if not picked:
            charID = sChar.all5ID()
            self.selectChar(charID)
            fitID = self.mainFrame.getActiveFit()
            sFit = Fit.getInstance()
            sFit.changeChar(fitID, charID)

        choice.Append(u"\u2015 Open Character Editor \u2015", -1)
        self.charCache = self.charChoice.GetCurrentSelection()

        if event is not None:
            event.Skip()
Example #22
0
    def fitChanged(self, event):
        enable = event.fitID is not None
        self.Enable(wx.ID_SAVEAS, enable)
        self.Enable(wx.ID_COPY, enable)
        self.Enable(self.exportSkillsNeededId, enable)

        sChar = Character.getInstance()
        charID = self.mainFrame.charSelection.getActiveCharacter()
        char = sChar.getCharacter(charID)

        # enable/disable character saving stuff
        self.Enable(self.saveCharId, not char.ro and char.isDirty)
        self.Enable(self.saveCharAsId, char.isDirty)
        self.Enable(self.revertCharId, char.isDirty)

        self.Enable(self.toggleIgnoreRestrictionID, enable)

        if event.fitID:
            sFit = Fit.getInstance()
            fit = sFit.getFit(event.fitID)

            if fit.ignoreRestrictions:
                self.ignoreRestrictionItem.SetItemLabel("Enable Fitting Restrictions")
            else:
                self.ignoreRestrictionItem.SetItemLabel("Disable Fitting Restrictions")

        event.Skip()
Example #23
0
    def swapModule(self, x, y, modIdx):
        """Swap a module from fitting window with cargo"""
        sFit = Fit.getInstance()
        fit = sFit.getFit(self.mainFrame.getActiveFit())
        dstRow, _ = self.HitTest((x, y))
        mstate = wx.GetMouseState()

        # Gather module information to get position
        module = fit.modules[modIdx]

        if module.item.isAbyssal:
            dlg = wx.MessageDialog(self,
               "Moving this Abyssal module to the cargo will convert it to the base module. Do you wish to proceed?",
               "Confirm", wx.YES_NO | wx.ICON_QUESTION)
            result = dlg.ShowModal() == wx.ID_YES

            if not result:
                return

        cargoPos = dstRow if dstRow > -1 else None

        self.mainFrame.command.Submit(cmd.GuiModuleToCargoCommand(
            self.mainFrame.getActiveFit(),
            module.modPosition,
            cargoPos,
            mstate.cmdDown
        ))
Example #24
0
    def fitChanged(self, event):
        sFit = Fit.getInstance()
        fit = sFit.getFit(event.fitID)

        # self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)

        # Clear list and get out if current fitId is None
        if event.fitID is None and self.lastFitId is not None:
            self.DeleteAllItems()
            self.lastFitId = None
            event.Skip()
            return

        self.original = fit.cargo if fit is not None else None
        self.cargo = stuff = fit.cargo if fit is not None else None
        if stuff is not None:
            stuff.sort(key=lambda c: (c.item.group.category.name, c.item.group.name, c.item.name))

        if event.fitID != self.lastFitId:
            self.lastFitId = event.fitID

            item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)

            if item != -1:
                self.EnsureVisible(item)

            self.deselectItems()

        self.populate(stuff)
        self.refresh(stuff)
        event.Skip()
Example #25
0
    def swapItems(self, x, y, srcIdx):
        """Swap two modules in fitting window"""
        mstate = wx.GetMouseState()
        sFit = Fit.getInstance()
        fit = sFit.getFit(self.activeFitID)

        if mstate.CmdDown():
            clone = True
        else:
            clone = False

        dstRow, _ = self.HitTest((x, y))

        if dstRow != -1 and dstRow not in self.blanks:

            mod1 = fit.modules[srcIdx]
            mod2 = self.mods[dstRow]

            if not isinstance(mod2, Module):
                return

            # can't swap modules to different racks
            if mod1.slot != mod2.slot:
                return

            if getattr(mod2, "modPosition") is not None:
                if clone and mod2.isEmpty:
                    sFit.cloneModule(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition)
                else:
                    sFit.swapModules(self.mainFrame.getActiveFit(), srcIdx, mod2.modPosition)

                wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=self.mainFrame.getActiveFit()))
            else:
                pyfalog.error("Missing module position for: {0}", str(getattr(mod2, "ID", "Unknown")))
Example #26
0
 def _merge(self, src, dst):
     dstDrone = self.get(dst)
     if isinstance(dstDrone, es_Drone):
         sFit = Fit.getInstance()
         fitID = self.mainFrame.getActiveFit()
         if sFit.mergeDrones(fitID, self.get(src), dstDrone, True):
             wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
Example #27
0
 def __init__(self, fitID, itemID):
     wx.Command.__init__(self, True, "Module Charge Add")
     self.mainFrame = gui.mainFrame.MainFrame.getInstance()
     self.sFit = Fit.getInstance()
     self.internal_history = wx.CommandProcessor()
     self.fitID = fitID
     self.itemID = itemID
Example #28
0
    def exportFitting(self, event):
        sPort = Port.getInstance()
        fitID = self.mainFrame.getActiveFit()

        self.statusbar.SetStatusText("", 0)

        if fitID is None:
            self.statusbar.SetStatusText("Please select an active fitting in the main window", 1)
            return

        self.statusbar.SetStatusText("Sending request and awaiting response", 1)
        sCrest = Crest.getInstance()

        try:
            sFit = Fit.getInstance()
            data = sPort.exportCrest(sFit.getFit(fitID))
            res = sCrest.postFitting(self.getActiveCharacter(), data)

            self.statusbar.SetStatusText("%d: %s" % (res.status_code, res.reason), 0)
            try:
                text = json.loads(res.text)
                self.statusbar.SetStatusText(text['message'], 1)
            except ValueError:
                self.statusbar.SetStatusText("", 1)
        except requests.exceptions.ConnectionError:
            self.statusbar.SetStatusText("Connection error, please check your internet connection", 1)
Example #29
0
    def appendItem(self, event):
        if self.parent.IsActive(self):
            itemID = event.itemID
            fitID = self.activeFitID
            if fitID is not None:
                sFit = Fit.getInstance()
                if sFit.isAmmo(itemID):
                    modules = []
                    sel = self.GetFirstSelected()
                    while sel != -1 and sel not in self.blanks:
                        mod = self.mods[self.GetItemData(sel)]
                        if isinstance(mod, Module) and not mod.isEmpty:
                            modules.append(self.mods[self.GetItemData(sel)])
                        sel = self.GetNextSelected(sel)

                    if len(modules) > 0:
                        sFit.setAmmo(fitID, itemID, modules)
                        wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
                else:
                    populate = sFit.appendModule(fitID, itemID)
                    if populate is not None:
                        self.slotsChanged()
                        wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID, action="modadd", typeID=itemID))

        event.Skip()
Example #30
0
    def fitChanged(self, event):
        sFit = Fit.getInstance()
        fit = sFit.getFit(event.fitID)

        self.Parent.Parent.DisablePage(self, not fit or fit.isStructure)

        # Clear list and get out if current fitId is None
        if event.fitID is None and self.lastFitId is not None:
            self.DeleteAllItems()
            self.lastFitId = None
            event.Skip()
            return

        self.origional = fit.boosters if fit is not None else None
        self.boosters = stuff = fit.boosters[:] if fit is not None else None

        if event.fitID != self.lastFitId:
            self.lastFitId = event.fitID

            item = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_DONTCARE)

            if item != -1:
                self.EnsureVisible(item)

            self.deselectItems()

        self.populate(stuff)
        self.refresh(stuff)
        event.Skip()
Example #31
0
def importEft(lines):
    lines = _importPrepare(lines)
    try:
        fit = _importCreateFit(lines)
    except EftImportError:
        return

    aFit = AbstractFit()
    aFit.mutations = importGetMutationData(lines)

    stubPattern = '^\[.+?\]$'
    modulePattern = '^(?P<typeName>{0}+?)(,\s*(?P<chargeName>{0}+?))?(?P<offline>\s*{1})?(\s*\[(?P<mutation>\d+?)\])?$'.format(NAME_CHARS, OFFLINE_SUFFIX)
    droneCargoPattern = '^(?P<typeName>{}+?) x(?P<amount>\d+?)(\s*\[(?P<mutation>\d+?)\])?$'.format(NAME_CHARS)

    sections = []
    for section in _importSectionIter(lines):
        for line in section.lines:
            # Stub line
            if re.match(stubPattern, line):
                section.itemSpecs.append(None)
                continue
            # Items with quantity specifier
            m = re.match(droneCargoPattern, line)
            if m:
                try:
                    itemSpec = MultiItemSpec(m.group('typeName'))
                # Items which cannot be fetched are considered as stubs
                except EftImportError:
                    section.itemSpecs.append(None)
                else:
                    itemSpec.amount = int(m.group('amount'))
                    section.itemSpecs.append(itemSpec)
                    if m.group('mutation'):
                        itemSpec.mutationIdx = int(m.group('mutation'))
                continue
            # All other items
            m = re.match(modulePattern, line)
            if m:
                try:
                    itemSpec = RegularItemSpec(m.group('typeName'), chargeName=m.group('chargeName'))
                # Items which cannot be fetched are considered as stubs
                except EftImportError:
                    section.itemSpecs.append(None)
                else:
                    if m.group('offline'):
                        itemSpec.offline = True
                    if m.group('mutation'):
                        itemSpec.mutationIdx = int(m.group('mutation'))
                    section.itemSpecs.append(itemSpec)
                continue
        _clearTail(section.itemSpecs)
        sections.append(section)

    hasDroneBay = any(s.isDroneBay for s in sections)
    hasFighterBay = any(s.isFighterBay for s in sections)
    for section in sections:
        if section.isModuleRack:
            aFit.addModules(section.itemSpecs)
        elif section.isImplantRack:
            for itemSpec in section.itemSpecs:
                aFit.addImplant(itemSpec)
        elif section.isDroneBay:
            for itemSpec in section.itemSpecs:
                aFit.addDrone(itemSpec)
        elif section.isFighterBay:
            for itemSpec in section.itemSpecs:
                aFit.addFighter(itemSpec)
        elif section.isCargoHold:
            for itemSpec in section.itemSpecs:
                aFit.addCargo(itemSpec)
        # Mix between different kinds of item specs (can happen when some
        # blank lines are removed)
        else:
            for itemSpec in section.itemSpecs:
                if itemSpec is None:
                    continue
                if itemSpec.isModule:
                    aFit.addModule(itemSpec)
                elif itemSpec.isImplant:
                    aFit.addImplant(itemSpec)
                elif itemSpec.isDrone and not hasDroneBay:
                    aFit.addDrone(itemSpec)
                elif itemSpec.isFighter and not hasFighterBay:
                    aFit.addFighter(itemSpec)
                elif itemSpec.isCargo:
                    aFit.addCargo(itemSpec)

    # Subsystems first because they modify slot amount
    for i, m in enumerate(aFit.subsystems):
        if m is None:
            dummy = Module.buildEmpty(aFit.getSlotByContainer(aFit.subsystems))
            dummy.owner = fit
            fit.modules.replaceRackPosition(i, dummy)
        elif m.fits(fit):
            m.owner = fit
            fit.modules.replaceRackPosition(i, m)
    sFit = svcFit.getInstance()
    sFit.recalc(fit)
    sFit.fill(fit)

    # Other stuff
    for modRack in (
        aFit.rigs,
        aFit.services,
        aFit.modulesHigh,
        aFit.modulesMed,
        aFit.modulesLow,
    ):
        for i, m in enumerate(modRack):
            if m is None:
                dummy = Module.buildEmpty(aFit.getSlotByContainer(modRack))
                dummy.owner = fit
                fit.modules.replaceRackPosition(i, dummy)
            elif m.fits(fit):
                m.owner = fit
                if not m.isValidState(m.state):
                    pyfalog.warning('service.port.eft.importEft: module {} cannot have state {}', m, m.state)
                fit.modules.replaceRackPosition(i, m)
    for implant in aFit.implants:
        fit.implants.append(implant)
    for booster in aFit.boosters:
        fit.boosters.append(booster)
    for drone in aFit.drones:
        fit.drones.append(drone)
    for fighter in aFit.fighters:
        fit.fighters.append(fighter)
    for cargo in aFit.cargo.values():
        fit.cargo.append(cargo)

    return fit
Example #32
0
def importEftCfg(shipname, lines, iportuser):
    """Handle import from EFT config store file"""

    # Check if we have such ship in database, bail if we don't
    sMkt = Market.getInstance()
    try:
        sMkt.getItem(shipname)
    except (KeyboardInterrupt, SystemExit):
        raise
    except:
        return []  # empty list is expected

    fits = []  # List for fits
    fitIndices = []  # List for starting line numbers for each fit

    for line in lines:
        # Detect fit header
        if line[:1] == "[" and line[-1:] == "]":
            # Line index where current fit starts
            startPos = lines.index(line)
            fitIndices.append(startPos)

    for i, startPos in enumerate(fitIndices):
        # End position is last file line if we're trying to get it for last fit,
        # or start position of next fit minus 1
        endPos = len(lines) if i == len(fitIndices) - 1 else fitIndices[i + 1]

        # Finally, get lines for current fitting
        fitLines = lines[startPos:endPos]

        try:
            # Create fit object
            fitobj = Fit()
            # Strip square brackets and pull out a fit name
            fitobj.name = fitLines[0][1:-1]
            # Assign ship to fitting
            try:
                fitobj.ship = Ship(sMkt.getItem(shipname))
            except ValueError:
                fitobj.ship = Citadel(sMkt.getItem(shipname))

            moduleList = []
            for x in range(1, len(fitLines)):
                line = fitLines[x]
                if not line:
                    continue

                # Parse line into some data we will need
                misc = re.match("(Drones|Implant|Booster)_(Active|Inactive)=(.+)", line)
                cargo = re.match("Cargohold=(.+)", line)
                # 2017/03/27 NOTE: store description from EFT
                description = re.match("Description=(.+)", line)

                if misc:
                    entityType = misc.group(1)
                    entityState = misc.group(2)
                    entityData = misc.group(3)
                    if entityType == "Drones":
                        droneData = re.match("(.+),([0-9]+)", entityData)
                        # Get drone name and attempt to detect drone number
                        droneName = droneData.group(1) if droneData else entityData
                        droneAmount = int(droneData.group(2)) if droneData else 1
                        # Bail if we can't get item or it's not from drone category
                        try:
                            droneItem = sMkt.getItem(droneName, eager="group.category")
                        except (KeyboardInterrupt, SystemExit):
                            raise
                        except:
                            pyfalog.warning("Cannot get item.")
                            continue
                        if droneItem.category.name == "Drone":
                            # Add drone to the fitting
                            d = Drone(droneItem)
                            d.amount = droneAmount
                            if entityState == "Active":
                                d.amountActive = droneAmount
                            elif entityState == "Inactive":
                                d.amountActive = 0
                            fitobj.drones.append(d)
                        elif droneItem.category.name == "Fighter":  # EFT saves fighter as drones
                            ft = Fighter(droneItem)
                            ft.amount = int(droneAmount) if ft.amount <= ft.fighterSquadronMaxSize else ft.fighterSquadronMaxSize
                            fitobj.fighters.append(ft)
                        else:
                            continue
                    elif entityType == "Implant":
                        # Bail if we can't get item or it's not from implant category
                        try:
                            implantItem = sMkt.getItem(entityData, eager="group.category")
                        except (KeyboardInterrupt, SystemExit):
                            raise
                        except:
                            pyfalog.warning("Cannot get item.")
                            continue
                        if implantItem.category.name != "Implant":
                            continue
                        # Add implant to the fitting
                        imp = Implant(implantItem)
                        if entityState == "Active":
                            imp.active = True
                        elif entityState == "Inactive":
                            imp.active = False
                        fitobj.implants.append(imp)
                    elif entityType == "Booster":
                        # Bail if we can't get item or it's not from implant category
                        try:
                            boosterItem = sMkt.getItem(entityData, eager="group.category")
                        except (KeyboardInterrupt, SystemExit):
                            raise
                        except:
                            pyfalog.warning("Cannot get item.")
                            continue
                        # All boosters have implant category
                        if boosterItem.category.name != "Implant":
                            continue
                        # Add booster to the fitting
                        b = Booster(boosterItem)
                        if entityState == "Active":
                            b.active = True
                        elif entityState == "Inactive":
                            b.active = False
                        fitobj.boosters.append(b)
                # If we don't have any prefixes, then it's a module
                elif cargo:
                    cargoData = re.match("(.+),([0-9]+)", cargo.group(1))
                    cargoName = cargoData.group(1) if cargoData else cargo.group(1)
                    cargoAmount = int(cargoData.group(2)) if cargoData else 1
                    # Bail if we can't get item
                    try:
                        item = sMkt.getItem(cargoName)
                    except (KeyboardInterrupt, SystemExit):
                        raise
                    except:
                        pyfalog.warning("Cannot get item.")
                        continue
                    # Add Cargo to the fitting
                    c = Cargo(item)
                    c.amount = cargoAmount
                    fitobj.cargo.append(c)
                # 2017/03/27 NOTE: store description from EFT
                elif description:
                    fitobj.notes = description.group(1).replace("|", "\n")
                else:
                    withCharge = re.match("(.+),(.+)", line)
                    modName = withCharge.group(1) if withCharge else line
                    chargeName = withCharge.group(2) if withCharge else None
                    # If we can't get module item, skip it
                    try:
                        modItem = sMkt.getItem(modName)
                    except (KeyboardInterrupt, SystemExit):
                        raise
                    except:
                        pyfalog.warning("Cannot get item.")
                        continue

                    # Create module
                    m = Module(modItem)

                    # Add subsystems before modules to make sure T3 cruisers have subsystems installed
                    if modItem.category.name == "Subsystem":
                        if m.fits(fitobj):
                            fitobj.modules.append(m)
                    else:
                        m.owner = fitobj
                        # Activate mod if it is activable
                        if m.isValidState(FittingModuleState.ACTIVE):
                            m.state = activeStateLimit(m.item)
                        # Add charge to mod if applicable, on any errors just don't add anything
                        if chargeName:
                            try:
                                chargeItem = sMkt.getItem(chargeName, eager="group.category")
                                if chargeItem.category.name == "Charge":
                                    m.charge = chargeItem
                            except (KeyboardInterrupt, SystemExit):
                                raise
                            except:
                                pyfalog.warning("Cannot get item.")
                                pass
                        # Append module to fit
                        moduleList.append(m)

            # Recalc to get slot numbers correct for T3 cruisers
            sFit = svcFit.getInstance()
            sFit.recalc(fitobj)
            sFit.fill(fitobj)

            for module in moduleList:
                if module.fits(fitobj):
                    fitobj.modules.append(module)

            # Append fit to list of fits
            fits.append(fitobj)

            if iportuser:  # NOTE: Send current processing status
                processing_notify(
                    iportuser, IPortUser.PROCESS_IMPORT | IPortUser.ID_UPDATE,
                    "%s:\n%s" % (fitobj.ship.name, fitobj.name)
                )

        except (KeyboardInterrupt, SystemExit):
            raise
        # Skip fit silently if we get an exception
        except Exception as e:
            pyfalog.error("Caught exception on fit.")
            pyfalog.error(e)
            pass

    return fits
Example #33
0
 def Do(self):
     cmd = CalcToggleBoosterStateCommand(fitID=self.fitID, position=self.position)
     success = self.internalHistory.submit(cmd)
     Fit.getInstance().recalc(self.fitID)
     wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitID=self.fitID))
     return success
Example #34
0
    def getSubMenu(self, context, mainItem, selection, rootMenu, i, pitem):
        self.moduleLookup = {}
        sFit = Fit.getInstance()
        fit = sFit.getFit(self.mainFrame.getActiveFit())

        def get_metalevel(x):
            if 'metaLevel' not in x.attributes:
                return 0
            return x.attributes['metaLevel'].value

        def get_metagroup(x):
            # We want deadspace before officer mods
            remap = {5: 6, 6: 5}
            return remap.get(x.metaGroup.ID,
                             x.metaGroup.ID) if x.metaGroup is not None else 0

        def get_boosterrank(x):
            # If we're returning a lot of items, sort my name
            if len(self.mainVariations) > 7:
                return x.name
            # Sort by booster chance to get some sort of pseudorank.
            elif 'boosterEffectChance1' in x.attributes:
                return x.attributes['boosterEffectChance1'].value
            # the "first" rank (Synth) doesn't have boosterEffectChance1. If we're not pulling back all boosters, return 0 for proper sorting
            else:
                return 0

        m = wx.Menu()

        # If on Windows we need to bind out events into the root menu, on other
        # platforms they need to go to our sub menu
        if 'wxMSW' in wx.PlatformInfo:
            bindmenu = rootMenu
        else:
            bindmenu = m

        # Sort items by metalevel, and group within that metalevel
        items = list(self.mainVariations)
        # Sort all items by name first
        items.sort(key=lambda x: x.name)
        # Do not do any extra sorting for implants
        if 'implantItem' in context:
            pass
        # Boosters don't have meta or anything concrete that we can rank by. Go by chance to inflict side effect
        elif 'boosterItem' in context:
            items.sort(key=get_boosterrank)
        else:
            # sort by group and meta level
            items.sort(key=get_metalevel)
            items.sort(key=get_metagroup)

        group = None
        for item in items:
            # Apparently no metaGroup for the Tech I variant:
            if 'subSystem' in item.effects:
                thisgroup = item.marketGroup.marketGroupName
            elif item.metaGroup is None:
                thisgroup = 'Tech I'
            else:
                thisgroup = item.metaGroup.name

            if thisgroup != group and context not in ('implantItem',
                                                      'boosterItem'):
                group = thisgroup
                id = ContextMenuCombined.nextID()
                m.Append(id, '─ %s ─' % group)
                m.Enable(id, False)

            id = ContextMenuCombined.nextID()
            mitem = wx.MenuItem(rootMenu, id, item.name)
            bindmenu.Bind(wx.EVT_MENU, self.handleSwitch, mitem)

            self.moduleLookup[id] = item, context
            m.Append(mitem)
            mitem.Enable(fit.canFit(item))

        return m
Example #35
0
    def populatePanel(self, panel):
        self.mainFrame = gui.mainFrame.MainFrame.getInstance()
        self.dirtySettings = False
        self.openFitsSettings = SettingsProvider.getInstance().getSettings(
            "pyfaPrevOpenFits", {
                "enabled": False,
                "pyfaOpenFits": []
            })

        helpCursor = wx.StockCursor(wx.CURSOR_QUESTION_ARROW)

        mainSizer = wx.BoxSizer(wx.VERTICAL)

        self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title,
                                     wx.DefaultPosition, wx.DefaultSize, 0)
        self.stTitle.Wrap(-1)
        self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))

        mainSizer.Add(self.stTitle, 0, wx.ALL, 5)

        self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY,
                                           wx.DefaultPosition, wx.DefaultSize,
                                           wx.LI_HORIZONTAL)
        mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)

        self.cbGlobalChar = wx.CheckBox(panel, wx.ID_ANY,
                                        u"Use global character",
                                        wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbGlobalChar, 0, wx.ALL | wx.EXPAND, 5)

        self.cbGlobalDmgPattern = wx.CheckBox(panel, wx.ID_ANY,
                                              u"Use global damage pattern",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        mainSizer.Add(self.cbGlobalDmgPattern, 0, wx.ALL | wx.EXPAND, 5)

        self.cbCompactSkills = wx.CheckBox(panel, wx.ID_ANY,
                                           u"Compact skills needed tooltip",
                                           wx.DefaultPosition, wx.DefaultSize,
                                           0)
        mainSizer.Add(self.cbCompactSkills, 0, wx.ALL | wx.EXPAND, 5)

        self.cbFitColorSlots = wx.CheckBox(panel, wx.ID_ANY,
                                           u"Color fitting view by slot",
                                           wx.DefaultPosition, wx.DefaultSize,
                                           0)
        mainSizer.Add(self.cbFitColorSlots, 0, wx.ALL | wx.EXPAND, 5)

        self.cbReopenFits = wx.CheckBox(panel, wx.ID_ANY,
                                        u"Reopen previous fits on startup",
                                        wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbReopenFits, 0, wx.ALL | wx.EXPAND, 5)

        self.cbRackSlots = wx.CheckBox(panel, wx.ID_ANY, u"Separate Racks",
                                       wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbRackSlots, 0, wx.ALL | wx.EXPAND, 5)

        labelSizer = wx.BoxSizer(wx.VERTICAL)
        self.cbRackLabels = wx.CheckBox(panel, wx.ID_ANY, u"Show Rack Labels",
                                        wx.DefaultPosition, wx.DefaultSize, 0)
        labelSizer.Add(self.cbRackLabels, 0, wx.ALL | wx.EXPAND, 5)
        mainSizer.Add(labelSizer, 0, wx.LEFT | wx.EXPAND, 30)

        self.cbShowTooltip = wx.CheckBox(panel, wx.ID_ANY,
                                         u"Show tab tooltips",
                                         wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbShowTooltip, 0, wx.ALL | wx.EXPAND, 5)

        self.cbMarketShortcuts = wx.CheckBox(panel, wx.ID_ANY,
                                             u"Show market shortcuts",
                                             wx.DefaultPosition,
                                             wx.DefaultSize, 0)
        mainSizer.Add(self.cbMarketShortcuts, 0, wx.ALL | wx.EXPAND, 5)

        self.cbGaugeAnimation = wx.CheckBox(panel, wx.ID_ANY,
                                            u"Animate gauges",
                                            wx.DefaultPosition, wx.DefaultSize,
                                            0)
        mainSizer.Add(self.cbGaugeAnimation, 0, wx.ALL | wx.EXPAND, 5)

        self.cbExportCharges = wx.CheckBox(panel, wx.ID_ANY,
                                           u"Export loaded charges",
                                           wx.DefaultPosition, wx.DefaultSize,
                                           0)
        mainSizer.Add(self.cbExportCharges, 0, wx.ALL | wx.EXPAND, 5)

        self.cbOpenFitInNew = wx.CheckBox(
            panel, wx.ID_ANY, u"Open fittings in a new page by default",
            wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbOpenFitInNew, 0, wx.ALL | wx.EXPAND, 5)

        self.cbShowShipBrowserTooltip = wx.CheckBox(
            panel, wx.ID_ANY, u"Show ship browser tooltip", wx.DefaultPosition,
            wx.DefaultSize, 0)
        mainSizer.Add(self.cbShowShipBrowserTooltip, 0, wx.ALL | wx.EXPAND, 5)

        priceSizer = wx.BoxSizer(wx.HORIZONTAL)

        self.stDefaultSystem = wx.StaticText(panel, wx.ID_ANY,
                                             u"Default Market Prices:",
                                             wx.DefaultPosition,
                                             wx.DefaultSize, 0)
        self.stDefaultSystem.Wrap(-1)
        priceSizer.Add(self.stDefaultSystem, 0,
                       wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)

        self.chPriceSystem = wx.Choice(panel, choices=Price.systemsList.keys())
        priceSizer.Add(self.chPriceSystem, 1, wx.ALL | wx.EXPAND, 5)

        mainSizer.Add(priceSizer, 0, wx.ALL | wx.EXPAND, 0)

        delayTimer = wx.BoxSizer(wx.HORIZONTAL)

        self.stMarketDelay = wx.StaticText(panel, wx.ID_ANY,
                                           u"Market Search Delay (ms):",
                                           wx.DefaultPosition, wx.DefaultSize,
                                           0)
        self.stMarketDelay.Wrap(-1)
        self.stMarketDelay.SetCursor(helpCursor)
        self.stMarketDelay.SetToolTip(
            wx.ToolTip(
                'The delay between a keystroke and the market search. Can help reduce lag when typing fast in the market search box.'
            ))

        delayTimer.Add(self.stMarketDelay, 0,
                       wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)

        self.intDelay = IntCtrl(panel, max=1000, limited=True)
        delayTimer.Add(self.intDelay, 0, wx.ALL, 5)

        mainSizer.Add(delayTimer, 0, wx.ALL | wx.EXPAND, 0)

        self.sFit = Fit.getInstance()

        self.cbGlobalChar.SetValue(
            self.sFit.serviceFittingOptions["useGlobalCharacter"])
        self.cbGlobalDmgPattern.SetValue(
            self.sFit.serviceFittingOptions["useGlobalDamagePattern"])
        self.cbFitColorSlots.SetValue(
            self.sFit.serviceFittingOptions["colorFitBySlot"] or False)
        self.cbRackSlots.SetValue(self.sFit.serviceFittingOptions["rackSlots"]
                                  or False)
        self.cbRackLabels.SetValue(
            self.sFit.serviceFittingOptions["rackLabels"] or False)
        self.cbCompactSkills.SetValue(
            self.sFit.serviceFittingOptions["compactSkills"] or False)
        self.cbReopenFits.SetValue(self.openFitsSettings["enabled"])
        self.cbShowTooltip.SetValue(
            self.sFit.serviceFittingOptions["showTooltip"] or False)
        self.cbMarketShortcuts.SetValue(
            self.sFit.serviceFittingOptions["showMarketShortcuts"] or False)
        self.cbGaugeAnimation.SetValue(
            self.sFit.serviceFittingOptions["enableGaugeAnimation"])
        self.cbExportCharges.SetValue(
            self.sFit.serviceFittingOptions["exportCharges"])
        self.cbOpenFitInNew.SetValue(
            self.sFit.serviceFittingOptions["openFitInNew"])
        self.chPriceSystem.SetStringSelection(
            self.sFit.serviceFittingOptions["priceSystem"])
        self.cbShowShipBrowserTooltip.SetValue(
            self.sFit.serviceFittingOptions["showShipBrowserTooltip"])
        self.intDelay.SetValue(
            self.sFit.serviceFittingOptions["marketSearchDelay"])

        self.cbGlobalChar.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalCharStateChange)
        self.cbGlobalDmgPattern.Bind(wx.EVT_CHECKBOX,
                                     self.OnCBGlobalDmgPatternStateChange)
        self.cbFitColorSlots.Bind(wx.EVT_CHECKBOX, self.onCBGlobalColorBySlot)
        self.cbRackSlots.Bind(wx.EVT_CHECKBOX, self.onCBGlobalRackSlots)
        self.cbRackLabels.Bind(wx.EVT_CHECKBOX, self.onCBGlobalRackLabels)
        self.cbCompactSkills.Bind(wx.EVT_CHECKBOX, self.onCBCompactSkills)
        self.cbReopenFits.Bind(wx.EVT_CHECKBOX, self.onCBReopenFits)
        self.cbShowTooltip.Bind(wx.EVT_CHECKBOX, self.onCBShowTooltip)
        self.cbMarketShortcuts.Bind(wx.EVT_CHECKBOX, self.onCBShowShortcuts)
        self.cbGaugeAnimation.Bind(wx.EVT_CHECKBOX, self.onCBGaugeAnimation)
        self.cbExportCharges.Bind(wx.EVT_CHECKBOX, self.onCBExportCharges)
        self.cbOpenFitInNew.Bind(wx.EVT_CHECKBOX, self.onCBOpenFitInNew)
        self.chPriceSystem.Bind(wx.EVT_CHOICE, self.onPriceSelection)
        self.cbShowShipBrowserTooltip.Bind(wx.EVT_CHECKBOX,
                                           self.onCBShowShipBrowserTooltip)
        self.intDelay.Bind(wx.lib.intctrl.EVT_INT, self.onMarketDelayChange)

        self.cbRackLabels.Enable(self.sFit.serviceFittingOptions["rackSlots"]
                                 or False)

        panel.SetSizer(mainSizer)
        panel.Layout()
Example #36
0
    def fetchPrices(cls, prices, fetchTimeout, validityOverride):
        """Fetch all prices passed to this method"""

        # Dictionary for our price objects
        priceMap = {}
        # Check all provided price objects, and add those we want to update to
        # dictionary
        for price in prices:
            if not price.isValid(validityOverride):
                priceMap[price.typeID] = price

        if not priceMap:
            return

        # Compose list of items we're going to request
        for typeID in tuple(priceMap):
            # Get item object
            item = db.getItem(typeID)
            # We're not going to request items only with market group, as our current market
            # sources do not provide any data for items not on the market
            if item is None:
                continue
            if not item.marketGroupID:
                priceMap[typeID].update(PriceStatus.notSupported)
                del priceMap[typeID]
                continue

        if not priceMap:
            return

        sFit = Fit.getInstance()

        if len(cls.sources.keys()) == 0:
            pyfalog.warn('No price source can be found')
            return

        # attempt to find user's selected price source, otherwise get first one
        sourceAll = list(cls.sources.keys())
        sourcePrimary = sFit.serviceFittingOptions["priceSource"] if sFit.serviceFittingOptions["priceSource"] in sourceAll else sourceAll[0]

        # Format: {source name: timeout weight}
        sources = {sourcePrimary: len(sourceAll)}
        for source in sourceAll:
            if source == sourcePrimary:
                continue
            sources[source] = min(sources.values()) - 1

        # Record timeouts as it will affect our final decision
        timedOutSources = {}

        remainingTime = fetchTimeout

        for source in sorted(sources, key=sources.get, reverse=True):
            timeBefore = timeit.default_timer()
            pyfalog.info('Trying {}'.format(source))
            timedOutSources[source] = False
            # Time we allocate for a source depends on source weight and remaining time
            sourceFetchTimeout = remainingTime * sources[source] / sum(sources.values())
            try:
                sourceCls = cls.sources.get(source)
                sourceCls(priceMap, cls.systemsList[sFit.serviceFittingOptions["priceSystem"]], sourceFetchTimeout)
            except TimeoutError:
                pyfalog.warning("Price fetch timeout for source {}".format(source))
                timedOutSources[source] = True
            except (KeyboardInterrupt, SystemExit):
                raise
            except Exception as e:
                pyfalog.warn('Failed to fetch prices from price source {}: {}'.format(source, e))
            # Sources remove price map items as they fetch info, if none remain then we're done
            if not priceMap:
                break
            timeAfter = timeit.default_timer()
            # Remove source so it doesn't affect time weights of sources we're going to use next
            del sources[source]
            remainingTime -= timeAfter - timeBefore
            # No time remaining (should not happen) - mark remaining sources as timeout
            if remainingTime <= 0:
                for source in sources:
                    timedOutSources[source] = True
                break


        # If we get to this point, then we've failed to get price with all our sources
        # If all sources failed due to timeouts, set one status
        if all(to is True for to in timedOutSources.values()):
            for typeID in priceMap.keys():
                priceMap[typeID].update(PriceStatus.fetchTimeout)
        # If some sources failed due to any other reason, then it's definitely not network
        # timeout and we just set another status
        else:
            for typeID in priceMap.keys():
                priceMap[typeID].update(PriceStatus.fetchFail)
Example #37
0
    def __getData(self, stuff):
        item = stuff.item
        if item is None:
            return "", None
        itemGroup = item.group.name
        itemCategory = item.category.name

        if itemGroup == "Ship Modifiers":
            return "", None
        elif itemGroup == "Booster":
            stuff.getModifiedItemAttr("boosterDuration")
            text = "{0} min".format(formatAmount(stuff.getModifiedItemAttr("boosterDuration") / 1000 / 60, 3, 0, 3))
            return text, "Booster Duration"
        elif itemGroup in ("Super Weapon", "Structure Doomsday Weapon"):
            volleyParams = stuff.getVolleyParameters(ignoreState=True)
            dmg = sum(dt.total for dt in volleyParams.values())
            duration = (max(volleyParams) - min(volleyParams)) / 1000
            if dmg <= 0:
                text = ""
                tooltip = ""
            elif duration > 0:
                text = "{} over {}s".format(
                    formatAmount(dmg, 3, 0, 6),
                    formatAmount((duration), 0, 0, 0))
                tooltip = "Raw damage done over time"
            else:
                text = "{} dmg".format(formatAmount(dmg, 3, 0, 6))
                tooltip = "Raw damage done"
            return text, tooltip

            pass
        elif itemGroup in ("Energy Weapon", "Hybrid Weapon", "Projectile Weapon", "Combat Drone", "Fighter Drone"):
            trackingSpeed = stuff.getModifiedItemAttr("trackingSpeed")
            optimalSig = stuff.getModifiedItemAttr("optimalSigRadius")
            if not trackingSpeed or not optimalSig:
                return "", None
            normalizedTracking = trackingSpeed * 40000 / optimalSig
            text = "{0}".format(formatAmount(normalizedTracking, 3, 0, 3))
            tooltip = "Tracking speed"
            return text, tooltip
        elif itemGroup == "Precursor Weapon":
            info = []
            trackingSpeed = stuff.getModifiedItemAttr("trackingSpeed")
            if trackingSpeed:
                text = "{0}".format(formatAmount(trackingSpeed, 3, 0, 3))
                tooltip = "tracking speed"
                info.append((text, tooltip))

            defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
            spoolTime = stuff.getSpoolData(spoolOptions=SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False))[1]
            if spoolTime:
                text = "{0}s".format(formatAmount(spoolTime, 3, 0, 3))
                tooltip = "spool up time"
                info.append((text, tooltip))
            if not info:
                return "", None
            text = ' | '.join(i[0] for i in info)
            tooltip = ' and '.join(i[1] for i in info).capitalize()
            return text, tooltip
        elif itemCategory == "Subsystem":
            slots = ("hi", "med", "low")
            info = []
            for slot in slots:
                n = int(stuff.getModifiedItemAttr("%sSlotModifier" % slot))
                if n > 0:
                    info.append("{0}{1}".format(n, slot[0].upper()))
            return "+ " + ", ".join(info), "Slot Modifiers"
        elif (
            itemGroup in ("Energy Neutralizer", "Structure Energy Neutralizer") or
            (itemGroup == "Structure Burst Projector" and "doomsdayAOENeut" in item.effects)
        ):
            neutAmount = stuff.getModifiedItemAttr("energyNeutralizerAmount")
            cycleParams = stuff.getCycleParameters()
            if cycleParams is None:
                return "", None
            cycleTime = cycleParams.averageTime
            if not neutAmount or not cycleTime:
                return "", None
            capPerSec = float(-neutAmount) * 1000 / cycleTime
            text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
            tooltip = "Energy neutralization per second"
            return text, tooltip
        elif itemGroup == "Energy Nosferatu":
            neutAmount = stuff.getModifiedItemAttr("powerTransferAmount")
            cycleParams = stuff.getCycleParameters()
            if cycleParams is None:
                return "", None
            cycleTime = cycleParams.averageTime
            if not neutAmount or not cycleTime:
                return "", None
            capPerSec = float(-neutAmount) * 1000 / cycleTime
            text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
            tooltip = "Energy neutralization per second"
            return text, tooltip
        elif itemGroup == "Salvager":
            chance = stuff.getModifiedItemAttr("accessDifficultyBonus")
            if not chance:
                return "", None
            text = "{0}%".format(formatAmount(chance, 3, 0, 3))
            tooltip = "Item retrieval chance"
            return text, tooltip
        elif itemGroup == "Data Miners":
            strength = stuff.getModifiedItemAttr("virusStrength")
            coherence = stuff.getModifiedItemAttr("virusCoherence")
            if not strength or not coherence:
                return "", None
            text = "{0} | {1}".format(formatAmount(strength, 3, 0, 3), formatAmount(coherence, 3, 0, 3))
            tooltip = "Virus strength and coherence"
            return text, tooltip
        elif itemGroup in ("Warp Scrambler", "Warp Core Stabilizer", "Structure Warp Scrambler"):
            scramStr = stuff.getModifiedItemAttr("warpScrambleStrength")
            if not scramStr:
                return "", None
            text = "{0}".format(formatAmount(-scramStr, 3, 0, 3, forceSign=True))
            tooltip = "Warp core strength modification"
            return text, tooltip
        elif (
            itemGroup in ("Stasis Web", "Stasis Webifying Drone", "Structure Stasis Webifier") or
            (itemGroup == "Structure Burst Projector" and "doomsdayAOEWeb" in item.effects)
        ):
            speedFactor = stuff.getModifiedItemAttr("speedFactor")
            if not speedFactor:
                return "", None
            text = "{0}%".format(formatAmount(speedFactor, 3, 0, 3))
            tooltip = "Speed reduction"
            return text, tooltip
        elif (
            itemGroup == "Target Painter" or
            (itemGroup == "Structure Disruption Battery" and "structureModuleEffectTargetPainter" in item.effects) or
            (itemGroup == "Structure Burst Projector" and "doomsdayAOEPaint" in item.effects)
        ):
            sigRadBonus = stuff.getModifiedItemAttr("signatureRadiusBonus")
            if not sigRadBonus:
                return "", None
            text = "{0}%".format(formatAmount(sigRadBonus, 3, 0, 3, forceSign=True))
            tooltip = "Signature radius increase"
            return text, tooltip
        elif (
            itemGroup == "Sensor Dampener" or
            (itemGroup == "Structure Disruption Battery" and "structureModuleEffectRemoteSensorDampener" in item.effects) or
            (itemGroup == "Structure Burst Projector" and "doomsdayAOEDamp" in item.effects)
        ):
            lockRangeBonus = stuff.getModifiedItemAttr("maxTargetRangeBonus")
            scanResBonus = stuff.getModifiedItemAttr("scanResolutionBonus")
            if lockRangeBonus is None or scanResBonus is None:
                return "", None
            display = 0
            for bonus in (lockRangeBonus, scanResBonus):
                if abs(bonus) > abs(display):
                    display = bonus
            if not display:
                return "", None
            text = "{0}%".format(formatAmount(display, 3, 0, 3, forceSign=True))
            ttEntries = []
            if display == lockRangeBonus:
                ttEntries.append("lock range")
            if display == scanResBonus:
                ttEntries.append("scan resolution")
            tooltip = "{0} dampening".format(formatList(ttEntries)).capitalize()
            return text, tooltip
        elif (
            itemGroup in ("Weapon Disruptor", "Structure Disruption Battery") or
            (itemGroup == "Structure Burst Projector" and "doomsdayAOETrack" in item.effects)
        ):
            # Weapon disruption now covers both tracking and guidance (missile) disruptors
            # First get the attributes for tracking disruptors
            optimalRangeBonus = stuff.getModifiedItemAttr("maxRangeBonus")
            falloffRangeBonus = stuff.getModifiedItemAttr("falloffBonus")
            trackingSpeedBonus = stuff.getModifiedItemAttr("trackingSpeedBonus")

            trackingDisruptorAttributes = {
                "optimal range": optimalRangeBonus,
                "falloff range": falloffRangeBonus,
                "tracking speed": trackingSpeedBonus}

            isTrackingDisruptor = any([x is not None and x != 0 for x in list(trackingDisruptorAttributes.values())])

            # Then get the attributes for guidance disruptors
            explosionVelocityBonus = stuff.getModifiedItemAttr("aoeVelocityBonus")
            explosionRadiusBonus = stuff.getModifiedItemAttr("aoeCloudSizeBonus")

            flightTimeBonus = stuff.getModifiedItemAttr("explosionDelayBonus")
            missileVelocityBonus = stuff.getModifiedItemAttr("missileVelocityBonus")

            guidanceDisruptorAttributes = {
                "explosion velocity": explosionVelocityBonus,
                "explosion radius": explosionRadiusBonus,
                "flight time": flightTimeBonus,
                "missile velocity": missileVelocityBonus}

            isGuidanceDisruptor = any([x is not None and x != 0 for x in list(guidanceDisruptorAttributes.values())])

            if not isTrackingDisruptor and not isGuidanceDisruptor:
                return "", None

            texts = []
            ttSegments = []

            for status, attributes in ((isTrackingDisruptor, trackingDisruptorAttributes), (isGuidanceDisruptor, guidanceDisruptorAttributes)):
                if not status:
                    continue
                display = max(list(attributes.values()), key=lambda x: abs(x))
                texts.append("{0}%".format(formatAmount(display, 3, 0, 3, forceSign=True)))
                ttEntries = []
                for attributeName, attributeValue in list(attributes.items()):
                    if abs(attributeValue) == abs(display):
                        ttEntries.append(attributeName)
                ttSegments.append("{0} disruption".format(formatList(ttEntries)).capitalize())
            return ' | '.join(texts), '\n'.join(ttSegments)
        elif itemGroup in (
            "Gyrostabilizer",
            "Magnetic Field Stabilizer",
            "Heat Sink",
            "Ballistic Control system",
            "Structure Weapon Upgrade",
            "Entropic Radiation Sink"
        ):
            attrMap = {
                "Gyrostabilizer": ("damageMultiplier", "speedMultiplier", "Projectile weapon"),
                "Magnetic Field Stabilizer": ("damageMultiplier", "speedMultiplier", "Hybrid weapon"),
                "Heat Sink": ("damageMultiplier", "speedMultiplier", "Energy weapon"),
                "Ballistic Control system": ("missileDamageMultiplierBonus", "speedMultiplier", "Missile"),
                "Structure Weapon Upgrade": ("missileDamageMultiplierBonus", "speedMultiplier", "Missile"),
                "Entropic Radiation Sink": ("damageMultiplier", "speedMultiplier", "Precursor weapon")}
            dmgAttr, rofAttr, weaponName = attrMap[itemGroup]
            dmg = stuff.getModifiedItemAttr(dmgAttr)
            rof = stuff.getModifiedItemAttr(rofAttr)
            if not dmg or not rof:
                return "", None
            texts = []
            tooltips = []
            cumulative = (dmg / rof - 1) * 100
            texts.append("{}%".format(formatAmount(cumulative, 3, 0, 3, forceSign=True)))
            tooltips.append("{} DPS boost".format(weaponName))
            droneDmg = stuff.getModifiedItemAttr("droneDamageBonus")
            if droneDmg:
                texts.append("{}%".format(formatAmount(droneDmg, 3, 0, 3, forceSign=True)))
                tooltips.append("drone DPS boost".format(weaponName))
            return ' | '.join(texts), ' and '.join(tooltips)
        elif itemGroup == "Drone Damage Modules":
            dmg = stuff.getModifiedItemAttr("droneDamageBonus")
            if not dmg:
                return
            text = "{}%".format(formatAmount(dmg, 3, 0, 3, forceSign=True))
            tooltip = "Drone DPS boost"
            return text, tooltip
        elif (
            itemGroup in ("ECM", "Burst Jammer", "Burst Projectors", "Structure ECM Battery") or
            (itemGroup == "Structure Burst Projector" and "doomsdayAOEECM" in item.effects)
        ):
            grav = stuff.getModifiedItemAttr("scanGravimetricStrengthBonus")
            ladar = stuff.getModifiedItemAttr("scanLadarStrengthBonus")
            radar = stuff.getModifiedItemAttr("scanRadarStrengthBonus")
            magnet = stuff.getModifiedItemAttr("scanMagnetometricStrengthBonus")
            displayMax = max(grav, ladar, radar, magnet)
            displayMin = min(grav, ladar, radar, magnet)
            if grav is None or ladar is None or radar is None or magnet is None or displayMax is None:
                return "", None

            if displayMax == displayMin or displayMin is None:
                text = "{0}".format(
                    formatAmount(displayMax, 3, 0, 3),
                )
            else:
                text = "{0} | {1}".format(
                    formatAmount(displayMax, 3, 0, 3),
                    formatAmount(displayMin, 3, 0, 3),
                )
            tooltip = "ECM Jammer Strength:\n{0} Gravimetric | {1} Ladar | {2} Magnetometric | {3} Radar".format(
                formatAmount(grav, 3, 0, 3),
                formatAmount(ladar, 3, 0, 3),
                formatAmount(magnet, 3, 0, 3),
                formatAmount(radar, 3, 0, 3),
            )
            return text, tooltip
        elif itemGroup in ("Remote Sensor Booster", "Sensor Booster", "Signal Amplifier"):
            scanResBonus = stuff.getModifiedItemAttr("scanResolutionBonus")
            lockRangeBonus = stuff.getModifiedItemAttr("maxTargetRangeBonus")
            gravBonus = stuff.getModifiedItemAttr("scanGravimetricStrengthPercent")
            if scanResBonus is None or lockRangeBonus is None or gravBonus is None:
                return "", None

            text = "{0}% | {1}% | {2}%".format(
                formatAmount(scanResBonus, 3, 0, 3),
                formatAmount(lockRangeBonus, 3, 0, 3),
                formatAmount(gravBonus, 3, 0, 3),
            )
            tooltip = "Applied bonuses:\n{0}% scan resolution | {1}% lock range | {2}% sensor strength".format(
                formatAmount(scanResBonus, 3, 0, 3),
                formatAmount(lockRangeBonus, 3, 0, 3),
                formatAmount(gravBonus, 3, 0, 3),
            )
            return text, tooltip
        elif itemGroup in ("Projected ECCM", "ECCM", "Sensor Backup Array"):
            grav = stuff.getModifiedItemAttr("scanGravimetricStrengthPercent")
            ladar = stuff.getModifiedItemAttr("scanLadarStrengthPercent")
            radar = stuff.getModifiedItemAttr("scanRadarStrengthPercent")
            magnet = stuff.getModifiedItemAttr("scanMagnetometricStrengthPercent")
            if grav is None or ladar is None or radar is None or magnet is None:
                return "", None
            display = max(grav, ladar, radar, magnet)
            if not display:
                return "", None
            text = "{0}%".format(formatAmount(display, 3, 0, 3, forceSign=True))
            ttEntries = []
            if display == grav:
                ttEntries.append("gravimetric")
            if display == ladar:
                ttEntries.append("ladar")
            if display == magnet:
                ttEntries.append("magnetometric")
            if display == radar:
                ttEntries.append("radar")
            plu = "" if len(ttEntries) == 1 else "s"
            tooltip = "{0} strength{1} bonus".format(formatList(ttEntries), plu).capitalize()
            return text, tooltip
        elif itemGroup == "Cloaking Device":
            recalibration = stuff.getModifiedItemAttr("cloakingTargetingDelay")
            if recalibration is None:
                return "", None
            text = "{0}s".format(formatAmount(float(recalibration) / 1000, 3, 0, 3))
            tooltip = "Sensor recalibration time"
            return text, tooltip
        elif itemGroup == "Remote Armor Repairer":
            rps = stuff.getRemoteReps(ignoreState=True).armor
            if not rps:
                return "", None
            text = "{0}/s".format(formatAmount(rps, 3, 0, 3, forceSign=True))
            tooltip = "Armor repaired per second"
            return text, tooltip
        elif itemGroup == "Mutadaptive Remote Armor Repairer":
            defaultSpoolValue = eos.config.settings['globalDefaultSpoolupPercentage']
            spoolOptDefault = SpoolOptions(SpoolType.SPOOL_SCALE, defaultSpoolValue, False)
            spoolOptPre = SpoolOptions(SpoolType.SPOOL_SCALE, 0, True)
            spoolOptFull = SpoolOptions(SpoolType.SPOOL_SCALE, 1, True)
            rps = stuff.getRemoteReps(spoolOptions=spoolOptDefault, ignoreState=True).armor
            rpsPre = stuff.getRemoteReps(spoolOptions=spoolOptPre, ignoreState=True).armor
            rpsFull = stuff.getRemoteReps(spoolOptions=spoolOptFull, ignoreState=True).armor
            if not rps:
                return "", None
            text = []
            tooltip = []
            text.append("{}/s".format(formatAmount(rps, 3, 0, 3, forceSign=True)))
            tooltip.append("Armor repaired per second")
            spoolTime = stuff.getSpoolData(spoolOptDefault)[1]
            if spoolTime:
                text.append("{}s".format(formatAmount(spoolTime, 3, 0, 3)))
                tooltip.append("spool up time")
            text = " | ".join(text)
            tooltip = " and ".join(tooltip)
            spoolTimePre = stuff.getSpoolData(spoolOptPre)[1]
            spoolTimeFull = stuff.getSpoolData(spoolOptFull)[1]
            if spoolTimePre != spoolTimeFull:
                tooltip = "{}\nSpool up: {}-{} over {}s".format(
                    tooltip,
                    formatAmount(rpsPre, 3, 0, 3),
                    formatAmount(rpsFull, 3, 0, 3),
                    formatAmount(spoolTimeFull - spoolTimePre, 3, 0, 3))
            return text, tooltip
        elif itemGroup == "Remote Shield Booster":
            rps = stuff.getRemoteReps(ignoreState=True).shield
            if not rps:
                return "", None
            text = "{0}/s".format(formatAmount(rps, 3, 0, 3, forceSign=True))
            tooltip = "Shield transferred per second"
            return text, tooltip
        elif itemGroup == "Remote Capacitor Transmitter":
            rps = stuff.getRemoteReps(ignoreState=True).capacitor
            if not rps:
                return "", None
            text = "{0}/s".format(formatAmount(rps, 3, 0, 3, forceSign=True))
            tooltip = "Energy transferred per second"
            return text, tooltip
        elif itemGroup == "Remote Hull Repairer":
            rps = stuff.getRemoteReps(ignoreState=True).hull
            if not rps:
                return "", None
            text = "{0}/s".format(formatAmount(rps, 3, 0, 3, forceSign=True))
            tooltip = "Structure repaired per second"
            return text, tooltip
        elif itemGroup == "Gang Coordinator":
            command = stuff.getModifiedItemAttr("commandBonus") or stuff.getModifiedItemAttr("commandBonusHidden")
            if not command:
                return "", None
            text = "{0}%".format(formatAmount(command, 3, 0, 3, forceSign=True))
            tooltip = "Gang bonus strength"
            return text, tooltip
        elif itemGroup == "Electronic Warfare Drone":
            sigRadBonus = stuff.getModifiedItemAttr("signatureRadiusBonus")
            lockRangeMult = stuff.getModifiedItemAttr("maxTargetRangeMultiplier")
            scanResMult = stuff.getModifiedItemAttr("scanResolutionMultiplier")
            falloffRangeMult = stuff.getModifiedItemAttr("fallofMultiplier")
            optimalRangeMult = stuff.getModifiedItemAttr("maxRangeMultiplier")
            trackingSpeedMult = stuff.getModifiedItemAttr("trackingSpeedMultiplier")
            grav = stuff.getModifiedItemAttr("scanGravimetricStrengthBonus")
            ladar = stuff.getModifiedItemAttr("scanLadarStrengthBonus")
            radar = stuff.getModifiedItemAttr("scanRadarStrengthBonus")
            magnet = stuff.getModifiedItemAttr("scanMagnetometricStrengthBonus")
            if sigRadBonus:
                text = "{0}%".format(formatAmount(sigRadBonus, 3, 0, 3, forceSign=True))
                tooltip = "Signature radius increase"
                return text, tooltip
            if lockRangeMult is not None and scanResMult is not None:
                lockRangeBonus = (lockRangeMult - 1) * 100
                scanResBonus = (scanResMult - 1) * 100
                display = 0
                for bonus in (lockRangeBonus, scanResBonus):
                    if abs(bonus) > abs(display):
                        display = bonus
                if not display:
                    return "", None
                text = "{0}%".format(formatAmount(display, 3, 0, 3, forceSign=True))
                ttEntries = []
                if display == lockRangeBonus:
                    ttEntries.append("lock range")
                if display == scanResBonus:
                    ttEntries.append("scan resolution")
                tooltip = "{0} dampening".format(formatList(ttEntries)).capitalize()
                return text, tooltip
            if falloffRangeMult is not None and optimalRangeMult is not None and trackingSpeedMult is not None:
                falloffRangeBonus = (falloffRangeMult - 1) * 100
                optimalRangeBonus = (optimalRangeMult - 1) * 100
                trackingSpeedBonus = (trackingSpeedMult - 1) * 100
                display = 0
                for bonus in (falloffRangeBonus, optimalRangeBonus, trackingSpeedBonus):
                    if abs(bonus) > abs(display):
                        display = bonus
                if not display:
                    return "", None
                text = "{0}%".format(formatAmount(display, 3, 0, 3), forceSign=True)
                ttEntries = []
                if display == optimalRangeBonus:
                    ttEntries.append("optimal range")
                if display == falloffRangeBonus:
                    ttEntries.append("falloff range")
                if display == trackingSpeedBonus:
                    ttEntries.append("tracking speed")
                tooltip = "{0} disruption".format(formatList(ttEntries)).capitalize()
                return text, tooltip
            if grav is not None and ladar is not None and radar is not None and magnet is not None:
                display = max(grav, ladar, radar, magnet)
                if not display:
                    return "", None
                text = "{0}".format(formatAmount(display, 3, 0, 3))
                ttEntries = []
                if display == grav:
                    ttEntries.append("gravimetric")
                if display == ladar:
                    ttEntries.append("ladar")
                if display == magnet:
                    ttEntries.append("magnetometric")
                if display == radar:
                    ttEntries.append("radar")
                plu = "" if len(ttEntries) == 1 else "s"
                tooltip = "{0} strength{1}".format(formatList(ttEntries), plu).capitalize()
                return text, tooltip
            else:
                return "", None
        elif itemGroup == "Fighter Bomber":
            optimalSig = stuff.getModifiedItemAttr("optimalSigRadius")
            if not optimalSig:
                return "", None
            text = "{0}m".format(formatAmount(optimalSig, 3, 0, 3))
            tooltip = "Optimal signature radius"
            return text, tooltip
        elif itemGroup in ("Frequency Mining Laser", "Strip Miner", "Mining Laser", "Gas Cloud Harvester", "Mining Drone"):
            miningAmount = stuff.getModifiedItemAttr("specialtyMiningAmount") or stuff.getModifiedItemAttr("miningAmount")
            cycleTime = getattr(stuff, 'cycleTime', stuff.getModifiedItemAttr("duration"))
            if not miningAmount or not cycleTime:
                return "", None
            minePerSec = (float(miningAmount) * 1000 / cycleTime)
            text = "{0} m3/s".format(formatAmount(minePerSec, 3, 0, 3))
            tooltip = "Mining Yield per second ({0} per hour)".format(formatAmount(minePerSec * 3600, 3, 0, 3))
            return text, tooltip
        elif itemGroup == "Logistic Drone":
            rpsData = stuff.getRemoteReps(ignoreState=True)
            rrType = None
            rps = None
            if rpsData.shield:
                rps = rpsData.shield
                rrType = 'Shield'
            elif rpsData.armor:
                rps = rpsData.armor
                rrType = 'Armor'
            elif rpsData.hull:
                rps = rpsData.hull
                rrType = 'Hull'
            if not rrType or not rps:
                return "", None
            text = "{}/s".format(formatAmount(rps, 3, 0, 3))
            tooltip = "{} HP repaired per second\n{} HP/s per drone".format(rrType, formatAmount(rps / stuff.amount, 3, 0, 3))
            return text, tooltip
        elif itemGroup == "Energy Neutralizer Drone":
            neutAmount = stuff.getModifiedItemAttr("energyNeutralizerAmount")
            cycleTime = stuff.getModifiedItemAttr("energyNeutralizerDuration")
            if not neutAmount or not cycleTime:
                return "", None
            capPerSec = float(-neutAmount) * 1000 / cycleTime
            text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
            tooltip = "Energy neutralization per second"
            return text, tooltip
        elif itemGroup in ("Micro Jump Drive", "Micro Jump Field Generators"):
            cycleTime = stuff.getModifiedItemAttr("duration") / 1000
            text = "{0}s".format(formatAmount(cycleTime, 3, 0, 3))
            tooltip = "Spoolup time"
            return text, tooltip
        elif itemGroup in ("Siege Module", "Cynosural Field Generator"):
            amt = stuff.getModifiedItemAttr("consumptionQuantity")
            if amt:
                typeID = stuff.getModifiedItemAttr("consumptionType")
                item = Market.getInstance().getItem(typeID)
                text = "{0} units".format(formatAmount(amt, 3, 0, 3))
                return text, item.name
            else:
                return "", None
        elif itemGroup in (
                "Ancillary Armor Repairer",
                "Ancillary Shield Booster",
                "Capacitor Booster",
                "Ancillary Remote Armor Repairer",
                "Ancillary Remote Shield Booster",
        ):
            if "Armor" in itemGroup or "Shield" in itemGroup:
                boosted_attribute = "HP"
                reload_time = item.getAttribute("reloadTime", 0) / 1000
            elif "Capacitor" in itemGroup:
                boosted_attribute = "Cap"
                reload_time = 10
            else:
                boosted_attribute = ""
                reload_time = 0

            cycles = max(stuff.numShots, 0)
            cycleTime = max(stuff.rawCycleTime, 0)

            # Get HP or boosted amount
            stuff_hp = max(stuff.hpBeforeReload, 0)
            armor_hp = stuff.getModifiedItemAttr("armorDamageAmount", 0)
            capacitor_hp = stuff.getModifiedChargeAttr("capacitorBonus", 0)
            shield_hp = stuff.getModifiedItemAttr("shieldBonus", 0)
            hp = max(stuff_hp, armor_hp * cycles, capacitor_hp * cycles, shield_hp * cycles, 0)

            if not hp or not cycleTime or not cycles:
                return "", None

            fit = Fit.getInstance().getFit(self.fittingView.getActiveFit())
            ehpTotal = fit.ehp
            hpTotal = fit.hp
            useEhp = self.mainFrame.statsPane.nameViewMap["resistancesViewFull"].showEffective
            tooltip = "{0} restored over duration using charges (plus reload)".format(boosted_attribute)

            if useEhp and boosted_attribute == "HP" and "Remote" not in itemGroup:
                if "Ancillary Armor Repairer" in itemGroup:
                    hpRatio = ehpTotal["armor"] / hpTotal["armor"]
                else:
                    hpRatio = ehpTotal["shield"] / hpTotal["shield"]
                tooltip = "E{0}".format(tooltip)
            else:
                hpRatio = 1

            if "Ancillary" in itemGroup and "Armor" in itemGroup:
                hpRatio *= stuff.getModifiedItemAttr("chargedArmorDamageMultiplier", 1)

            ehp = hp * hpRatio

            duration = cycles * cycleTime / 1000
            for number_of_cycles in {5, 10, 25}:
                tooltip = "{0}\n{1} charges lasts {2} seconds ({3} cycles)".format(
                    tooltip,
                    formatAmount(number_of_cycles * cycles, 3, 0, 3),
                    formatAmount((duration + reload_time) * number_of_cycles, 3, 0, 3),
                    formatAmount(number_of_cycles, 3, 0, 3)
                )
            text = "{0} / {1}s (+{2}s)".format(
                formatAmount(ehp, 3, 0, 9),
                formatAmount(duration, 3, 0, 3),
                formatAmount(reload_time, 3, 0, 3)
            )

            return text, tooltip
        elif itemGroup == "Armor Resistance Shift Hardener":
            itemArmorResistanceShiftHardenerEM = (1 - stuff.getModifiedItemAttr("armorEmDamageResonance")) * 100
            itemArmorResistanceShiftHardenerTherm = (1 - stuff.getModifiedItemAttr("armorThermalDamageResonance")) * 100
            itemArmorResistanceShiftHardenerKin = (1 - stuff.getModifiedItemAttr("armorKineticDamageResonance")) * 100
            itemArmorResistanceShiftHardenerExp = (1 - stuff.getModifiedItemAttr("armorExplosiveDamageResonance")) * 100

            text = "{0}% | {1}% | {2}% | {3}%".format(
                formatAmount(itemArmorResistanceShiftHardenerEM, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerTherm, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerKin, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerExp, 3, 0, 3),
            )
            tooltip = "Resistances Shifted to Damage Profile:\n{0}% EM | {1}% Therm | {2}% Kin | {3}% Exp".format(
                formatAmount(itemArmorResistanceShiftHardenerEM, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerTherm, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerKin, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerExp, 3, 0, 3),
            )
            return text, tooltip
        elif stuff.charge is not None:
            chargeGroup = stuff.charge.group.name
            if chargeGroup.endswith("Rocket") or chargeGroup.endswith("Missile") or chargeGroup.endswith("Torpedo"):
                cloudSize = stuff.getModifiedChargeAttr("aoeCloudSize")
                aoeVelocity = stuff.getModifiedChargeAttr("aoeVelocity")
                if not cloudSize or not aoeVelocity:
                    return "", None
                text = "{0}{1} | {2}{3}".format(formatAmount(cloudSize, 3, 0, 3), "m",
                                                formatAmount(aoeVelocity, 3, 0, 3), "m/s")
                tooltip = "Explosion radius and explosion velocity"
                return text, tooltip
            elif chargeGroup in ("Bomb", "Structure Guided Bomb"):
                cloudSize = stuff.getModifiedChargeAttr("aoeCloudSize")
                if not cloudSize:
                    return "", None
                text = "{0}{1}".format(formatAmount(cloudSize, 3, 0, 3), "m")
                tooltip = "Explosion radius"
                return text, tooltip
            elif chargeGroup in ("Scanner Probe",):
                scanStr = stuff.getModifiedChargeAttr("baseSensorStrength")
                baseRange = stuff.getModifiedChargeAttr("baseScanRange")
                if not scanStr or not baseRange:
                    return "", None
                strTwoAu = scanStr / (2.0 / baseRange)
                text = "{0}".format(formatAmount(strTwoAu, 3, 0, 3))
                tooltip = "Scan strength with 2 AU scan range"
                return text, tooltip
            else:
                return "", None
        else:
            return "", None
Example #38
0
    def _merge(self, src, dst):
        sFit = Fit.getInstance()
        fitID = self.mainFrame.getActiveFit()

        if sFit.mergeDrones(fitID, self.drones[src], self.drones[dst]):
            wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
Example #39
0
    def refresh(self, stuff):
        """
        Displays fitting

        Sends data to d.Display.refresh where the rows and columns are set up, then does a
        bit of post-processing (colors)
        """
        self.Freeze()
        d.Display.refresh(self, stuff)

        sFit = Fit.getInstance()
        fit = sFit.getFit(self.activeFitID)
        slotMap = {}

        # test for too many modules (happens with t3s / CCP change in slot layout)
        for slot in [e.value for e in FittingSlot]:
            slotMap[slot] = fit.getSlotsFree(slot) < 0

        for i, mod in enumerate(self.mods):
            self.SetItemBackgroundColour(i, self.GetBackgroundColour())

            #  only consider changing color if we're dealing with a Module
            if isinstance(mod, Module):
                hasRestrictionOverriden = False
                if not mod.isEmpty:
                    fits = mod.fits(fit, False)
                    hasRestrictionOverriden = getattr(mod,
                                                      'restrictionOverridden',
                                                      None)
                    # If module had broken fitting restrictions but now doesn't,
                    # ensure it is now valid, and remove restrictionOverridden
                    # variable. More in #1519
                    if not fit.ignoreRestrictions and hasRestrictionOverriden:
                        clean = False
                        if fits:
                            if not mod.hardpoint:
                                clean = True
                            elif fit.getHardpointsFree(mod.hardpoint) >= 0:
                                clean = True
                        if clean:
                            del mod.restrictionOverridden
                            hasRestrictionOverriden = not hasRestrictionOverriden

                if slotMap[
                        mod.
                        slot] or hasRestrictionOverriden:  # Color too many modules as red
                    self.SetItemBackgroundColour(i, wx.Colour(204, 51, 51))
                elif sFit.serviceFittingOptions[
                        "colorFitBySlot"]:  # Color by slot it enabled
                    self.SetItemBackgroundColour(i, self.slotColour(mod.slot))

            # Set rack face to bold
            if isinstance(mod, Rack) and \
                    sFit.serviceFittingOptions["rackSlots"] and \
                    sFit.serviceFittingOptions["rackLabels"]:
                self.font.SetWeight(wx.FONTWEIGHT_BOLD)
                self.SetItemFont(i, self.font)
            else:
                self.font.SetWeight(wx.FONTWEIGHT_NORMAL)
                self.SetItemFont(i, self.font)

        self.Thaw()
        self.itemCount = self.GetItemCount()
Example #40
0
    def __getData(self, stuff):
        item = stuff.item
        if item is None:
            return "", None
        itemGroup = item.group.name
        itemCategory = item.category.name

        if itemGroup == "Ship Modifiers":
            return "", None
        elif itemGroup in ("Energy Weapon", "Hybrid Weapon",
                           "Projectile Weapon", "Combat Drone",
                           "Fighter Drone"):
            trackingSpeed = stuff.getModifiedItemAttr("trackingSpeed")
            if not trackingSpeed:
                return "", None
            text = "{0}".format(formatAmount(trackingSpeed, 3, 0, 3))
            tooltip = "Tracking speed"
            return text, tooltip
        elif itemCategory == "Subsystem":
            slots = ("hi", "med", "low")
            info = []
            for slot in slots:
                n = int(stuff.getModifiedItemAttr("%sSlotModifier" % slot))
                if n > 0:
                    info.append("{0}{1}".format(n, slot[0].upper()))
            return "+ " + ", ".join(info), "Slot Modifiers"
        elif itemGroup == "Energy Neutralizer":
            neutAmount = stuff.getModifiedItemAttr("energyNeutralizerAmount")
            cycleTime = stuff.cycleTime
            if not neutAmount or not cycleTime:
                return "", None
            capPerSec = float(-neutAmount) * 1000 / cycleTime
            text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
            tooltip = "Energy neutralization per second"
            return text, tooltip
        elif itemGroup == "Energy Nosferatu":
            neutAmount = stuff.getModifiedItemAttr("powerTransferAmount")
            cycleTime = stuff.cycleTime
            if not neutAmount or not cycleTime:
                return "", None
            capPerSec = float(-neutAmount) * 1000 / cycleTime
            text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
            tooltip = "Energy neutralization per second"
            return text, tooltip
        elif itemGroup == "Salvager":
            chance = stuff.getModifiedItemAttr("accessDifficultyBonus")
            if not chance:
                return "", None
            text = "{0}%".format(formatAmount(chance, 3, 0, 3))
            tooltip = "Item retrieval chance"
            return text, tooltip
        elif itemGroup == "Data Miners":
            strength = stuff.getModifiedItemAttr("virusStrength")
            coherence = stuff.getModifiedItemAttr("virusCoherence")
            if not strength or not coherence:
                return "", None
            text = "{0} | {1}".format(formatAmount(strength, 3, 0, 3),
                                      formatAmount(coherence, 3, 0, 3))
            tooltip = "Virus strength and coherence"
            return text, tooltip
        elif itemGroup in ("Warp Scrambler", "Warp Core Stabilizer"):
            scramStr = stuff.getModifiedItemAttr("warpScrambleStrength")
            if not scramStr:
                return "", None
            text = "{0}".format(
                formatAmount(-scramStr, 3, 0, 3, forceSign=True))
            tooltip = "Warp core strength modification"
            return text, tooltip
        elif itemGroup in ("Stasis Web", "Stasis Webifying Drone"):
            speedFactor = stuff.getModifiedItemAttr("speedFactor")
            if not speedFactor:
                return "", None
            text = "{0}%".format(formatAmount(speedFactor, 3, 0, 3))
            tooltip = "Speed reduction"
            return text, tooltip
        elif itemGroup == "Target Painter":
            sigRadBonus = stuff.getModifiedItemAttr("signatureRadiusBonus")
            if not sigRadBonus:
                return "", None
            text = "{0}%".format(
                formatAmount(sigRadBonus, 3, 0, 3, forceSign=True))
            tooltip = "Signature radius increase"
            return text, tooltip
        elif itemGroup == "Sensor Dampener":
            lockRangeBonus = stuff.getModifiedItemAttr("maxTargetRangeBonus")
            scanResBonus = stuff.getModifiedItemAttr("scanResolutionBonus")
            if lockRangeBonus is None or scanResBonus is None:
                return "", None
            display = 0
            for bonus in (lockRangeBonus, scanResBonus):
                if abs(bonus) > abs(display):
                    display = bonus
            if not display:
                return "", None
            text = "{0}%".format(formatAmount(display, 3, 0, 3,
                                              forceSign=True))
            ttEntries = []
            if display == lockRangeBonus:
                ttEntries.append("lock range")
            if display == scanResBonus:
                ttEntries.append("scan resolution")
            tooltip = "{0} dampening".format(
                formatList(ttEntries)).capitalize()
            return text, tooltip
        elif itemGroup == "Weapon Disruptor":
            # Weapon disruption now covers both tracking and guidance (missile) disruptors
            # First get the attributes for tracking disruptors
            optimalRangeBonus = stuff.getModifiedItemAttr("maxRangeBonus")
            falloffRangeBonus = stuff.getModifiedItemAttr("falloffBonus")
            trackingSpeedBonus = stuff.getModifiedItemAttr(
                "trackingSpeedBonus")

            trackingDisruptorAttributes = {
                "optimal range": optimalRangeBonus,
                "falloff range": falloffRangeBonus,
                "tracking speed": trackingSpeedBonus
            }

            isTrackingDisruptor = any(
                map(lambda x: x is not None and x != 0,
                    trackingDisruptorAttributes.values()))

            # Then get the attributes for guidance disruptors
            explosionVelocityBonus = stuff.getModifiedItemAttr(
                "aoeVelocityBonus")
            explosionRadiusBonus = stuff.getModifiedItemAttr(
                "aoeCloudSizeBonus")

            flightTimeBonus = stuff.getModifiedItemAttr("explosionDelayBonus")
            missileVelocityBonus = stuff.getModifiedItemAttr(
                "missileVelocityBonus")

            guidanceDisruptorAttributes = {
                "explosion velocity": explosionVelocityBonus,
                "explosion radius": explosionRadiusBonus,
                "flight time": flightTimeBonus,
                "missile velocity": missileVelocityBonus
            }

            isGuidanceDisruptor = any(
                map(lambda x: x is not None and x != 0,
                    guidanceDisruptorAttributes.values()))

            if isTrackingDisruptor:
                attributes = trackingDisruptorAttributes
            elif isGuidanceDisruptor:
                attributes = guidanceDisruptorAttributes
            else:
                return "", None

            display = max(attributes.values(), key=lambda x: abs(x))

            text = "{0}%".format(formatAmount(display, 3, 0, 3,
                                              forceSign=True))

            ttEntries = []
            for attributeName, attributeValue in attributes.items():
                if attributeValue == display:
                    ttEntries.append(attributeName)

            tooltip = "{0} disruption".format(
                formatList(ttEntries)).capitalize()
            return text, tooltip
        elif itemGroup in ("ECM", "Burst Jammer", "Burst Projectors"):
            grav = stuff.getModifiedItemAttr("scanGravimetricStrengthBonus")
            ladar = stuff.getModifiedItemAttr("scanLadarStrengthBonus")
            radar = stuff.getModifiedItemAttr("scanRadarStrengthBonus")
            magnet = stuff.getModifiedItemAttr(
                "scanMagnetometricStrengthBonus")
            displayMax = max(grav, ladar, radar, magnet)
            displayMin = min(grav, ladar, radar, magnet)
            if grav is None or ladar is None or radar is None or magnet is None or displayMax is None:
                return "", None

            if displayMax == displayMin or displayMin is None:
                text = "{0}".format(formatAmount(displayMax, 3, 0, 3), )
            else:
                text = "{0} | {1}".format(
                    formatAmount(displayMax, 3, 0, 3),
                    formatAmount(displayMin, 3, 0, 3),
                )
            tooltip = "ECM Jammer Strength:\n{0} Gravimetric | {1} Ladar | {2} Magnetometric | {3} Radar".format(
                formatAmount(grav, 3, 0, 3),
                formatAmount(ladar, 3, 0, 3),
                formatAmount(magnet, 3, 0, 3),
                formatAmount(radar, 3, 0, 3),
            )
            return text, tooltip
        elif itemGroup in ("Remote Sensor Booster", "Sensor Booster",
                           "Signal Amplifier"):
            scanResBonus = stuff.getModifiedItemAttr("scanResolutionBonus")
            lockRangeBonus = stuff.getModifiedItemAttr("maxTargetRangeBonus")
            gravBonus = stuff.getModifiedItemAttr(
                "scanGravimetricStrengthPercent")
            if scanResBonus is None or lockRangeBonus is None or gravBonus is None:
                return "", None

            text = "{0}% | {1}% | {2}%".format(
                formatAmount(scanResBonus, 3, 0, 3),
                formatAmount(lockRangeBonus, 3, 0, 3),
                formatAmount(gravBonus, 3, 0, 3),
            )
            tooltip = "Applied bonuses:\n{0}% scan resolution | {1}% lock range | {2}% sensor strength".format(
                formatAmount(scanResBonus, 3, 0, 3),
                formatAmount(lockRangeBonus, 3, 0, 3),
                formatAmount(gravBonus, 3, 0, 3),
            )
            return text, tooltip
        elif itemGroup in ("Projected ECCM", "ECCM", "Sensor Backup Array"):
            grav = stuff.getModifiedItemAttr("scanGravimetricStrengthPercent")
            ladar = stuff.getModifiedItemAttr("scanLadarStrengthPercent")
            radar = stuff.getModifiedItemAttr("scanRadarStrengthPercent")
            magnet = stuff.getModifiedItemAttr(
                "scanMagnetometricStrengthPercent")
            if grav is None or ladar is None or radar is None or magnet is None:
                return "", None
            display = max(grav, ladar, radar, magnet)
            if not display:
                return "", None
            text = "{0}%".format(formatAmount(display, 3, 0, 3,
                                              forceSign=True))
            ttEntries = []
            if display == grav:
                ttEntries.append("gravimetric")
            if display == ladar:
                ttEntries.append("ladar")
            if display == magnet:
                ttEntries.append("magnetometric")
            if display == radar:
                ttEntries.append("radar")
            plu = "" if len(ttEntries) == 1 else "s"
            tooltip = "{0} strength{1} bonus".format(formatList(ttEntries),
                                                     plu).capitalize()
            return text, tooltip
        elif itemGroup == "Cloaking Device":
            recalibration = stuff.getModifiedItemAttr("cloakingTargetingDelay")
            if recalibration is None:
                return "", None
            text = "{0}s".format(
                formatAmount(float(recalibration) / 1000, 3, 0, 3))
            tooltip = "Sensor recalibration time"
            return text, tooltip
        elif itemGroup == "Remote Armor Repairer":
            repAmount = stuff.getModifiedItemAttr("armorDamageAmount")
            cycleTime = stuff.getModifiedItemAttr("duration")
            if not repAmount or not cycleTime:
                return "", None
            repPerSec = float(repAmount) * 1000 / cycleTime
            text = "{0}/s".format(
                formatAmount(repPerSec, 3, 0, 3, forceSign=True))
            tooltip = "Armor repaired per second"
            return text, tooltip
        elif itemGroup == "Remote Shield Booster":
            repAmount = stuff.getModifiedItemAttr("shieldBonus")
            cycleTime = stuff.cycleTime
            if not repAmount or not cycleTime:
                return "", None
            repPerSec = float(repAmount) * 1000 / cycleTime
            text = "{0}/s".format(
                formatAmount(repPerSec, 3, 0, 3, forceSign=True))
            tooltip = "Shield transferred per second"
            return text, tooltip
        elif itemGroup == "Remote Capacitor Transmitter":
            repAmount = stuff.getModifiedItemAttr("powerTransferAmount")
            cycleTime = stuff.cycleTime
            if not repAmount or not cycleTime:
                return "", None
            repPerSec = float(repAmount) * 1000 / cycleTime
            text = "{0}/s".format(
                formatAmount(repPerSec, 3, 0, 3, forceSign=True))
            tooltip = "Energy transferred per second"
            return text, tooltip
        elif itemGroup == "Remote Hull Repairer":
            repAmount = stuff.getModifiedItemAttr("structureDamageAmount")
            cycleTime = stuff.cycleTime
            if not repAmount or not cycleTime:
                return "", None
            repPerSec = float(repAmount) * 1000 / cycleTime
            text = "{0}/s".format(
                formatAmount(repPerSec, 3, 0, 3, forceSign=True))
            tooltip = "Structure repaired per second"
            return text, tooltip
        elif itemGroup == "Gang Coordinator":
            command = stuff.getModifiedItemAttr(
                "commandBonus") or stuff.getModifiedItemAttr(
                    "commandBonusHidden")
            if not command:
                return "", None
            text = "{0}%".format(formatAmount(command, 3, 0, 3,
                                              forceSign=True))
            tooltip = "Gang bonus strength"
            return text, tooltip
        elif itemGroup == "Electronic Warfare Drone":
            sigRadBonus = stuff.getModifiedItemAttr("signatureRadiusBonus")
            lockRangeMult = stuff.getModifiedItemAttr(
                "maxTargetRangeMultiplier")
            scanResMult = stuff.getModifiedItemAttr("scanResolutionMultiplier")
            falloffRangeMult = stuff.getModifiedItemAttr("fallofMultiplier")
            optimalRangeMult = stuff.getModifiedItemAttr("maxRangeMultiplier")
            trackingSpeedMult = stuff.getModifiedItemAttr(
                "trackingSpeedMultiplier")
            grav = stuff.getModifiedItemAttr("scanGravimetricStrengthBonus")
            ladar = stuff.getModifiedItemAttr("scanLadarStrengthBonus")
            radar = stuff.getModifiedItemAttr("scanRadarStrengthBonus")
            magnet = stuff.getModifiedItemAttr(
                "scanMagnetometricStrengthBonus")
            if sigRadBonus:
                text = "{0}%".format(
                    formatAmount(sigRadBonus, 3, 0, 3, forceSign=True))
                tooltip = "Signature radius increase"
                return text, tooltip
            if lockRangeMult is not None and scanResMult is not None:
                lockRangeBonus = (lockRangeMult - 1) * 100
                scanResBonus = (scanResMult - 1) * 100
                display = 0
                for bonus in (lockRangeBonus, scanResBonus):
                    if abs(bonus) > abs(display):
                        display = bonus
                if not display:
                    return "", None
                text = "{0}%".format(
                    formatAmount(display, 3, 0, 3, forceSign=True))
                ttEntries = []
                if display == lockRangeBonus:
                    ttEntries.append("lock range")
                if display == scanResBonus:
                    ttEntries.append("scan resolution")
                tooltip = "{0} dampening".format(
                    formatList(ttEntries)).capitalize()
                return text, tooltip
            if falloffRangeMult is not None and optimalRangeMult is not None and trackingSpeedMult is not None:
                falloffRangeBonus = (falloffRangeMult - 1) * 100
                optimalRangeBonus = (optimalRangeMult - 1) * 100
                trackingSpeedBonus = (trackingSpeedMult - 1) * 100
                display = 0
                for bonus in (falloffRangeBonus, optimalRangeBonus,
                              trackingSpeedBonus):
                    if abs(bonus) > abs(display):
                        display = bonus
                if not display:
                    return "", None
                text = "{0}%".format(formatAmount(display, 3, 0, 3),
                                     forceSign=True)
                ttEntries = []
                if display == optimalRangeBonus:
                    ttEntries.append("optimal range")
                if display == falloffRangeBonus:
                    ttEntries.append("falloff range")
                if display == trackingSpeedBonus:
                    ttEntries.append("tracking speed")
                tooltip = "{0} disruption".format(
                    formatList(ttEntries)).capitalize()
                return text, tooltip
            if grav is not None and ladar is not None and radar is not None and magnet is not None:
                display = max(grav, ladar, radar, magnet)
                if not display:
                    return "", None
                text = "{0}".format(formatAmount(display, 3, 0, 3))
                ttEntries = []
                if display == grav:
                    ttEntries.append("gravimetric")
                if display == ladar:
                    ttEntries.append("ladar")
                if display == magnet:
                    ttEntries.append("magnetometric")
                if display == radar:
                    ttEntries.append("radar")
                plu = "" if len(ttEntries) == 1 else "s"
                tooltip = "{0} strength{1}".format(formatList(ttEntries),
                                                   plu).capitalize()
                return text, tooltip
            else:
                return "", None
        elif itemGroup == "Fighter Bomber":
            optimalSig = stuff.getModifiedItemAttr("optimalSigRadius")
            if not optimalSig:
                return "", None
            text = "{0}m".format(formatAmount(optimalSig, 3, 0, 3))
            tooltip = "Optimal signature radius"
            return text, tooltip
        elif itemGroup in ("Frequency Mining Laser", "Strip Miner",
                           "Mining Laser", "Gas Cloud Harvester",
                           "Mining Drone"):
            miningAmount = stuff.getModifiedItemAttr(
                "specialtyMiningAmount") or stuff.getModifiedItemAttr(
                    "miningAmount")
            cycleTime = getattr(stuff, 'cycleTime',
                                stuff.getModifiedItemAttr("duration"))
            if not miningAmount or not cycleTime:
                return "", None
            minePerSec = (float(miningAmount) * 1000 / cycleTime)
            text = "{0} m3/s".format(formatAmount(minePerSec, 3, 0, 3))
            tooltip = "Mining Yield per second ({0} per hour)".format(
                formatAmount(minePerSec * 3600, 3, 0, 3))
            return text, tooltip
        elif itemGroup == "Logistic Drone":
            armorAmount = stuff.getModifiedItemAttr("armorDamageAmount")
            shieldAmount = stuff.getModifiedItemAttr("shieldBonus")
            hullAmount = stuff.getModifiedItemAttr("structureDamageAmount")
            repAmount = armorAmount or shieldAmount or hullAmount
            cycleTime = stuff.getModifiedItemAttr("duration")
            if not repAmount or not cycleTime:
                return "", None
            repPerSec = float(repAmount) * 1000 / cycleTime
            text = "{0}/s".format(formatAmount(repPerSec, 3, 0, 3))
            ttEntries = []
            if hullAmount is not None and repAmount == hullAmount:
                ttEntries.append("structure")
            if armorAmount is not None and repAmount == armorAmount:
                ttEntries.append("armor")
            if shieldAmount is not None and repAmount == shieldAmount:
                ttEntries.append("shield")
            tooltip = "{0} repaired per second".format(
                formatList(ttEntries)).capitalize()
            return text, tooltip
        elif itemGroup == "Energy Neutralizer Drone":
            neutAmount = stuff.getModifiedItemAttr("energyNeutralizerAmount")
            cycleTime = stuff.getModifiedItemAttr("energyNeutralizerDuration")
            if not neutAmount or not cycleTime:
                return "", None
            capPerSec = float(-neutAmount) * 1000 / cycleTime
            text = "{0}/s".format(formatAmount(capPerSec, 3, 0, 3))
            tooltip = "Energy neutralization per second"
            return text, tooltip
        elif itemGroup == "Micro Jump Drive":
            cycleTime = stuff.getModifiedItemAttr("duration") / 1000
            text = "{0}s".format(cycleTime)
            tooltip = "Spoolup time"
            return text, tooltip
        elif itemGroup in ("Siege Module", "Cynosural Field"):
            amt = stuff.getModifiedItemAttr("consumptionQuantity")
            if amt:
                typeID = stuff.getModifiedItemAttr("consumptionType")
                item = Market.getInstance().getItem(typeID)
                text = "{0} units".format(formatAmount(amt, 3, 0, 3))
                return text, item.name
            else:
                return "", None
        elif itemGroup in (
                "Ancillary Armor Repairer",
                "Ancillary Shield Booster",
                "Capacitor Booster",
                "Ancillary Remote Armor Repairer",
                "Ancillary Remote Shield Booster",
        ):
            if "Armor" in itemGroup or "Shield" in itemGroup:
                boosted_attribute = "HP"
                reload_time = item.getAttribute("reloadTime", 0) / 1000
            elif "Capacitor" in itemGroup:
                boosted_attribute = "Cap"
                reload_time = 10
            else:
                boosted_attribute = ""
                reload_time = 0

            cycles = max(stuff.numShots, 0)
            cycleTime = max(stuff.rawCycleTime, 0)

            # Get HP or boosted amount
            stuff_hp = max(stuff.hpBeforeReload, 0)
            armor_hp = stuff.getModifiedItemAttr("armorDamageAmount", 0)
            capacitor_hp = stuff.getModifiedChargeAttr("capacitorBonus", 0)
            shield_hp = stuff.getModifiedItemAttr("shieldBonus", 0)
            hp = max(stuff_hp, armor_hp * cycles, capacitor_hp * cycles,
                     shield_hp * cycles, 0)

            if not hp or not cycleTime or not cycles:
                return "", None

            fit = Fit.getInstance().getFit(self.mainFrame.getActiveFit())
            ehpTotal = fit.ehp
            hpTotal = fit.hp
            useEhp = self.mainFrame.statsPane.nameViewMap[
                "resistancesViewFull"].showEffective
            tooltip = "{0} restored over duration using charges (plus reload)".format(
                boosted_attribute)

            if useEhp and boosted_attribute == "HP" and "Remote" not in itemGroup:
                if "Ancillary Armor Repairer" in itemGroup:
                    hpRatio = ehpTotal["armor"] / hpTotal["armor"]
                else:
                    hpRatio = ehpTotal["shield"] / hpTotal["shield"]
                tooltip = "E{0}".format(tooltip)
            else:
                hpRatio = 1

            if "Ancillary" in itemGroup and "Armor" in itemGroup:
                hpRatio *= stuff.getModifiedItemAttr(
                    "chargedArmorDamageMultiplier", 1)

            ehp = hp * hpRatio

            duration = cycles * cycleTime / 1000
            for number_of_cycles in {5, 10, 25}:
                tooltip = "{0}\n{1} charges lasts {2} seconds ({3} cycles)".format(
                    tooltip, formatAmount(number_of_cycles * cycles, 3, 0, 3),
                    formatAmount((duration + reload_time) * number_of_cycles,
                                 3, 0, 3),
                    formatAmount(number_of_cycles, 3, 0, 3))
            text = "{0} / {1}s (+{2}s)".format(
                formatAmount(ehp, 3, 0, 9), formatAmount(duration, 3, 0, 3),
                formatAmount(reload_time, 3, 0, 3))

            return text, tooltip
        elif itemGroup == "Armor Resistance Shift Hardener":
            itemArmorResistanceShiftHardenerEM = (
                1 - stuff.getModifiedItemAttr("armorEmDamageResonance")) * 100
            itemArmorResistanceShiftHardenerTherm = (
                1 -
                stuff.getModifiedItemAttr("armorThermalDamageResonance")) * 100
            itemArmorResistanceShiftHardenerKin = (
                1 -
                stuff.getModifiedItemAttr("armorKineticDamageResonance")) * 100
            itemArmorResistanceShiftHardenerExp = (
                1 - stuff.getModifiedItemAttr("armorExplosiveDamageResonance")
            ) * 100

            text = "{0}% | {1}% | {2}% | {3}%".format(
                formatAmount(itemArmorResistanceShiftHardenerEM, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerTherm, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerKin, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerExp, 3, 0, 3),
            )
            tooltip = "Resistances Shifted to Damage Profile:\n{0}% EM | {1}% Therm | {2}% Kin | {3}% Exp".format(
                formatAmount(itemArmorResistanceShiftHardenerEM, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerTherm, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerKin, 3, 0, 3),
                formatAmount(itemArmorResistanceShiftHardenerExp, 3, 0, 3),
            )
            return text, tooltip
        elif stuff.charge is not None:
            chargeGroup = stuff.charge.group.name
            if chargeGroup in ("Rocket", "Advanced Rocket", "Light Missile",
                               "Advanced Light Missile", "FoF Light Missile",
                               "Heavy Assault Missile",
                               "Advanced Heavy Assault Missile",
                               "Heavy Missile", "Advanced Heavy Missile",
                               "FoF Heavy Missile", "Torpedo",
                               "Advanced Torpedo", "Cruise Missile",
                               "Advanced Cruise Missile", "FoF Cruise Missile",
                               "XL Torpedo", "XL Cruise Missile"):
                cloudSize = stuff.getModifiedChargeAttr("aoeCloudSize")
                aoeVelocity = stuff.getModifiedChargeAttr("aoeVelocity")
                if not cloudSize or not aoeVelocity:
                    return "", None
                text = "{0}{1} | {2}{3}".format(
                    formatAmount(cloudSize, 3, 0, 3), "m",
                    formatAmount(aoeVelocity, 3, 0, 3), "m/s")
                tooltip = "Explosion radius and explosion velocity"
                return text, tooltip
            elif chargeGroup == "Bomb":
                cloudSize = stuff.getModifiedChargeAttr("aoeCloudSize")
                if not cloudSize:
                    return "", None
                text = "{0}{1}".format(formatAmount(cloudSize, 3, 0, 3), "m")
                tooltip = "Explosion radius"
                return text, tooltip
            elif chargeGroup in ("Scanner Probe", ):
                scanStr = stuff.getModifiedChargeAttr("baseSensorStrength")
                baseRange = stuff.getModifiedChargeAttr("baseScanRange")
                if not scanStr or not baseRange:
                    return "", None
                strTwoAu = scanStr / (2.0 / baseRange)
                text = "{0}".format(formatAmount(strTwoAu, 3, 0, 3))
                tooltip = "Scan strength with 2 AU scan range"
                return text, tooltip
            else:
                return "", None
        else:
            return "", None
Example #41
0
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 "&lt;" is Ignored
    # fit['description'] = "<pyfa:%d />" % 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)
Example #42
0
 def copyFit(self, event=None):
     sFit = Fit.getInstance()
     fitID = sFit.copyFit(self.fitID)
     self.shipBrowser.fitIDMustEditName = fitID
     wx.PostEvent(self.shipBrowser, Stage3Selected(shipID=self.shipID))
     wx.PostEvent(self.mainFrame, FitSelected(fitID=fitID))
Example #43
0
def importESI(str_):

    sMkt = Market.getInstance()
    fitobj = Fit()
    refobj = json.loads(str_)
    items = refobj['items']
    # "<" and ">" is replace to "&lt;", "&gt;" 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
Example #44
0
def importKillmail(
        killmail,
        fitNameFunction=lambda killmail, fit: fit.ship.item.name
) -> Fit or None:
    """Parses a single killmail from the ESI API. The argument is an already parsed JSON"""
    sMkt = Market.getInstance()
    fit = Fit()
    victim = killmail["victim"]
    items = victim["items"]

    try:
        ship = victim["ship_type_id"]
        try:
            fit.ship = Ship(sMkt.getItem(ship))
        except ValueError:
            fit.ship = Citadel(sMkt.getItem(ship))
    except:
        pyfalog.warning("Caught exception in importZKillboard")
        return None

    fit.name = fitNameFunction(killmail, fit)

    items.sort(key=lambda k: k["flag"])

    moduleList = []
    moduleByFlag = {}
    chargeByFlag = {}
    for module in items:
        try:
            item = sMkt.getItem(module["item_type_id"], eager="group.category")
            if not item.published:
                continue
            flag = module["flag"]
            if flag == INV_FLAG_DRONEBAY:
                d = Drone(item)
                d.amount = module.get("quantity_destroyed", 0) + module.get(
                    "quantity_dropped", 0)
                fit.drones.append(d)
            elif flag == INV_FLAG_CARGOBAY:
                c = fit.cargo.findFirst(item)
                if c is None:
                    c = Cargo(item)
                    fit.cargo.append(c)
                c.amount += module.get("quantity_destroyed", 0) + module.get(
                    "quantity_dropped", 0)

            elif flag == INV_FLAG_FIGHTER:
                fighter = Fighter(item)
                fit.fighters.append(fighter)
            else:
                try:
                    m = Module(item)
                    moduleByFlag[flag] = m
                # When item can't be added to any slot (unknown item or just charge), ignore it
                except ValueError:
                    chargeByFlag[flag] = item
                    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(fit):
                        fit.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(fit)

    for flag in moduleByFlag.keys():
        module = moduleByFlag[flag]
        charge = chargeByFlag.get(flag, None)
        if (not charge is None
            ) and module.isValidCharge(charge) and module.charge is None:
            module.charge = charge

    for module in moduleList:
        if module.fits(fit):
            fit.modules.append(module)

    km_time = datetime.strptime(killmail["killmail_time"],
                                "%Y-%m-%dT%H:%M:%SZ")
    fit.timestamp = time.mktime(km_time.timetuple())
    fit.modified = fit.created = km_time

    return saveImportedFit(fit)
Example #45
0
 def Do(self):
     fit = Fit.getInstance().getFit(self.fitID)
     srcMod = fit.modules[self.srcModPosition]
     if srcMod.isEmpty:
         return False
     srcModItemID = srcMod.itemID
     dstCargo = next(
         (c for c in fit.cargo if c.itemID == self.dstCargoItemID), None)
     success = False
     # Attempt to swap if we're moving our module onto a module in the cargo hold
     if not self.copy and dstCargo is not None and dstCargo.item.isModule:
         if srcModItemID == self.dstCargoItemID:
             return False
         srcModSlot = srcMod.slot
         newModInfo = ModuleInfo.fromModule(srcMod, unmutate=True)
         newModInfo.itemID = self.dstCargoItemID
         srcModChargeItemID = srcMod.chargeID
         srcModChargeAmount = srcMod.numCharges
         commands = []
         commands.append(
             CalcRemoveCargoCommand(fitID=self.fitID,
                                    cargoInfo=CargoInfo(
                                        itemID=self.dstCargoItemID,
                                        amount=1)))
         commands.append(
             CalcAddCargoCommand(
                 fitID=self.fitID,
                 # We cannot put mutated items to cargo, so use unmutated item ID
                 cargoInfo=CargoInfo(itemID=ModuleInfo.fromModule(
                     srcMod, unmutate=True).itemID,
                                     amount=1)))
         cmdReplace = CalcReplaceLocalModuleCommand(
             fitID=self.fitID,
             position=self.srcModPosition,
             newModInfo=newModInfo,
             unloadInvalidCharges=True)
         commands.append(cmdReplace)
         # Submit batch now because we need to have updated info on fit to keep going
         success = self.internalHistory.submitBatch(*commands)
         newMod = fit.modules[self.srcModPosition]
         # Process charge changes if module is moved to proper slot
         if newMod.slot == srcModSlot:
             # If we had to unload charge, add it to cargo
             if cmdReplace.unloadedCharge and srcModChargeItemID is not None:
                 cmdAddCargoCharge = CalcAddCargoCommand(
                     fitID=self.fitID,
                     cargoInfo=CargoInfo(itemID=srcModChargeItemID,
                                         amount=srcModChargeAmount))
                 success = self.internalHistory.submit(cmdAddCargoCharge)
             # If we did not unload charge and there still was a charge, see if amount differs and process it
             elif not cmdReplace.unloadedCharge and srcModChargeItemID is not None:
                 # How many extra charges do we need to take from cargo
                 extraChargeAmount = newMod.numCharges - srcModChargeAmount
                 if extraChargeAmount > 0:
                     cmdRemoveCargoExtraCharge = CalcRemoveCargoCommand(
                         fitID=self.fitID,
                         cargoInfo=CargoInfo(itemID=srcModChargeItemID,
                                             amount=extraChargeAmount))
                     # Do not check if operation was successful or not, we're okay if we have no such
                     # charges in cargo
                     self.internalHistory.submit(cmdRemoveCargoExtraCharge)
                 elif extraChargeAmount < 0:
                     cmdAddCargoExtraCharge = CalcAddCargoCommand(
                         fitID=self.fitID,
                         cargoInfo=CargoInfo(itemID=srcModChargeItemID,
                                             amount=abs(extraChargeAmount)))
                     success = self.internalHistory.submit(
                         cmdAddCargoExtraCharge)
             if success:
                 # Store info to properly send events later
                 self.removedModItemID = srcModItemID
                 self.addedModItemID = self.dstCargoItemID
         # If drag happened to module which cannot be fit into current slot - consider it as failure
         else:
             success = False
         # And in case of any failures, cancel everything to try to do move instead
         if not success:
             self.internalHistory.undoAll()
     # Just dump module and its charges into cargo when copying or moving to cargo
     if not success:
         commands = []
         commands.append(
             CalcAddCargoCommand(fitID=self.fitID,
                                 cargoInfo=CargoInfo(
                                     itemID=ModuleInfo.fromModule(
                                         srcMod, unmutate=True).itemID,
                                     amount=1)))
         if srcMod.chargeID is not None:
             commands.append(
                 CalcAddCargoCommand(fitID=self.fitID,
                                     cargoInfo=CargoInfo(
                                         itemID=srcMod.chargeID,
                                         amount=srcMod.numCharges)))
         if not self.copy:
             commands.append(
                 CalcRemoveLocalModulesCommand(
                     fitID=self.fitID, positions=[self.srcModPosition]))
         success = self.internalHistory.submitBatch(*commands)
     eos.db.flush()
     sFit = Fit.getInstance()
     sFit.recalc(self.fitID)
     self.savedRemovedDummies = sFit.fill(self.fitID)
     eos.db.commit()
     events = []
     if self.removedModItemID is not None:
         events.append(
             GE.FitChanged(fitID=self.fitID,
                           action='moddel',
                           typeID=self.removedModItemID))
     if self.addedModItemID is not None:
         events.append(
             GE.FitChanged(fitID=self.fitID,
                           action='modadd',
                           typeID=self.addedModItemID))
     if not events:
         events.append(GE.FitChanged(fitID=self.fitID))
     for event in events:
         wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), event)
     return success
Example #46
0
 def OnFitRemoved(self, event):
     event.Skip()
     AddCommandFit.populateFits(event)
     fitID = self.mainFrame.getActiveFit()
     fit = Fit.getInstance().getFit(fitID)
     self.refreshContents(fit)
Example #47
0
    def handleModule(self, event):
        item = self.moduleLookup.get(event.Id, None)
        if item is None:
            event.Skip()
            return

        sFit = Fit.getInstance()
        fitID = self.mainFrame.getActiveFit()
        fit = sFit.getFit(fitID)

        for selected_item in self.selection:
            if isinstance(selected_item, Module):
                pos = fit.modules.index(selected_item)
                sFit.changeModule(fitID, pos, item.ID)

            elif isinstance(selected_item, Drone):
                drone_count = None

                for idx, drone_stack in enumerate(fit.drones):
                    if drone_stack is selected_item:
                        drone_count = drone_stack.amount
                        sFit.removeDrone(fitID, idx, drone_count, False)
                        break

                if drone_count:
                    sFit.addDrone(fitID, item.ID, drone_count, True)

            elif isinstance(selected_item, Fighter):
                fighter_count = None

                for idx, fighter_stack in enumerate(fit.fighters):
                    # Right now fighters always will have max stack size.
                    # Including this for future improvement, so if adjustable
                    # fighter stacks get added we're ready for it.
                    if fighter_stack is selected_item:
                        if fighter_stack.amount > 0:
                            fighter_count = fighter_stack.amount
                        elif fighter_stack.amount == -1:
                            fighter_count = fighter_stack.amountActive
                        else:
                            fighter_count.amount = 0

                        sFit.removeFighter(fitID, idx, False)
                        break

                sFit.addFighter(fitID, item.ID, True)

            elif isinstance(selected_item, Booster):
                for idx, booster_stack in enumerate(fit.boosters):
                    if booster_stack is selected_item:
                        sFit.removeBooster(fitID, idx, False)
                        sFit.addBooster(fitID, item.ID, True)
                        break

            elif isinstance(selected_item, Implant):
                for idx, implant_stack in enumerate(fit.implants):
                    if implant_stack is selected_item:
                        sFit.removeImplant(fitID, idx, False)
                        sFit.addImplant(fitID, item.ID, True)
                        break

        wx.PostEvent(self.mainFrame, GE.FitChanged(fitID=fitID))
    def populatePanel(self, panel):
        self.mainFrame = gui.mainFrame.MainFrame.getInstance()
        self.sFit = Fit.getInstance()

        helpCursor = wx.Cursor(wx.CURSOR_QUESTION_ARROW)
        mainSizer = wx.BoxSizer(wx.VERTICAL)

        self.stTitle = wx.StaticText(panel, wx.ID_ANY, "Market && Prices",
                                     wx.DefaultPosition, wx.DefaultSize, 0)
        self.stTitle.Wrap(-1)
        self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))

        mainSizer.Add(self.stTitle, 0, wx.ALL, 5)

        self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY,
                                           wx.DefaultPosition, wx.DefaultSize,
                                           wx.LI_HORIZONTAL)
        mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)

        delayTimer = wx.BoxSizer(wx.HORIZONTAL)
        self.stMarketDelay = wx.StaticText(panel, wx.ID_ANY,
                                           "Market Search Delay (ms):",
                                           wx.DefaultPosition, wx.DefaultSize,
                                           0)
        self.stMarketDelay.Wrap(-1)
        self.stMarketDelay.SetCursor(helpCursor)
        self.stMarketDelay.SetToolTip(
            wx.ToolTip(
                'The delay between a keystroke and the market search. Can help reduce lag when typing fast in the market search box.'
            ))
        delayTimer.Add(self.stMarketDelay, 0,
                       wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        self.intDelay = IntCtrl(panel, max=1000, limited=True)
        delayTimer.Add(self.intDelay, 0, wx.ALL, 5)
        mainSizer.Add(delayTimer, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 10)
        self.intDelay.SetValue(
            self.sFit.serviceFittingOptions["marketSearchDelay"])
        self.intDelay.Bind(wx.lib.intctrl.EVT_INT, self.onMarketDelayChange)

        self.cbMarketShortcuts = wx.CheckBox(panel, wx.ID_ANY,
                                             "Show market shortcuts",
                                             wx.DefaultPosition,
                                             wx.DefaultSize, 0)
        mainSizer.Add(self.cbMarketShortcuts, 0, wx.EXPAND | wx.TOP | wx.RIGHT,
                      10)
        self.cbMarketShortcuts.SetValue(
            self.sFit.serviceFittingOptions["showMarketShortcuts"] or False)
        self.cbMarketShortcuts.Bind(wx.EVT_CHECKBOX, self.onCBShowShortcuts)

        priceSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.stDefaultSystem = wx.StaticText(panel, wx.ID_ANY,
                                             "Default Market Prices:",
                                             wx.DefaultPosition,
                                             wx.DefaultSize, 0)
        self.stDefaultSystem.Wrap(-1)
        priceSizer.Add(self.stDefaultSystem, 0,
                       wx.ALL | wx.ALIGN_CENTER_VERTICAL, 5)
        self.stDefaultSystem.SetCursor(helpCursor)
        self.stDefaultSystem.SetToolTip(
            wx.ToolTip(
                'The source you choose will be tried first, but subsequent sources will be used if the preferred source fails. '
                'The system you choose will also be tried first, and if no data is available, global price will be used.'
            ))
        self.chPriceSource = wx.Choice(panel,
                                       choices=sorted(Price.sources.keys()))
        self.chPriceSystem = wx.Choice(panel,
                                       choices=list(Price.systemsList.keys()))
        priceSizer.Add(self.chPriceSource, 1, wx.ALL | wx.EXPAND, 5)
        priceSizer.Add(self.chPriceSystem, 1, wx.ALL | wx.EXPAND, 5)
        mainSizer.Add(priceSizer, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 10)
        self.chPriceSource.SetStringSelection(
            self.sFit.serviceFittingOptions["priceSource"])
        self.chPriceSource.Bind(wx.EVT_CHOICE, self.onPricesSourceSelection)
        self.chPriceSystem.SetStringSelection(
            self.sFit.serviceFittingOptions["priceSystem"])
        self.chPriceSystem.Bind(wx.EVT_CHOICE, self.onPriceSelection)

        self.tbTotalPriceBox = wx.StaticBoxSizer(wx.VERTICAL, panel,
                                                 "Total Price Includes")
        self.tbTotalPriceDrones = wx.CheckBox(panel, -1, "Drones",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 1)
        self.tbTotalPriceDrones.SetValue(self.priceSettings.get("drones"))
        self.tbTotalPriceDrones.Bind(wx.EVT_CHECKBOX,
                                     self.OnTotalPriceDroneChange)
        self.tbTotalPriceBox.Add(self.tbTotalPriceDrones, 0,
                                 wx.LEFT | wx.RIGHT | wx.TOP, 5)
        self.tbTotalPriceCargo = wx.CheckBox(panel, -1, "Cargo",
                                             wx.DefaultPosition,
                                             wx.DefaultSize, 1)
        self.tbTotalPriceCargo.SetValue(self.priceSettings.get("cargo"))
        self.tbTotalPriceCargo.Bind(wx.EVT_CHECKBOX,
                                    self.OnTotalPriceCargoChange)
        self.tbTotalPriceBox.Add(self.tbTotalPriceCargo, 0, wx.LEFT | wx.RIGHT,
                                 5)
        self.tbTotalPriceCharacter = wx.CheckBox(panel, -1,
                                                 "Implants && Boosters",
                                                 wx.DefaultPosition,
                                                 wx.DefaultSize, 1)
        self.tbTotalPriceCharacter.SetValue(
            self.priceSettings.get("character"))
        self.tbTotalPriceCharacter.Bind(wx.EVT_CHECKBOX,
                                        self.OnTotalPriceCharacterChange)
        self.tbTotalPriceBox.Add(self.tbTotalPriceCharacter, 0,
                                 wx.LEFT | wx.RIGHT | wx.BOTTOM, 5)
        mainSizer.Add(self.tbTotalPriceBox, 0, wx.EXPAND | wx.TOP | wx.RIGHT,
                      10)

        self.rbMarketSearch = wx.RadioBox(
            panel, -1, "Market Search && Recent Items", wx.DefaultPosition,
            wx.DefaultSize, [
                "No changes to meta buttons",
                "Enable all meta buttons for a duration of search / recents",
                "Enable all meta buttons"
            ], 1, wx.RA_SPECIFY_COLS)
        self.rbMarketSearch.SetSelection(
            self.priceSettings.get('marketMGSearchMode'))
        mainSizer.Add(self.rbMarketSearch, 0, wx.RIGHT | wx.TOP | wx.EXPAND,
                      10)
        self.rbMarketSearch.Bind(wx.EVT_RADIOBOX, self.OnMarketSearchChange)

        self.rbMarketEmpty = wx.RadioBox(
            panel, -1, "Market Group Selection", wx.DefaultPosition,
            wx.DefaultSize,
            ["No changes to meta buttons", "Enable all meta buttons"], 1,
            wx.RA_SPECIFY_COLS)
        self.rbMarketEmpty.SetSelection(
            self.priceSettings.get('marketMGMarketSelectMode'))
        mainSizer.Add(self.rbMarketEmpty, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 10)
        self.rbMarketEmpty.Bind(wx.EVT_RADIOBOX,
                                self.OnMarketGroupSelectionChange)

        self.rbMarketEmpty = wx.RadioBox(
            panel, -1, "Empty Market View", wx.DefaultPosition, wx.DefaultSize,
            [
                "No changes to meta buttons",
                "Enable leftmost available meta button",
                "Enable all available meta buttons"
            ], 1, wx.RA_SPECIFY_COLS)
        self.rbMarketEmpty.SetSelection(
            self.priceSettings.get('marketMGEmptyMode'))
        mainSizer.Add(self.rbMarketEmpty, 0, wx.EXPAND | wx.TOP | wx.RIGHT, 10)
        self.rbMarketEmpty.Bind(wx.EVT_RADIOBOX, self.OnMarketEmptyChange)

        self.rbMarketJump = wx.RadioBox(
            panel, -1, "Item Market Group Jump", wx.DefaultPosition,
            wx.DefaultSize, [
                "No changes to meta buttons", "Enable item's meta button",
                "Enable item's meta button, disable others",
                "Enable all meta buttons"
            ], 1, wx.RA_SPECIFY_COLS)
        self.rbMarketJump.SetSelection(
            self.priceSettings.get('marketMGJumpMode'))
        mainSizer.Add(self.rbMarketJump, 0,
                      wx.EXPAND | wx.TOP | wx.RIGHT | wx.BOTTOM, 10)
        self.rbMarketJump.Bind(wx.EVT_RADIOBOX, self.OnMarketJumpChange)

        panel.SetSizer(mainSizer)
        panel.Layout()
Example #49
0
 def getCommandForFit(self, fitID) -> wx.CommandProcessor:
     return Fit.getCommandProcessor(fitID)
    def populatePanel(self, panel):
        self.mainFrame = gui.mainFrame.MainFrame.getInstance()
        self.dirtySettings = False
        self.openFitsSettings = SettingsProvider.getInstance().getSettings(
            "pyfaPrevOpenFits", {
                "enabled": False,
                "pyfaOpenFits": []
            })

        mainSizer = wx.BoxSizer(wx.VERTICAL)

        self.stTitle = wx.StaticText(panel, wx.ID_ANY, self.title,
                                     wx.DefaultPosition, wx.DefaultSize, 0)
        self.stTitle.Wrap(-1)
        self.stTitle.SetFont(wx.Font(12, 70, 90, 90, False, wx.EmptyString))

        helpCursor = wx.Cursor(wx.CURSOR_QUESTION_ARROW)
        mainSizer.Add(self.stTitle, 0, wx.ALL, 5)

        self.m_staticline1 = wx.StaticLine(panel, wx.ID_ANY,
                                           wx.DefaultPosition, wx.DefaultSize,
                                           wx.LI_HORIZONTAL)
        mainSizer.Add(self.m_staticline1, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)

        self.cbGlobalChar = wx.CheckBox(panel, wx.ID_ANY,
                                        "Use global character",
                                        wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbGlobalChar, 0, wx.ALL | wx.EXPAND, 5)

        self.cbDefaultCharImplants = wx.CheckBox(
            panel, wx.ID_ANY, "Use character implants by default for new fits",
            wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbDefaultCharImplants, 0, wx.ALL | wx.EXPAND, 5)

        self.cbGlobalDmgPattern = wx.CheckBox(panel, wx.ID_ANY,
                                              "Use global damage pattern",
                                              wx.DefaultPosition,
                                              wx.DefaultSize, 0)
        mainSizer.Add(self.cbGlobalDmgPattern, 0, wx.ALL | wx.EXPAND, 5)

        self.cbCompactSkills = wx.CheckBox(panel, wx.ID_ANY,
                                           "Compact skills needed tooltip",
                                           wx.DefaultPosition, wx.DefaultSize,
                                           0)
        mainSizer.Add(self.cbCompactSkills, 0, wx.ALL | wx.EXPAND, 5)

        self.cbFitColorSlots = wx.CheckBox(panel, wx.ID_ANY,
                                           "Color fitting view by slot",
                                           wx.DefaultPosition, wx.DefaultSize,
                                           0)
        mainSizer.Add(self.cbFitColorSlots, 0, wx.ALL | wx.EXPAND, 5)

        self.cbReopenFits = wx.CheckBox(panel, wx.ID_ANY,
                                        "Reopen previous fits on startup",
                                        wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbReopenFits, 0, wx.ALL | wx.EXPAND, 5)

        self.cbRackSlots = wx.CheckBox(panel, wx.ID_ANY, "Separate Racks",
                                       wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbRackSlots, 0, wx.ALL | wx.EXPAND, 5)

        labelSizer = wx.BoxSizer(wx.VERTICAL)
        self.cbRackLabels = wx.CheckBox(panel, wx.ID_ANY, "Show Rack Labels",
                                        wx.DefaultPosition, wx.DefaultSize, 0)
        labelSizer.Add(self.cbRackLabels, 0, wx.ALL | wx.EXPAND, 5)
        mainSizer.Add(labelSizer, 0, wx.LEFT | wx.EXPAND, 30)

        self.cbShowTooltip = wx.CheckBox(panel, wx.ID_ANY,
                                         "Show fitting tab tooltips",
                                         wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbShowTooltip, 0, wx.ALL | wx.EXPAND, 5)

        self.cbGaugeAnimation = wx.CheckBox(panel, wx.ID_ANY, "Animate gauges",
                                            wx.DefaultPosition, wx.DefaultSize,
                                            0)
        mainSizer.Add(self.cbGaugeAnimation, 0, wx.ALL | wx.EXPAND, 5)

        self.cbOpenFitInNew = wx.CheckBox(
            panel, wx.ID_ANY, "Open fittings in a new page by default",
            wx.DefaultPosition, wx.DefaultSize, 0)
        mainSizer.Add(self.cbOpenFitInNew, 0, wx.ALL | wx.EXPAND, 5)

        self.cbShowShipBrowserTooltip = wx.CheckBox(
            panel, wx.ID_ANY, "Show ship browser tooltip", wx.DefaultPosition,
            wx.DefaultSize, 0)
        mainSizer.Add(self.cbShowShipBrowserTooltip, 0, wx.ALL | wx.EXPAND, 5)

        self.cbReloadAll = wx.CheckBox(
            panel, wx.ID_ANY, "Change charge in all modules of the same type",
            wx.DefaultPosition, wx.DefaultSize, 0)
        if "wxGTK" not in wx.PlatformInfo:
            self.cbReloadAll.SetCursor(helpCursor)
        self.cbReloadAll.SetToolTip(
            wx.ToolTip(
                'When disabled, reloads charges just in selected modules. Action can be reversed by holding Ctrl or Alt key while changing charge.'
            ))
        mainSizer.Add(self.cbReloadAll, 0, wx.ALL | wx.EXPAND, 5)

        self.sFit = Fit.getInstance()

        self.cbGlobalChar.SetValue(
            self.sFit.serviceFittingOptions["useGlobalCharacter"])
        self.cbDefaultCharImplants.SetValue(
            self.sFit.serviceFittingOptions["useCharacterImplantsByDefault"])
        self.cbGlobalDmgPattern.SetValue(
            self.sFit.serviceFittingOptions["useGlobalDamagePattern"])
        self.cbFitColorSlots.SetValue(
            self.sFit.serviceFittingOptions["colorFitBySlot"] or False)
        self.cbRackSlots.SetValue(self.sFit.serviceFittingOptions["rackSlots"]
                                  or False)
        self.cbRackLabels.SetValue(
            self.sFit.serviceFittingOptions["rackLabels"] or False)
        self.cbCompactSkills.SetValue(
            self.sFit.serviceFittingOptions["compactSkills"] or False)
        self.cbReopenFits.SetValue(self.openFitsSettings["enabled"])
        self.cbShowTooltip.SetValue(
            self.sFit.serviceFittingOptions["showTooltip"] or False)
        self.cbGaugeAnimation.SetValue(
            self.sFit.serviceFittingOptions["enableGaugeAnimation"])
        self.cbOpenFitInNew.SetValue(
            self.sFit.serviceFittingOptions["openFitInNew"])
        self.cbShowShipBrowserTooltip.SetValue(
            self.sFit.serviceFittingOptions["showShipBrowserTooltip"])
        self.cbReloadAll.SetValue(
            self.sFit.serviceFittingOptions["ammoChangeAll"])

        self.cbGlobalChar.Bind(wx.EVT_CHECKBOX, self.OnCBGlobalCharStateChange)
        self.cbDefaultCharImplants.Bind(
            wx.EVT_CHECKBOX, self.OnCBDefaultCharImplantsStateChange)
        self.cbGlobalDmgPattern.Bind(wx.EVT_CHECKBOX,
                                     self.OnCBGlobalDmgPatternStateChange)
        self.cbFitColorSlots.Bind(wx.EVT_CHECKBOX, self.onCBGlobalColorBySlot)
        self.cbRackSlots.Bind(wx.EVT_CHECKBOX, self.onCBGlobalRackSlots)
        self.cbRackLabels.Bind(wx.EVT_CHECKBOX, self.onCBGlobalRackLabels)
        self.cbCompactSkills.Bind(wx.EVT_CHECKBOX, self.onCBCompactSkills)
        self.cbReopenFits.Bind(wx.EVT_CHECKBOX, self.onCBReopenFits)
        self.cbShowTooltip.Bind(wx.EVT_CHECKBOX, self.onCBShowTooltip)
        self.cbGaugeAnimation.Bind(wx.EVT_CHECKBOX, self.onCBGaugeAnimation)
        self.cbOpenFitInNew.Bind(wx.EVT_CHECKBOX, self.onCBOpenFitInNew)
        self.cbShowShipBrowserTooltip.Bind(wx.EVT_CHECKBOX,
                                           self.onCBShowShipBrowserTooltip)
        self.cbReloadAll.Bind(wx.EVT_CHECKBOX, self.onCBReloadAll)

        self.cbRackLabels.Enable(self.sFit.serviceFittingOptions["rackSlots"]
                                 or False)

        panel.SetSizer(mainSizer)
        panel.Layout()
Example #51
0
 def Undo(self):
     success = self.internalHistory.undoAll()
     Fit.getInstance().recalc(self.fitID)
     wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitID=self.fitID))
     return success
Example #52
0
 def command(self) -> wx.CommandProcessor:
     return Fit.getCommandProcessor(self.getActiveFit())
Example #53
0
 def toggleEffective(self, event):
     event.Skip()
     sFit = Fit.getInstance()
     self.refreshPanel(sFit.getFit(self.mainFrame.getActiveFit()))
Example #54
0
    def activate(self, callingWindow, fullContext, mainItem, i):
        fitID = self.mainFrame.getActiveFit()
        srcContext = fullContext[0]
        if isinstance(mainItem, es_Fit):
            try:
                value = mainItem.getProjectionInfo(fitID).amount
            except AttributeError:
                return
        else:
            value = mainItem.amount

        limits = (0, 20) if isinstance(mainItem, es_Fit) else None
        with AmountChanger(self.mainFrame, value, limits) as dlg:
            if dlg.ShowModal() == wx.ID_OK:

                if dlg.input.GetLineText(0).strip() == '':
                    return

                sFit = Fit.getInstance()
                fit = sFit.getFit(fitID)
                cleanInput = int(
                    float(
                        re.sub(r'[^0-9.]', '',
                               dlg.input.GetLineText(0).strip())))

                if isinstance(mainItem, es_Cargo):
                    self.mainFrame.command.Submit(
                        cmd.GuiChangeCargoAmountCommand(fitID=fitID,
                                                        itemID=mainItem.itemID,
                                                        amount=cleanInput))
                elif isinstance(mainItem, Drone):
                    if srcContext == "projectedDrone":
                        self.mainFrame.command.Submit(
                            cmd.GuiChangeProjectedDroneAmountCommand(
                                fitID=fitID,
                                itemID=mainItem.itemID,
                                amount=cleanInput))
                    else:
                        if mainItem in fit.drones:
                            position = fit.drones.index(mainItem)
                            self.mainFrame.command.Submit(
                                cmd.GuiChangeLocalDroneAmountCommand(
                                    fitID=fitID,
                                    position=position,
                                    amount=cleanInput))
                elif isinstance(mainItem, es_Fit):
                    self.mainFrame.command.Submit(
                        cmd.GuiChangeProjectedFitAmountCommand(
                            fitID=fitID,
                            projectedFitID=mainItem.ID,
                            amount=cleanInput))
                elif isinstance(mainItem, es_Fighter):
                    if srcContext == "projectedFighter":
                        if mainItem in fit.projectedFighters:
                            position = fit.projectedFighters.index(mainItem)
                            self.mainFrame.command.Submit(
                                cmd.GuiChangeProjectedFighterAmountCommand(
                                    fitID=fitID,
                                    position=position,
                                    amount=cleanInput))
                    else:
                        if mainItem in fit.fighters:
                            position = fit.fighters.index(mainItem)
                            self.mainFrame.command.Submit(
                                cmd.GuiChangeLocalFighterAmountCommand(
                                    fitID=fitID,
                                    position=position,
                                    amount=cleanInput))
Example #55
0
    def click(self, event):
        """
        Handle click event on modules.

        This is only useful for the State column. If multiple items are selected,
        and we have clicked the State column, iterate through the selections and
        change State
        """

        clickedRow, _, col = self.HitTestSubItem(event.Position)

        # only do State column and ignore invalid rows
        if clickedRow != -1 and clickedRow not in self.blanks and col == self.getColIndex(
                State):
            selectedRows = []
            currentRow = self.GetFirstSelected()

            while currentRow != -1 and clickedRow not in self.blanks:
                selectedRows.append(currentRow)
                currentRow = self.GetNextSelected(currentRow)

            if clickedRow not in selectedRows:
                try:
                    selectedMods = [self.mods[clickedRow]]
                except IndexError:
                    return
            else:
                selectedMods = self.getSelectedMods()

            click = "ctrl" if event.GetModifiers(
            ) == wx.MOD_CONTROL or event.middleIsDown else "right" if event.GetButton(
            ) == 3 else "left"

            try:
                mainMod = self.mods[clickedRow]
            except IndexError:
                return
            if mainMod.isEmpty:
                return
            fitID = self.mainFrame.getActiveFit()
            fit = Fit.getInstance().getFit(fitID)
            if mainMod not in fit.modules:
                return
            mainPosition = fit.modules.index(mainMod)
            if event.GetModifiers() == wx.MOD_ALT:
                positions = getSimilarModPositions(fit.modules, mainMod)
            else:
                positions = []
                for position, mod in enumerate(fit.modules):
                    if mod in selectedMods:
                        positions.append(position)
            self.mainFrame.command.Submit(
                cmd.GuiChangeLocalModuleStatesCommand(
                    fitID=fitID,
                    mainPosition=mainPosition,
                    positions=positions,
                    click=click))

            # update state tooltip
            tooltip = self.activeColumns[col].getToolTip(self.mods[clickedRow])
            if tooltip:
                self.SetToolTip(tooltip)

        else:
            event.Skip()
Example #56
0
    def fetchPrices(cls, prices):
        """Fetch all prices passed to this method"""

        # Dictionary for our price objects
        priceMap = {}
        # Check all provided price objects, and add invalid ones to dictionary
        for price in prices:
            if not price.isValid:
                priceMap[price.typeID] = price

        if len(priceMap) == 0:
            return

        # Set of items which are still to be requested from this service
        toRequest = set()

        # Compose list of items we're going to request
        for typeID in priceMap:
            # Get item object
            item = db.getItem(typeID)
            # We're not going to request items only with market group, as eve-central
            # doesn't provide any data for items not on the market
            if item is not None and item.marketGroupID:
                toRequest.add(typeID)

        # Do not waste our time if all items are not on the market
        if len(toRequest) == 0:
            return

        sFit = Fit.getInstance()

        if len(cls.sources.keys()) == 0:
            pyfalog.warn('No price source can be found')
            return

        # attempt to find user's selected price source, otherwise get first one
        sourcesToTry = list(cls.sources.keys())
        curr = sFit.serviceFittingOptions["priceSource"] if sFit.serviceFittingOptions["priceSource"] in sourcesToTry else sourcesToTry[0]

        while len(sourcesToTry) > 0:
            sourcesToTry.remove(curr)
            try:
                sourceCls = cls.sources.get(curr)
                sourceCls(toRequest, cls.systemsList[sFit.serviceFittingOptions["priceSystem"]], priceMap)
                break
                # If getting or processing data returned any errors
            except TimeoutError:
                # Timeout error deserves special treatment
                pyfalog.warning("Price fetch timout")
                for typeID in priceMap.keys():
                    priceobj = priceMap[typeID]
                    priceobj.time = time.time() + TIMEOUT
                    priceobj.failed = True

                    del priceMap[typeID]
            except Exception as ex:
                # something happened, try another source
                pyfalog.warn('Failed to fetch prices from price source {}: {}'.format(curr, ex, sourcesToTry[0]))
                if len(sourcesToTry) > 0:
                    pyfalog.warn('Trying {}'.format(sourcesToTry[0]))
                    curr = sourcesToTry[0]

        # if we get to this point, then we've got an error in all of our sources. Set to REREQUEST delay
        for typeID in priceMap.keys():
            priceobj = priceMap[typeID]
            priceobj.time = time.time() + REREQUEST
            priceobj.failed = True
Example #57
0
 def addModule(self, x, y, itemID):
     """Add a module from the market browser (from dragging it)"""
     fitID = self.mainFrame.getActiveFit()
     item = Market.getInstance().getItem(itemID)
     fit = Fit.getInstance().getFit(fitID)
     dstRow, _ = self.HitTest((x, y))
     if dstRow == -1 or dstRow in self.blanks:
         dstMod = None
     else:
         try:
             dstMod = self.mods[dstRow]
         except IndexError:
             dstMod = None
         if not isinstance(dstMod, Module):
             dstMod = None
         if dstMod not in fit.modules:
             dstMod = None
     dstPos = fit.modules.index(dstMod) if dstMod is not None else None
     mstate = wx.GetMouseState()
     # If we dropping on a module, try to replace, or add if replacement fails
     if item.isModule and dstMod is not None and not dstMod.isEmpty:
         positions = getSimilarModPositions(
             fit.modules,
             dstMod) if mstate.GetModifiers() == wx.MOD_ALT else [dstPos]
         command = cmd.GuiReplaceLocalModuleCommand(fitID=fitID,
                                                    itemID=itemID,
                                                    positions=positions)
         if not self.mainFrame.command.Submit(command):
             if mstate.GetModifiers() == wx.MOD_ALT:
                 self.mainFrame.command.Submit(
                     cmd.GuiFillWithNewLocalModulesCommand(fitID=fitID,
                                                           itemID=itemID))
             else:
                 self.mainFrame.command.Submit(
                     cmd.GuiAddLocalModuleCommand(fitID=fitID,
                                                  itemID=itemID))
     elif item.isModule:
         if mstate.GetModifiers() == wx.MOD_ALT:
             self.mainFrame.command.Submit(
                 cmd.GuiFillWithNewLocalModulesCommand(fitID=fitID,
                                                       itemID=itemID))
         elif dstPos is not None:
             self.mainFrame.command.Submit(
                 cmd.GuiReplaceLocalModuleCommand(fitID=fitID,
                                                  itemID=itemID,
                                                  positions=[dstPos]))
         else:
             self.mainFrame.command.Submit(
                 cmd.GuiAddLocalModuleCommand(fitID=fitID, itemID=itemID))
     elif item.isSubsystem:
         self.mainFrame.command.Submit(
             cmd.GuiAddLocalModuleCommand(fitID=fitID, itemID=itemID))
     elif item.isCharge:
         failoverToAll = False
         positionsAll = list(range(len(fit.modules)))
         if dstMod is None or dstMod.isEmpty:
             positions = positionsAll
         elif mstate.GetModifiers() == wx.MOD_ALT:
             positions = getSimilarModPositions(fit.modules, dstMod)
             failoverToAll = True
         else:
             positions = [fit.modules.index(dstMod)]
         if len(positions) > 0:
             command = cmd.GuiChangeLocalModuleChargesCommand(
                 fitID=fitID, positions=positions, chargeItemID=itemID)
             if not self.mainFrame.command.Submit(
                     command) and failoverToAll:
                 self.mainFrame.command.Submit(
                     cmd.GuiChangeLocalModuleChargesCommand(
                         fitID=fitID,
                         positions=positionsAll,
                         chargeItemID=itemID))
Example #58
0
 def activate(self, callingWindow, fullContext, mainItem, i):
     fitID = self.mainFrame.getActiveFit()
     Fit.getInstance().setAsPattern(fitID, mainItem)
     wx.PostEvent(self.mainFrame, GE.FitChanged(fitIDs=(fitID, )))
Example #59
0
    def __init__(self, parent):
        super().__init__(
            parent, id=wx.ID_ANY, title="Character Editor", resizeable=True,
            pos=wx.DefaultPosition, size=wx.Size(640, 600))

        i = wx.Icon(BitmapLoader.getBitmap("character_small", "gui"))
        self.SetIcon(i)

        self.mainFrame = parent
        # self.disableWin = wx.WindowDisabler(self)
        sFit = Fit.getInstance()

        mainSizer = wx.BoxSizer(wx.VERTICAL)

        self.entityEditor = CharacterEntityEditor(self)
        mainSizer.Add(self.entityEditor, 0, wx.ALL | wx.EXPAND, 2)
        # Default drop down to current fit's character
        self.entityEditor.setActiveEntity(sFit.character)

        self.viewsNBContainer = wx.Notebook(self, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, 0)

        self.sview = SkillTreeView(self.viewsNBContainer)
        self.iview = ImplantEditorView(self.viewsNBContainer, self)
        self.aview = APIView(self.viewsNBContainer)

        self.viewsNBContainer.AddPage(self.sview, "Skills")
        self.viewsNBContainer.AddPage(self.iview, "Implants")
        self.viewsNBContainer.AddPage(self.aview, "EVE SSO")

        mainSizer.Add(self.viewsNBContainer, 1, wx.EXPAND | wx.ALL, 5)

        bSizerButtons = wx.BoxSizer(wx.HORIZONTAL)

        self.btnSaveChar = wx.Button(self, wx.ID_ANY, "Save")
        self.btnSaveAs = wx.Button(self, wx.ID_ANY, "Save As...")
        self.btnRevert = wx.Button(self, wx.ID_ANY, "Revert")
        self.btnOK = wx.Button(self, wx.ID_OK)

        bSizerButtons.Add(self.btnSaveChar, 0, wx.ALL, 5)
        bSizerButtons.Add(self.btnSaveAs, 0, wx.ALL, 5)
        bSizerButtons.Add(self.btnRevert, 0, wx.ALL, 5)
        bSizerButtons.AddStretchSpacer()
        bSizerButtons.Add(self.btnOK, 0, wx.ALL, 5)

        self.btnSaveChar.Bind(wx.EVT_BUTTON, self.saveChar)
        self.btnSaveAs.Bind(wx.EVT_BUTTON, self.saveCharAs)
        self.btnRevert.Bind(wx.EVT_BUTTON, self.revertChar)
        self.btnOK.Bind(wx.EVT_BUTTON, self.editingFinished)

        mainSizer.Add(bSizerButtons, 0, wx.EXPAND, 5)

        self.btnRestrict()

        self.SetSizer(mainSizer)
        self.Layout()

        self.Centre(wx.BOTH)

        self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Bind(wx.EVT_CHAR_HOOK, self.kbEvent)
        self.Bind(GE.CHAR_LIST_UPDATED, self.refreshCharacterList)
        self.entityEditor.Bind(wx.EVT_CHOICE, self.charChanged)

        self.charChanged(None)
Example #60
0
    def MakeSnapshot(self, maxColumns=1337):
        if self.FVsnapshot:
            self.FVsnapshot = None

        tbmp = wx.Bitmap(16, 16)
        tdc = wx.MemoryDC()
        tdc.SelectObject(tbmp)
        tdc.SetFont(self.font)

        columnsWidths = []
        for i in range(len(self.DEFAULT_COLS)):
            columnsWidths.append(0)

        sFit = Fit.getInstance()
        try:
            fit = sFit.getFit(self.activeFitID)
        except (KeyboardInterrupt, SystemExit):
            raise
        except Exception as e:
            pyfalog.critical("Failed to get fit")
            pyfalog.critical(e)
            return

        if fit is None:
            return

        slotMap = {}

        for slot in [e.value for e in FittingSlot]:
            slotMap[slot] = fit.getSlotsFree(slot) < 0

        padding = 2
        isize = 16
        headerSize = max(isize, tdc.GetTextExtent("W")[0]) + padding * 2

        maxRowHeight = isize
        rows = 0
        for st in self.mods:
            for i, col in enumerate(self.activeColumns):
                if i > maxColumns:
                    break
                name = col.getText(st)

                if not isinstance(name, str):
                    name = ""

                nx, ny = tdc.GetTextExtent(name)
                imgId = col.getImageId(st)
                cw = 0
                if imgId != -1:
                    cw += isize + padding
                if name != "":
                    cw += nx + 4 * padding

                if imgId == -1 and name == "":
                    cw += isize + padding

                maxRowHeight = max(ny, maxRowHeight)
                columnsWidths[i] = max(columnsWidths[i], cw)

            rows += 1

        render = wx.RendererNative.Get()

        # Fix column widths (use biggest between header or items)

        for i, col in enumerate(self.activeColumns):
            if i > maxColumns:
                break

            name = col.columnText
            imgId = col.imageId

            if not isinstance(name, str):
                name = ""

            opts = wx.HeaderButtonParams()

            if name != "":
                opts.m_labelText = name

            if imgId != -1:
                opts.m_labelBitmap = wx.Bitmap(isize, isize)

            width = render.DrawHeaderButton(self,
                                            tdc, (0, 0, 16, 16),
                                            sortArrow=wx.HDR_SORT_ICON_NONE,
                                            params=opts)

            columnsWidths[i] = max(columnsWidths[i], width)

        tdc.SelectObject(wx.NullBitmap)

        maxWidth = padding * 2

        for i in range(len(self.DEFAULT_COLS)):
            if i > maxColumns:
                break
            maxWidth += columnsWidths[i]

        mdc = wx.MemoryDC()
        mbmp = wx.Bitmap(maxWidth,
                         maxRowHeight * rows + padding * 4 + headerSize)

        mdc.SelectObject(mbmp)

        mdc.SetBackground(
            wx.Brush(wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOW)))
        mdc.Clear()

        mdc.SetFont(self.font)
        mdc.SetTextForeground(
            wx.SystemSettings.GetColour(wx.SYS_COLOUR_WINDOWTEXT))

        cx = padding
        for i, col in enumerate(self.activeColumns):
            if i > maxColumns:
                break

            name = col.columnText
            imgId = col.imageId

            if not isinstance(name, str):
                name = ""

            opts = wx.HeaderButtonParams()
            opts.m_labelAlignment = wx.ALIGN_LEFT
            if name != "":
                opts.m_labelText = name

            if imgId != -1:
                bmp = col.bitmap
                opts.m_labelBitmap = bmp

            render.DrawHeaderButton(
                self,
                mdc, (cx, padding, columnsWidths[i], headerSize),
                wx.CONTROL_CURRENT,
                sortArrow=wx.HDR_SORT_ICON_NONE,
                params=opts)

            cx += columnsWidths[i]

        brush = wx.Brush(wx.Colour(224, 51, 51))
        pen = wx.Pen(wx.Colour(224, 51, 51))

        mdc.SetPen(pen)
        mdc.SetBrush(brush)

        cy = padding * 2 + headerSize
        for st in self.mods:
            cx = padding

            if slotMap[st.slot]:
                mdc.DrawRectangle(cx, cy, maxWidth - cx, maxRowHeight)

            for i, col in enumerate(self.activeColumns):
                if i > maxColumns:
                    break

                name = col.getText(st)
                if not isinstance(name, str):
                    name = ""

                imgId = col.getImageId(st)
                tcx = cx

                if imgId != -1:
                    self.imageList.Draw(imgId, mdc, cx, cy,
                                        wx.IMAGELIST_DRAW_TRANSPARENT, False)
                    tcx += isize + padding

                if name != "":
                    nx, ny = mdc.GetTextExtent(name)
                    rect = wx.Rect()
                    rect.top = cy
                    rect.left = cx + 2 * padding
                    rect.width = nx
                    rect.height = maxRowHeight + padding
                    mdc.DrawLabel(name, rect, wx.ALIGN_CENTER_VERTICAL)
                    tcx += nx + padding

                cx += columnsWidths[i]

            cy += maxRowHeight

        mdc.SelectObject(wx.NullBitmap)

        self.FVsnapshot = mbmp