def display(self, srcContext, mainItem): validContexts = ("marketItemMisc", "fittingModule", "fittingCharge", "droneItem", "implantItem", "boosterItem", "projectedModule", "projectedDrone", "projectedCharge", "cargoItem", "implantItemChar", "fighterItem", "projectedFighter") if srcContext not in validContexts or mainItem is None: return False if mainItem is None or getattr(mainItem, "isEmpty", False): return False sMkt = Market.getInstance() item = getattr(mainItem, "item", mainItem) isMutated = getattr(mainItem, "isMutated", False) mktGrp = sMkt.getMarketGroupByItem(item) if mktGrp is None and isMutated: mktGrp = sMkt.getMarketGroupByItem(mainItem.baseItem) # 1663 is Special Edition Festival Assets, we don't have root group for it if mktGrp is None or mktGrp.ID == 1663: return False doit = not mainItem.isEmpty if srcContext == "fittingModule" else True return doit
def display(self, srcContext, mainItem, selection): if not self.settings.get('metaSwap'): return False if self.mainFrame.getActiveFit() is None or srcContext not in ( 'fittingModule', 'droneItem', 'fighterItem', 'boosterItem', 'implantItem', 'cargoItem', 'projectedModule', 'projectedDrone', 'projectedFighter' ): return False if mainItem is None or getattr(mainItem, 'isEmpty', False): return False self.mainVariations = Market.getInstance().getVariationsByItems((mainItem.item,)) # No variations from current module if len(self.mainVariations) < 2: return False self.mainItem = mainItem self.selection = selection return True
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
def display(self, srcContext, selection): if not self.settings.get('marketJump'): return False validContexts = ("marketItemMisc", "fittingModule", "fittingCharge", "droneItem", "implantItem", "boosterItem", "projectedModule", "projectedDrone", "projectedCharge", "cargoItem", "implantItemChar", "fighterItem", "projectedDrone") if srcContext not in validContexts or selection is None or len(selection) < 1: return False sMkt = Market.getInstance() item = getattr(selection[0], "item", selection[0]) isMutated = getattr(selection[0], "isMutated", False) mktGrp = sMkt.getMarketGroupByItem(item) if mktGrp is None and isMutated: mktGrp = sMkt.getMarketGroupByItem(selection[0].baseItem) # 1663 is Special Edition Festival Assets, we don't have root group for it if mktGrp is None or mktGrp.ID == 1663: return False doit = not selection[0].isEmpty if srcContext == "fittingModule" else True return doit
def Do(self): pyfalog.debug('Doing change of module charges according to map {} on fit {}'.format(self.chargeMap, self.fitID)) sFit = Fit.getInstance() fit = sFit.getFit(self.fitID) container = fit.modules if not self.projected else fit.projectedModules changes = False self.savedChargeMap = {} sMkt = Market.getInstance() for position, chargeItemID in self.chargeMap.items(): mod = container[position] if mod.isEmpty: continue if mod.chargeID is None and chargeItemID is None: continue if mod.chargeID == chargeItemID: continue chargeItem = sMkt.getItem(chargeItemID) if chargeItemID is not None else None if chargeItem is not None and not chargeItem.isCharge: continue if not self.ignoreRestriction and not mod.isValidCharge(chargeItem): pyfalog.warning('Invalid charge {} for {}'.format(chargeItem, mod)) continue pyfalog.debug('Setting charge {} for {} on fit {}'.format(chargeItem, mod, self.fitID)) self.savedChargeMap[position] = mod.chargeID changes = True mod.charge = chargeItem if not changes: return False sFit.recalc(fit) self.savedStateCheckChanges = sFit.checkStates(fit, None) return True
def display(self, srcContext, selection): if not self.settings.get('moduleAmmoPicker'): return False if self.mainFrame.getActiveFit() is None or srcContext not in ("fittingModule", "projectedModule"): return False modules = selection if srcContext == "fittingModule" else (selection[0],) validCharges = None checkedTypes = set() for mod in modules: # loop through modules and gather list of valid charges if mod.item.ID in checkedTypes: continue checkedTypes.add(mod.item.ID) currCharges = mod.getValidCharges() if len(currCharges) > 0: if validCharges is not None and validCharges != currCharges: return False validCharges = currCharges self.module = mod if validCharges is None: return False self.modules = modules self.charges = list([charge for charge in validCharges if Market.getInstance().getPublicityByItem(charge)]) return len(self.charges) > 0
def expandLookup(self, event): tree = self.availableImplantsTree sMkt = Market.getInstance() parent = event.Item child, _ = tree.GetFirstChild(parent) text = tree.GetItemText(child) if text == "dummy" or text == "itemdummy": tree.Delete(child) # if the dummy item is a market group, replace with actual market groups if text == "dummy": # Add 'real stoof!' instead currentMktGrp = sMkt.getMarketGroup(tree.GetPyData(parent), eager="children") for childMktGrp in sMkt.getMarketGroupChildren(currentMktGrp): iconId = self.addMarketViewImage(sMkt.getIconByMarketGroup(childMktGrp)) childId = tree.AppendItem(parent, childMktGrp.name, iconId, data=wx.TreeItemData(childMktGrp.ID)) if sMkt.marketGroupHasTypesCheck(childMktGrp) is False: tree.AppendItem(childId, "dummy") else: tree.AppendItem(childId, "itemdummy") # replace dummy with actual items if text == "itemdummy": currentMktGrp = sMkt.getMarketGroup(tree.GetPyData(parent)) items = sMkt.getItemsByMarketGroup(currentMktGrp) for item in items: iconId = self.addMarketViewImage(item.icon.iconFile) tree.AppendItem(parent, item.name, iconId, data=wx.TreeItemData(item)) tree.SortChildren(parent)
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)
def refreshPanel(self, fit): if fit is not None: self.fit = fit # Compose a list of all the data we need & request it typeIDs = [] typeIDs.append(fit.ship.item.ID) for mod in fit.modules: if not mod.isEmpty: typeIDs.append(mod.itemID) for drone in fit.drones: typeIDs.append(drone.itemID) for fighter in fit.fighters: if fighter.amountActive > 0: typeIDs.append(fighter.itemID) for cargo in fit.cargo: typeIDs.append(cargo.itemID) sMkt = Market.getInstance() sMkt.getPrices(typeIDs, self.processPrices) self.labelEMStatus.SetLabel("Updating prices...") else: self.labelEMStatus.SetLabel("") self.labelPriceShip.SetLabel("0.0 ISK") self.labelPriceFittings.SetLabel("0.0 ISK") self.labelPriceTotal.SetLabel("0.0 ISK") self._cachedFittings = self._cachedShip = self._cachedTotal = 0 self.panel.Layout()
def getAbyssalWeather(self): sMkt = Market.getInstance() environments = {x.ID: x for x in sMkt.getGroup("Abyssal Environment").items} items = chain(sMkt.getGroup("MassiveEnvironments").items, sMkt.getGroup("Non-Interactable Object").items) grouped = {} flat = set() for beacon in items: if not beacon.isType('projected'): continue type = self.__class__.abyssal_mapping.get(beacon.name[0:-2], None) type = environments.get(type, None) if type is None: continue if type.name not in grouped: grouped[type.name] = set() display_name = "{} {}".format(type.name, beacon.name[-1:]) grouped[type.name].add((beacon, display_name, display_name)) # PVP weather flat.add((sMkt.getItem(49766), 'PvP Weather', 'PvP Weather')) return grouped, flat
def spawnMenu(self, event): item = event.GetItem() self.skillTreeListCtrl.Select(item) thing = self.skillTreeListCtrl.GetFirstChild(item).IsOk() if thing: return id = self.skillTreeListCtrl.GetItemData(item)[1] eveItem = Market.getInstance().getItem(id) srcContext = "skillItem" itemContext = "Skill" context = (srcContext, itemContext) menu = ContextMenu.getMenu(eveItem, [eveItem], context) char = self.charEditor.entityEditor.getActiveEntity() if char.name not in ("All 0", "All 5"): menu.AppendSeparator() menu.Append(self.idUnlearned, "Unlearn") for level in range(6): menu.Append(self.idLevels[level], "Level %d" % level) # Doesn't make sense to have these menu items here, as they do not revert skill changes # done in an editor - because these changes are persisted anyway # menu.AppendSeparator() # menu.Append(self.revertID, "Revert") # menu.Append(self.saveID, "Save") menu.Bind(wx.EVT_MENU, self.changeLevel) self.PopupMenu(menu)
def findCheaperReplacements(self, items, callback, fetchTimeout=10): sMkt = Market.getInstance() replacementsAll = {} # All possible item replacements for item in items: if item in replacementsAll: continue itemRepls = sMkt.getReplacements(item) if itemRepls: replacementsAll[item] = itemRepls itemsToFetch = {i for i in chain(replacementsAll.keys(), *replacementsAll.values())} def makeCheapMapCb(requests): # Decide what we are going to replace replacementsCheaper = {} # Items which should be replaced for replacee, replacers in replacementsAll.items(): replacer = min(replacers, key=lambda i: i.price.price or math.inf) if (replacer.price.price or math.inf) < (replacee.price.price or math.inf): replacementsCheaper[replacee] = replacer try: callback(replacementsCheaper) except Exception as e: pyfalog.critical("Execution of callback from findCheaperReplacements failed.") pyfalog.critical(e) # Prices older than 2 hours have to be refetched validityOverride = 2 * 60 * 60 self.getPrices(itemsToFetch, makeCheapMapCb, fetchTimeout=fetchTimeout, validityOverride=validityOverride)
def display(self, srcContext, selection): if not self.settings.get('metaSwap'): return False if self.mainFrame.getActiveFit() is None or srcContext not in ( "fittingModule", "droneItem", "fighterItem", "boosterItem", "implantItem", "cargoItem", ): return False # Check if list of variations is same for all of selection # If not - don't show the menu mkt = Market.getInstance() self.variations = None for i in selection: variations = mkt.getVariationsByItems([i.item]) if self.variations is None: self.variations = variations else: if variations != self.variations: return False self.selection = selection if len(self.variations) == 1: return False # no variations from current module return True
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)
def droneKey(self, drone): sMkt = Market.getInstance() groupName = sMkt.getMarketGroupByItem(drone.item).name return (self.DRONE_ORDER.index(groupName), drone.item.name)
def getSubMenu(self, context, selection, rootMenu, i, pitem): msw = True if "wxMSW" in wx.PlatformInfo else False sMkt = Market.getInstance() effdata = sMkt.getSystemWideEffects() self.idmap = {} sub = wx.Menu() for swType in sorted(effdata): subItem = wx.MenuItem(sub, wx.ID_ANY, swType) grandSub = wx.Menu() subItem.SetSubMenu(grandSub) sub.AppendItem(subItem) for swData in sorted(effdata[swType], key=lambda tpl: tpl[2]): wxid = ContextMenu.nextID() swObj, swName, swClass = swData self.idmap[wxid] = (swObj, swName) grandSubItem = wx.MenuItem(grandSub, wxid, swClass) if msw: rootMenu.Bind(wx.EVT_MENU, self.handleSelection, grandSubItem) else: grandSub.Bind(wx.EVT_MENU, self.handleSelection, grandSubItem) grandSub.AppendItem(grandSubItem) return sub
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
def Do(self): pyfalog.debug('Doing changing ship mode to {} for fit {}'.format(self.itemID, self.fitID)) fit = Fit.getInstance().getFit(self.fitID) self.savedItemID = fit.mode.item.ID item = Market.getInstance().getItem(self.itemID) mode = Mode(item) fit.mode = mode return True
def groupHasFits(self, id): sMkt = Market.getInstance() grp = sMkt.getGroup(id, eager=("items", "group")) items = sMkt.getItemsByGroup(grp) for item in items: if self.countFitsWithShip(item.ID) > 0: return True return False
def stage3(self, event): self.navpanel.ToggleRecentShips(False, False) self.lpane.ShowLoading(False) # If back is False, do not append to history. This could be us calling # the stage from previous history, creating / copying fit, etc. # We also have to use conditional for search stage since it's last data # is kept elsewhere if getattr(event, "back", False): if self._activeStage == 4 and self.navpanel.lastSearch != "": self.browseHist.append((4, self.navpanel.lastSearch)) else: self.browseHist.append((self._activeStage, self.lastdata)) shipID = event.shipID self.lastdata = shipID self._lastStage = self._activeStage self._activeStage = 3 sFit = Fit.getInstance() sMkt = Market.getInstance() ship = sMkt.getItem(shipID) categoryID = ship.group.ID self.lpane.Freeze() self.lpane.RemoveAllChildren() fitList = sFit.getFitsWithShip(shipID) if len(fitList) == 0: stage, data = self.browseHist.pop() self.lpane.Thaw() self.navpanel.gotoStage(stage, data) return self.categoryFitCache[categoryID] = True self.navpanel.ShowNewFitButton(True) self.navpanel.ShowSwitchEmptyGroupsButton(False) if self.showRacesFilterInStage2Only: self.raceselect.Show(False) self.Layout() fitList.sort(key=self.nameKey) shipName = ship.name self._stage3ShipName = shipName self._stage3Data = shipID shipTrait = ship.traits.traitText if (ship.traits is not None) else "" # empty string if no traits for ID, name, booster, timestamp, notes, graphicID in fitList: self.lpane.AddWidget(FitItem(self.lpane, ID, (shipName, shipTrait, name, booster, timestamp, notes), shipID, graphicID=graphicID)) self.lpane.RefreshList() self.lpane.Thaw() self.raceselect.RebuildRaces(self.RACE_ORDER)
def getEffectBeacons(self, incursions=False): """ Get dictionary with wormhole system-wide effects """ sMkt = Market.getInstance() # todo: rework this # Container for system-wide effects grouped = {} # Expressions for matching when detecting effects we're looking for if incursions: validgroups = ("Incursion ship attributes effects", "Invasion Effects") else: validgroups = ("Black Hole Effect Beacon", "Cataclysmic Variable Effect Beacon", "Magnetar Effect Beacon", "Pulsar Effect Beacon", "Red Giant Beacon", "Wolf Rayet Effect Beacon") # Stuff we don't want to see in names garbages = ("Effects?", "Beacon", "ship attributes effects") # Get group with all the system-wide beacons grp = sMkt.getGroup("Effect Beacon") # Cycle through them for beacon in sMkt.getItemsByGroup(grp): # Check if it belongs to any valid group for group in validgroups: # Check beginning of the name only if re.match(group, beacon.name): # Get full beacon name beaconname = beacon.name for garbage in garbages: beaconname = re.sub(garbage, "", beaconname) beaconname = re.sub(" {2,}", " ", beaconname).strip() # Get short name shortname = re.sub(group, "", beacon.name) for garbage in garbages: shortname = re.sub(garbage, "", shortname) shortname = re.sub(" {2,}", " ", shortname).strip() # Get group name groupname = group for garbage in garbages: groupname = re.sub(garbage, "", groupname) groupname = re.sub(" {2,}", " ", groupname).strip() # Add stuff to dictionary if groupname not in grouped: grouped[groupname] = set() grouped[groupname].add((beacon, beaconname, shortname)) # Break loop on 1st result break return grouped, ()
def spawnMenu(self, event): sel = self.GetFirstSelected() if sel != -1: fighter = self.fighters[sel] sMkt = Market.getInstance() sourceContext = "fighterItem" itemContext = sMkt.getCategoryByItem(fighter.item).name menu = ContextMenu.getMenu((fighter,), (sourceContext, itemContext)) self.PopupMenu(menu)
def spawnMenu(self): sel = self.GetFirstSelected() if sel != -1: drone = self.drones[sel] sMkt = Market.getInstance() sourceContext = "droneItem" itemContext = sMkt.getCategoryByItem(drone.item).name menu = ContextMenu.getMenu((drone,), (sourceContext, itemContext)) self.PopupMenu(menu)
def fighterKey(self, fighter): groupName = Market.getInstance().getGroupByItem(fighter.item).name orderPos = self.FIGHTER_ORDER.index(groupName) # Sort support fighters by name, ignore their abilities if groupName == 'Support Fighter': abilityEffectIDs = () # Group up fighters from various roles else: abilityEffectIDs = sorted(a.effectID for a in fighter.abilities) return orderPos, abilityEffectIDs, fighter.item.name
def addItem(self, event): item = Market.getInstance().getItem(event.itemID, eager='group.category') if item is None or not item.isFighter: event.Skip() return fitID = self.mainFrame.getActiveFit() if self.mainFrame.command.Submit(cmd.GuiAddLocalFighterCommand(fitID, event.itemID)): self.mainFrame.additionsPane.select('Fighters') event.Skip()
def searchStage(self, event): self.lpane.ShowLoading(False) self.navpanel.ShowNewFitButton(False) self.navpanel.ShowSwitchEmptyGroupsButton(False) if not event.back: if self._activeStage != 4: if len(self.browseHist) > 0: self.browseHist.append((self._activeStage, self.lastdata)) else: self.browseHist.append((1, 0)) self._lastStage = self._activeStage self._activeStage = 4 sMkt = Market.getInstance() sFit = Fit.getInstance() query = event.text self.lpane.Freeze() self.lpane.RemoveAllChildren() if query: ships = sMkt.searchShips(query) fitList = sFit.searchFits(query) for ship in ships: shipTrait = ship.traits.traitText if (ship.traits is not None) else "" # empty string if no traits self.lpane.AddWidget( ShipItem(self.lpane, ship.ID, (ship.name, shipTrait, len(sFit.getFitsWithShip(ship.ID))), ship.race, ship.graphicID)) for ID, name, shipID, shipName, booster, timestamp, notes in fitList: ship = sMkt.getItem(shipID) if not sMkt.getPublicityByItem(ship): continue shipTrait = ship.traits.traitText if (ship.traits is not None) else "" # empty string if no traits self.lpane.AddWidget(FitItem(self.lpane, ID, (shipName, shipTrait, name, booster, timestamp, notes), shipID, graphicID=ship.graphicID)) if len(ships) == 0 and len(fitList) == 0: self.lpane.AddWidget(PFStaticText(self.lpane, label="No matching results.")) self.lpane.RefreshList(doFocus=False) self.lpane.Thaw() self.raceselect.RebuildRaces(self.RACE_ORDER) if self.showRacesFilterInStage2Only: self.raceselect.Show(False) self.Layout()
def scheduleSearch(self, event=None): sMkt = Market.getInstance() search = self.searchBox.GetLineText(0) # Make sure we do not count wildcard as search symbol realsearch = search.replace("*", "") # Show nothing if query is too short if len(realsearch) < 3: self.clearSearch() return sMkt.searchItems(search, self.populateSearch, ["Implant"])
def _fetchItem(typeName, eagerCat=False): sMkt = Market.getInstance() eager = 'group.category' if eagerCat else None try: item = sMkt.getItem(typeName, eager=eager) except: pyfalog.warning('service.port.eft: unable to fetch item "{}"'.format(typeName)) return None if sMkt.getPublicityByItem(item): return item else: return None
def __handleCargo(self, varItem): fitID = self.mainFrame.getActiveFit() sMkt = Market.getInstance() itemIDs = [] for cargo in self.selection: if cargo is self.mainItem: itemIDs.append(cargo.itemID) continue cargoVariations = sMkt.getVariationsByItems((cargo.item,)) if cargoVariations == self.mainVariations: itemIDs.append(cargo.itemID) self.mainFrame.command.Submit(cmd.GuiChangeCargoMetasCommand( fitID=fitID, itemIDs=itemIDs, newItemID=varItem.ID))
def spawnMenu(self,event): sel = self.GetFirstSelected() if sel != -1: sFit = Fit.getInstance() fit = sFit.getFit(self.mainFrame.getActiveFit()) cargo = fit.cargo[sel] sMkt = Market.getInstance() sourceContext = "cargoItem" itemContext = sMkt.getCategoryByItem(cargo.item).name menu = ContextMenu.getMenu((cargo,), (sourceContext, itemContext)) self.PopupMenu(menu)
def spawnMenu(self, event): selection = self.getSelectedFighters() clickedPos = self.getRowByAbs(event.Position) mainFighter = None if clickedPos != -1: try: fighter = self.fighters[clickedPos] except IndexError: pass else: if fighter in self.original: mainFighter = fighter sourceContext = "fighterItem" itemContext = None if mainFighter is None else Market.getInstance().getCategoryByItem(mainFighter.item).name menu = ContextMenu.getMenu(self, mainFighter, selection, (sourceContext, itemContext)) if menu: self.PopupMenu(menu)
def spawnMenu(self, event): selection = self.getSelectedDrones() clickedPos = self.getRowByAbs(event.Position) mainDrone = None if clickedPos != -1: try: drone = self.drones[clickedPos] except IndexError: pass else: if drone in self.original: mainDrone = drone sourceContext = "droneItem" itemContext = None if mainDrone is None else Market.getInstance().getCategoryByItem(mainDrone.item).name menu = ContextMenu.getMenu(mainDrone, selection, (sourceContext, itemContext)) if menu: self.PopupMenu(menu)
def addItem(self, event): item = Market.getInstance().getItem(event.itemID, eager='group.category') if item is None or not item.isDrone: event.Skip() return fitID = self.mainFrame.getActiveFit() fit = Fit.getInstance().getFit(fitID) if not fit or fit.isStructure: event.Skip() return amount = droneStackLimit(fit, event.itemID) if wx.GetMouseState().altDown else 1 if self.mainFrame.command.Submit(cmd.GuiAddLocalDroneCommand(fitID=fitID, itemID=event.itemID, amount=amount)): self.mainFrame.additionsPane.select('Drones') event.Skip()
def itemSort(self, item): sMkt = Market.getInstance() isFittable = item.group.name in sMkt.FIT_GROUPS or item.category.name in sMkt.FIT_CATEGORIES catname = sMkt.getCategoryByItem(item).name try: mktgrpid = sMkt.getMarketGroupByItem(item).ID except AttributeError: mktgrpid = -1 pyfalog.warning("unable to find market group for {}".format( item.name)) parentname = sMkt.getParentItemByItem(item).name # Get position of market group metagrpid = sMkt.getMetaGroupIdByItem(item) metatab = sMkt.META_MAP_REVERSE_INDICES.get(metagrpid) metalvl = item.metaLevel or 0 return not isFittable, catname, mktgrpid, parentname, metatab, metalvl, item.name
def __init__(self, parent): wx.Panel.__init__(self, parent) pyfalog.debug("Initialize marketBrowser") vbox = wx.BoxSizer(wx.VERTICAL) self.SetSizer(vbox) # Add a search box on top self.search = SearchBox(self) vbox.Add(self.search, 0, wx.EXPAND) self.splitter = wx.SplitterWindow(self, style=wx.SP_LIVE_UPDATE) vbox.Add(self.splitter, 1, wx.EXPAND) # Grab market service instance and create child objects self.sMkt = Market.getInstance() self.searchMode = False self.marketView = MarketTree(self.splitter, self) self.itemView = ItemView(self.splitter, self) self.splitter.SplitHorizontally(self.marketView, self.itemView) self.splitter.SetMinimumPaneSize(250) # Setup our buttons for metaGroup selection # Same fix as for search box on macs, # need some pixels of extra space or everything clips and is ugly p = wx.Panel(self) box = wx.BoxSizer(wx.HORIZONTAL) p.SetSizer(box) vbox.Add(p, 0, wx.EXPAND) self.metaButtons = [] btn = None for name in self.sMkt.META_MAP.keys(): btn = MetaButton(p, wx.ID_ANY, name.capitalize(), style=wx.BU_EXACTFIT) setattr(self, name, btn) box.Add(btn, 1, wx.ALIGN_CENTER) btn.Bind(wx.EVT_TOGGLEBUTTON, self.toggleMetaButton) btn.metaName = name self.metaButtons.append(btn) # Make itemview to set toggles according to list contents self.itemView.setToggles() p.SetMinSize((wx.SIZE_AUTO_WIDTH, btn.GetSize()[1] + 5))
def stage1(self, event): self.navpanel.ToggleRecentShips(False, False) self._lastStage = self._activeStage self._activeStage = 1 self.lastdata = 0 self.browseHist = [(1, 0)] self.navpanel.ShowNewFitButton(False) self.navpanel.ShowSwitchEmptyGroupsButton(False) sMkt = Market.getInstance() sFit = Fit.getInstance() self.lpane.ShowLoading(False) self.lpane.Freeze() self.lpane.RemoveAllChildren() pyfalog.debug("Populate ship category list.") if len(self.categoryList) == 0: # set cache of category list self.categoryList = list(sMkt.getShipRoot()) self.categoryList.sort(key=lambda _ship: _ship.name) # set map & cache of fittings per category for cat in self.categoryList: itemIDs = [x.ID for x in cat.items] num = sFit.countFitsWithShip(itemIDs) self.categoryFitCache[cat.ID] = num > 0 for ship in self.categoryList: if self.filterShipsWithNoFits and not self.categoryFitCache[ ship.ID]: continue else: self.lpane.AddWidget( CategoryItem(self.lpane, ship.ID, (ship.name, 0))) self.navpanel.ShowSwitchEmptyGroupsButton(True) self.lpane.RefreshList() self.lpane.Thaw() self.raceselect.RebuildRaces(self.RACE_ORDER) if self.showRacesFilterInStage2Only: self.raceselect.Show(False) self.Layout()
def toModule(self, fallbackState=None): mkt = Market.getInstance() item = mkt.getItem(self.itemID, eager=('attributes', 'group.category')) if self.baseItemID and self.mutaplasmidID: baseItem = mkt.getItem(self.baseItemID, eager=('attributes', 'group.category')) mutaplasmid = eos.db.getDynamicItem(self.mutaplasmidID) else: baseItem = None mutaplasmid = None try: mod = Module(item, baseItem=baseItem, mutaplasmid=mutaplasmid) except ValueError: pyfalog.warning('Invalid item: {}'.format(self.itemID)) return None if self.mutations is not None: for attrID, mutator in mod.mutators.items(): if attrID in self.mutations: mutator.value = self.mutations[attrID] if self.spoolType is not None and self.spoolAmount is not None: mod.spoolType = self.spoolType mod.spoolAmount = self.spoolAmount mod.rahPatternOverride = self.rahPattern if self.state is not None: if mod.isValidState(self.state): mod.state = self.state else: mod.state = mod.getMaxState(proposedState=self.state) elif fallbackState is not None: if mod.isValidState(fallbackState): mod.state = fallbackState if self.chargeID is not None: charge = mkt.getItem(self.chargeID, eager=('attributes', )) if charge is None: pyfalog.warning('Cannot set charge {}'.format(self.chargeID)) return None mod.charge = charge return mod
def importDnaAlt(string, fitName=None): sMkt = Market.getInstance() ids = list(map(int, re.findall(r'\d+', string))) for id_ in ids: try: try: Ship(sMkt.getItem(id_)) except ValueError: Citadel(sMkt.getItem(id_)) string = string[string.index(str(id_)):] break except (KeyboardInterrupt, SystemExit): raise except: pyfalog.warning("Exception caught in importDna") pass info = string.split(":") return processImportInfo(info, fitName, "*")
def __handleDrone(self, varItem): fitID = self.mainFrame.getActiveFit() fit = Fit.getInstance().getFit(fitID) sMkt = Market.getInstance() positions = [] for drone in self.selection: if drone not in fit.drones: continue if drone is self.mainItem: positions.append(fit.drones.index(drone)) continue droneVariations = sMkt.getVariationsByItems((drone.item, )) if droneVariations == self.mainVariations: positions.append(fit.drones.index(drone)) self.mainFrame.command.Submit( cmd.GuiChangeLocalDroneMetasCommand(fitID=fitID, positions=positions, newItemID=varItem.ID))
def addItem(self, event): item = Market.getInstance().getItem(event.itemID, eager='group') if item is None or not item.isBooster: event.Skip() return fitID = self.mainFrame.getActiveFit() fit = Fit.getInstance().getFit(fitID) if not fit or fit.isStructure: event.Skip() return self.mainFrame.command.Submit( cmd.GuiAddBoosterCommand(fitID=fitID, itemID=event.itemID)) # Select in any case - as we might've added booster which has been there already and command failed self.mainFrame.additionsPane.select('Boosters') event.Skip()
def toFighter(self): item = Market.getInstance().getItem(self.itemID, eager=('attributes', 'group.category')) try: fighter = Fighter(item) except ValueError: pyfalog.warning('Invalid item: {}'.format(self.itemID)) return None if self.amount is not None: fighter.amount = self.amount if self.state is not None: fighter.active = self.state if self.abilities is not None: for ability in fighter.abilities: ability.active = self.abilities.get(ability.effectID, ability.active) return fighter
def Do(self): sMkt = Market.getInstance() results = [] for position in sorted(self.positions, reverse=True): cmd = CalcRemoveLocalDroneCommand(fitID=self.fitID, position=position, amount=self.amount) results.append(self.internalHistory.submit(cmd)) sMkt.storeRecentlyUsed(cmd.savedDroneInfo.itemID) success = any(results) eos.db.flush() sFit = Fit.getInstance() sFit.recalc(self.fitID) sFit.fill(self.fitID) eos.db.commit() wx.PostEvent(gui.mainFrame.MainFrame.getInstance(), GE.FitChanged(fitIDs=(self.fitID, ))) return success
def __handleProjectedDrone(self, varItem): fitID = self.mainFrame.getActiveFit() fit = Fit.getInstance().getFit(fitID) sMkt = Market.getInstance() itemIDs = [] for drone in self.selection: if drone not in fit.projectedDrones: continue if drone is self.mainItem: itemIDs.append(drone.itemID) continue droneVariations = sMkt.getVariationsByItems((drone.item, )) if droneVariations == self.mainVariations: itemIDs.append(drone.itemID) self.mainFrame.command.Submit( cmd.GuiChangeProjectedDroneMetasCommand(fitID=fitID, itemIDs=itemIDs, newItemID=varItem.ID))
def OnExport(self, event): sMkt = Market.getInstance() items = sMkt.getItemsWithOverrides() defaultFile = "pyfa_overrides.csv" with wx.FileDialog( self, "Save Overrides As...", wildcard="pyfa overrides (*.csv)|*.csv", style=wx.FD_SAVE, defaultFile=defaultFile ) as dlg: if dlg.ShowModal() == wx.ID_OK: path = dlg.GetPath() with open(path, 'w', encoding='utf-8') as csvfile: writer = csv.writer(csvfile) for item in items: for key, override in item.overrides.items(): writer.writerow([item.ID, override.attrID, override.value])
def spawnMenu(self, event): clickedPos = self.getRowByAbs(event.Position) self.ensureSelection(clickedPos) selection = self.getSelectedCargos() mainCargo = None if clickedPos != -1: try: cargo = self.cargo[clickedPos] except IndexError: pass else: if cargo in self.original: mainCargo = cargo itemContext = None if mainCargo is None else Market.getInstance().getCategoryByItem(mainCargo.item).name menu = ContextMenu.getMenu(self, mainCargo, selection, ("cargoItem", itemContext), ("cargoItemMisc", itemContext)) if menu: self.PopupMenu(menu)
def getAbyssalWeather(self): sMkt = Market.getInstance() data = Group() environments = { x.ID: x for x in sMkt.getGroup("Abyssal Environment").items } items = chain( sMkt.getGroup("MassiveEnvironments").items, sMkt.getGroup("Non-Interactable Object").items) for beacon in items: if not beacon.isType('projected'): continue type = self.__class__.abyssal_mapping.get(beacon.name[0:-2], None) type = environments.get(type, None) if type is None: continue subdata = data.groups.setdefault(type.name, Group()) display_name = "{} {}".format(type.name, beacon.name[-1:]) subdata.items.append(Entry(beacon.ID, display_name, display_name)) data.sort() # Localized abyssal hazards items = sMkt.getGroup("Abyssal Hazards").items if items: subdata = data.groups.setdefault('Localized', Group()) for beacon in sMkt.getGroup("Abyssal Hazards").items: if not beacon.isType('projected'): continue # Localized effects, currently, have a name like "(size) (type) Cloud" # Until this inevitably changes, do a simple split name_parts = beacon.name.split(" ") key = name_parts[1].strip() subsubdata = subdata.groups.setdefault(key, Group()) subsubdata.items.append( Entry(beacon.ID, beacon.name, beacon.name)) subdata.sort() # PVP weather data.items.append(Entry(49766, 'PvP Weather', 'PvP Weather')) return data
def spawnMenu(self, event): fitID = self.mainFrame.getActiveFit() if fitID is None: return if self.getColumn(self.ScreenToClient(event.Position)) == self.getColIndex(State): return sel = self.GetFirstSelected() context = () item = self.get(sel) if item is not None: sMkt = Market.getInstance() if isinstance(item, es_Drone): srcContext = "projectedDrone" itemContext = sMkt.getCategoryByItem(item.item).name context = ((srcContext, itemContext),) elif isinstance(item, es_Fighter): srcContext = "projectedFighter" itemContext = sMkt.getCategoryByItem(item.item).name context = ((srcContext, itemContext),) elif isinstance(item, es_Module): modSrcContext = "projectedModule" modItemContext = sMkt.getCategoryByItem(item.item).name modFullContext = (modSrcContext, modItemContext) if item.charge is not None: chgSrcContext = "projectedCharge" chgItemContext = sMkt.getCategoryByItem(item.charge).name chgFullContext = (chgSrcContext, chgItemContext) context = (modFullContext, chgFullContext) else: context = (modFullContext,) else: fitSrcContext = "projectedFit" fitItemContext = "Fit" context = ((fitSrcContext, fitItemContext),) context += (("projected",),) menu = ContextMenu.getMenu((item,) if item is not None else [], *context) if menu is not None: self.PopupMenu(menu)
def importSets(self, text): sMkt = Market.getInstance() lines = text.splitlines() newSets = [] errors = 0 current = None lookup = {} for i, line in enumerate(lines): line = line.strip() try: if line == '' or line[0] == "#": # comments / empty string continue if line[:1] == "[" and line[-1:] == "]": current = es_ImplantSet(line[1:-1]) newSets.append(current) else: item = sMkt.getItem(line) current.implants.append(es_Implant(item)) except (KeyboardInterrupt, SystemExit): raise except: errors += 1 continue for implant_set in self.getImplantSetList(): lookup[implant_set.name] = implant_set for implant_set in newSets: if implant_set.name in lookup: match = lookup[implant_set.name] for implant in implant_set.implants: match.implants.append(es_Implant(implant.item)) else: eos.db.save(implant_set) eos.db.commit() lenImports = len(newSets) if lenImports == 0: raise ImportError("No patterns found for import") if errors > 0: raise ImportError("%d sets imported from clipboard; %d errors" % (lenImports, errors))
def __handleProjectedModule(self, varItem): fitID = self.mainFrame.getActiveFit() fit = Fit.getInstance().getFit(fitID) if wx.GetMouseState().GetModifiers() == wx.MOD_ALT: positions = getSimilarModPositions(fit.projectedModules, self.mainItem) else: sMkt = Market.getInstance() positions = [] for mod in self.selection: if mod is self.mainItem: positions.append(fit.projectedModules.index(mod)) continue if mod not in fit.projectedModules: continue modVariations = sMkt.getVariationsByItems((mod.item,)) if modVariations == self.mainVariations: positions.append(fit.projectedModules.index(mod)) self.mainFrame.command.Submit(cmd.GuiChangeProjectedModuleMetasCommand( fitID=fitID, positions=positions, newItemID=varItem.ID))
def getAbyssalWeather(self): sMkt = Market.getInstance() data = Group() environments = {x.ID: x for x in sMkt.getGroup("Abyssal Environment").items} items = chain( sMkt.getGroup("MassiveEnvironments").items, sMkt.getGroup("Non-Interactable Object").items) for beacon in items: if not beacon.isType('projected'): continue type = self.__class__.abyssal_mapping.get(beacon.name[0:-2], None) type = environments.get(type, None) if type is None: continue subdata = data.groups.setdefault(type.name, Group()) display_name = "{} {}".format(type.name, beacon.name[-1:]) subdata.items.append(Entry(beacon.ID, display_name, display_name)) data.sort() # Localized abyssal hazards items = sMkt.getGroup("Abyssal Hazards").items if items: subdata = data.groups.setdefault(_t('Localized'), Group()) for beacon in sMkt.getGroup("Abyssal Hazards").items: if not beacon.isType('projected'): continue groups = (_t('Bioluminescence'), _t('Tachyon'), _t('Filament')) for group in groups: if re.search(group, beacon.customName): key = group break else: continue subsubdata = subdata.groups.setdefault(key, Group()) subsubdata.items.append(Entry(beacon.ID, beacon.customName, beacon.customName)) subdata.sort() # PVP weather data.items.append(Entry(49766, _t('PvP Weather'), _t('PvP Weather'))) return data
def OnClear(self, event): with wx.MessageDialog( self, "Are you sure you want to delete all overrides?", "Confirm Delete", wx.YES | wx.NO | wx.ICON_EXCLAMATION ) as dlg: if dlg.ShowModal() == wx.ID_YES: sMkt = Market.getInstance() items = sMkt.getItemsWithOverrides() # We can't just delete overrides, as loaded items will still have # them assigned. Deleting them from the database won't propagate # them due to the eve/user database disconnect. We must loop through # all items that have overrides and remove them for item in items: for _, x in list(item.overrides.items()): item.deleteOverride(x.attr) self.itemView.updateItems(True) self.pg.Clear()
def __handleProjectedFighter(self, varItem): fitID = self.mainFrame.getActiveFit() fit = Fit.getInstance().getFit(fitID) if wx.GetMouseState().GetModifiers() == wx.MOD_ALT: fighters = getSimilarFighters(fit.projectedFighters, self.mainItem) else: fighters = self.selection sMkt = Market.getInstance() positions = [] for fighter in fighters: if fighter not in fit.projectedFighters: continue if fighter is self.mainItem: positions.append(fit.projectedFighters.index(fighter)) continue fighterVariations = sMkt.getVariationsByItems((fighter.item,)) if fighterVariations == self.mainVariations: positions.append(fit.projectedFighters.index(fighter)) self.mainFrame.command.Submit(cmd.GuiChangeProjectedFighterMetasCommand( fitID=fitID, positions=positions, newItemID=varItem.ID))
def parseAdditions(text, mutaData=None): items = [] sMkt = Market.getInstance() pattern = '^(?P<typeName>{}+?)( x(?P<amount>\d+?))?(\s*\[(?P<mutaref>\d+?)\])?$'.format(NAME_CHARS) for line in lineIter(text): m = re.match(pattern, line) if not m: continue item = sMkt.getItem(m.group('typeName')) if item is None: continue amount = m.group('amount') amount = 1 if amount is None else int(amount) mutaRef = int(m.group('mutaref')) if m.group('mutaref') else None if mutaRef and mutaData and mutaRef in mutaData: mutation = mutaData[mutaRef] else: mutation = None items.append((item, amount, mutation)) return items
def display(self, callingWindow, srcContext, mainItem, selection): if self.mainFrame.getActiveFit() is None or srcContext not in ( 'fittingModule', 'droneItem', 'fighterItem', 'boosterItem', 'implantItem', 'cargoItem', 'projectedModule', 'projectedDrone', 'projectedFighter'): return False if mainItem is None or getattr(mainItem, 'isEmpty', False): return False self.mainVariations = Market.getInstance().getVariationsByItems( (mainItem.item, )) # No variations from current module if len(self.mainVariations) < 2: return False self.mainItem = mainItem self.selection = selection self.srcContext = srcContext return True
def spawnMenu(self, event): selection = self.getSelectedImplants() clickedPos = self.getRowByAbs(event.Position) mainImplant = None if clickedPos != -1: try: implant = self.implants[clickedPos] except IndexError: pass else: if implant in self.original: mainImplant = implant fitID = self.mainFrame.getActiveFit() fit = Fit.getInstance().getFit(fitID) sourceContext1 = "implantItem" if fit.implantSource == ImplantLocation.FIT else "implantItemChar" sourceContext2 = "implantView" if fit.implantSource == ImplantLocation.FIT else "implantViewChar" itemContext = None if mainImplant is None else Market.getInstance().getCategoryByItem(mainImplant.item).name menu = ContextMenu.getMenu(mainImplant, selection, (sourceContext1, itemContext), (sourceContext2, itemContext)) if menu: self.PopupMenu(menu)
def spawnMenu(self): sel = self.GetFirstSelected() menu = None if sel != -1: item = self.get(sel) if item is None: return sMkt = Market.getInstance() if isinstance(item, es_Drone): srcContext = "projectedDrone" itemContext = sMkt.getCategoryByItem(item.item).name context = ((srcContext, itemContext),) elif isinstance(item, es_Fighter): srcContext = "projectedFighter" itemContext = sMkt.getCategoryByItem(item.item).name context = ((srcContext, itemContext),) elif isinstance(item, es_Module): modSrcContext = "projectedModule" modItemContext = sMkt.getCategoryByItem(item.item).name modFullContext = (modSrcContext, modItemContext) if item.charge is not None: chgSrcContext = "projectedCharge" chgItemContext = sMkt.getCategoryByItem(item.charge).name chgFullContext = (chgSrcContext, chgItemContext) context = (modFullContext, chgFullContext) else: context = (modFullContext,) else: fitSrcContext = "projectedFit" fitItemContext = item.name context = ((fitSrcContext, fitItemContext),) context += ("projected",), menu = ContextMenu.getMenu((item,), *context) elif sel == -1: fitID = self.mainFrame.getActiveFit() if fitID is None: return context = (("projected",),) menu = ContextMenu.getMenu([], *context) if menu is not None: self.PopupMenu(menu)
def __init__(self, fittingView, params): ViewColumn.__init__(self, fittingView) sAttr = Attribute.getInstance() info = sAttr.getAttributeInfo(params["attribute"]) self.info = info self.direct = False if params["showIcon"]: if info.name == "power": iconFile = "pg_small" iconType = "gui" else: iconFile = info.icon.iconFile if info.icon else None iconType = "icons" if iconFile: self.imageId = fittingView.imageList.GetImageIndex( iconFile, iconType) self.bitmap = BitmapLoader.getBitmap(iconFile, iconType) else: self.imageId = -1 self.mask = wx.LIST_MASK_IMAGE else: self.imageId = -1 if params["displayName"] or self.imageId == -1: self.columnText = info.displayName if info.displayName != "" else info.name self.mask |= wx.LIST_MASK_IMAGE if params["direct"]: self.direct = True self.view = fittingView originalRefresh = fittingView.refresh sMkt = Market.getInstance() def refresh(stuff): # Hack into our master view and add a callback for ourselves to know when to query self.directInfo = sMkt.directAttrRequest( stuff, info) if stuff else None originalRefresh(stuff) fittingView.refresh = refresh
def getLocalizedEnvironments(self): sMkt = Market.getInstance() grp = sMkt.getGroup("Abyssal Hazards") grouped = dict() for beacon in grp.items: if not beacon.isType('projected'): continue # Localized effects, currently, have a name like "(size) (type) Cloud" # Until this inevitably changes, do a simple split name_parts = beacon.name.split(" ") key = name_parts[1].strip() if key not in grouped: grouped[key] = set() grouped[key].add((beacon, beacon.name, beacon.name)) return grouped, ()
def getPrices(self, objitems, callback, waitforthread=False): """Get prices for multiple typeIDs""" requests = [] sMkt = Market.getInstance() for objitem in objitems: item = sMkt.getItem(objitem) requests.append(item.price) def cb(): try: callback(requests) except Exception as e: pyfalog.critical("Callback failed.") pyfalog.critical(e) db.commit() if waitforthread: self.priceWorkerThread.setToWait(requests, cb) else: self.priceWorkerThread.trigger(requests, cb)
def stage2(self, event): # back = event.back # if not back: # self.browseHist.append( (1,0) ) self._lastStage = self._activeStage self._activeStage = 2 categoryID = event.categoryID self.lastdata = categoryID self.lpane.ShowLoading() self.lpane.RemoveAllChildren() sMkt = Market.getInstance() sMkt.getShipListDelayed(categoryID, self.stage2Callback) self._stage2Data = categoryID self.navpanel.ShowNewFitButton(False) self.navpanel.ShowSwitchEmptyGroupsButton(True)