From 9f949ff7e2dbd622bc7a7dfb9c3e42f1137bc17c Mon Sep 17 00:00:00 2001 From: DarkPhoenix Date: Thu, 21 Apr 2011 22:43:40 +0400 Subject: [PATCH] Rewrite market service, for now incompatible with UI --- service/market.py | 638 +++++++++++++++++++++++++++++++--------------- 1 file changed, 438 insertions(+), 200 deletions(-) diff --git a/service/market.py b/service/market.py index ecb26cae5..fde757b1e 100644 --- a/service/market.py +++ b/service/market.py @@ -17,21 +17,34 @@ # along with pyfa. If not, see . #=============================================================================== +import threading +import traceback +import wx + +from sqlalchemy.orm.exc import NoResultFound +import sqlalchemy.sql +import sqlalchemy.orm +import Queue + import eos.db import eos.types import eos.saveddata -import wx -import threading -from sqlalchemy.orm.exc import NoResultFound -import Queue -import traceback -import sqlalchemy.sql -import sqlalchemy.orm + +try: + from collections import OrderedDict +except ImportError: + from gui.utils.compat import OrderedDict + +# Event which tells threads dependent on Market that it's initialized +mktRdy = threading.Event() class ShipBrowserWorkerThread(threading.Thread): def run(self): self.queue = Queue.Queue() self.cache = {} + # Wait for full market initialization (otherwise there's high riskjy + # this thread will attempt to init Market which is already being inited) + mktRdy.wait(5) self.processRequests() def processRequests(self): @@ -64,7 +77,7 @@ class PriceWorkerThread(threading.Thread): queue = self.queue while True: try: - # Grab our data and rerelease the lock + # Grab our data and re-release the lock callback, requests = queue.get() # Grab prices, this is the time-consuming part @@ -121,161 +134,337 @@ class SearchWorkerThread(threading.Thread): class Market(): instance = None - FORCEPUBLISHED_SHIPS = ("Ibis", "Impairor", "Velator", "Reaper") - FORCEPUBLISHED_GROUPS = ("Rookie ship") - FORCED_ITEM_MKTGRPS = { 2080: (648, 1), 2083: (712, 1), 2212: (924, 1), 2838: (977, 1), 2948: (1310, 1), 3149: (1156, 1), - 3150: (1156, 1), 3151: (1156, 1), 4579: (1050, 1), 4621: (1051, 3), 20358: (1152, 3), 20371: (1189, 3), - 20443: (1163, 3), 20700: (1187, 3), 21606: (1185, 3), 22325: (714, 1), 22327: (714, 1), 22329: (714, 1), - 22331: (714, 1), 22333: (714, 1), 22335: (714, 1), 22337: (714, 1), 22339: (714, 1), 22715: (620, 4), - 22760: (618, 4), 22921: (1039, 3), 22923: (1039, 3), 24663: (1176, 1), 24669: (1157, 3), 25867: (1186, 3), - 25868: (1180, 3), 27204: (1156, 1), 27205: (1156, 1), 27206: (1156, 1), 27213: (1154, 1), 27214: (1154, 1), - 27215: (1154, 1), 27216: (1152, 1), 27217: (1152, 1), 27218: (1152, 1), 27219: (1160, 1), 27220: (1160, 1), - 27221: (1160, 1), 28513: (644, 4), 30328: (760, 1), 30342: (760, 1), 30420: (760, 1), 30422: (760, 1), - 30424: (760, 1), 30839: (760, 1), 32248: (977, 4), 32254: (1185, 4), 32255: (1167, 4), 32413: (679, 4), - 32416: (680, 4), 32417: (680, 4), 32459: (760, 1), 32461: (760, 1), 32463: (920, 1), 32465: (837, 1), - 32467: (760, 1), 32469: (760, 1) } - META_MAP = {"normal": (1, 2, 14), - "faction": (4, 3), - "complex": (6,), - "officer": (5,)} - SEARCH_CATEGORIES = ("Drone", "Module", "Subsystem", "Charge", "Implant") + def __init__(self): + #self.activeMetas = set() + self.priceCache = {} + + # Start price fetcher + self.priceWorkerThread = PriceWorkerThread() + self.priceWorkerThread.daemon = True + self.priceWorkerThread.start() + + # Thread which handles search + self.searchWorkerThread = SearchWorkerThread() + self.searchWorkerThread.daemon = True + self.searchWorkerThread.start() + + # Ship browser helper thread + self.shipBrowserWorkerThread = ShipBrowserWorkerThread() + self.shipBrowserWorkerThread.daemon = True + self.shipBrowserWorkerThread.start() + + # Items' group overrides + self.customGroups = set() + # Limited edition ships + self.les_grp = eos.types.Group() + self.les_grp.ID = -1 + self.les_grp.name = "Limited Issue Ships" + self.les_grp.published = True + ships = self.getCategory("Ship") + self.les_grp.category = ships + self.les_grp.categoryID = ships.ID + self.les_grp.description = "" + # TODO: fetch proper icon for LES group + self.les_grp.icon = None + self.ITEMS_FORCEGROUP = { + "Opux Luxury Yacht": self.les_grp, # One of those is wedding present at CCP fanfest, another was hijacked from ISD guy during an event + "Silver Magnate": self.les_grp, # Amarr Championship prize + "Gold Magnate": self.les_grp, # Amarr Championship prize + "Armageddon Imperial Issue": self.les_grp, # Amarr Championship prize + "Apocalypse Imperial Issue": self.les_grp, # Amarr Championship prize + "Guardian-Vexor": self.les_grp, # Illegal rewards for the Gallente Frontier Tour Lines event arc + "Megathron Federate Issue": self.les_grp, # Reward during Crielere event + "Raven State Issue": self.les_grp, # AT4 prize + "Tempest Tribal Issue": self.les_grp, # AT4 prize + "Apotheosis": self.les_grp, # 5th EVE anniversary present + "Zephyr": self.les_grp, # 2010 new year gift + # TODO: check to which group assign iris + #"Prototype Iris Probe Launcher", # 2010 new year gift + "Primae": self.les_grp, # Promotion of planetary interaction + "Freki": self.les_grp, # AT7 prize + "Mimir": self.les_grp, # AT7 prize + "Utu": self.les_grp, # AT8 prize + "Adrestia": self.les_grp, # AT8 prize + "Echelon": self.les_grp } # 2011 new year gift + self.ITEMS_FORCEGROUP_R = self.__makeRevDict(self.ITEMS_FORCEGROUP) + self.les_grp.items += list(self.getItem(itmn) for itmn in self.ITEMS_FORCEGROUP_R[self.les_grp]) + self.customGroups.add(self.les_grp) + + # List of items which are forcibly published or hidden + self.ITEMS_FORCEPUBLISHED = { + "Ibis": True, # Noobship + "Impairor": True, # Noobship + "Velator": True, # Noobship + "Reaper": True, # Noobship + "TEST Damage Mod": False, # Marked as published by CCP for whatever reason + "Shadow" : False, # Sansha fighter bomber + "Ghost Heavy Missile": False } # Missile used by sansha + + # List of groups which are forcibly published + self.GROUPS_FORCEPUBLISHED = { + "Prototype Exploration Ship": False, # We moved the only ship inside this group to other group anyway + "Rookie ship": True } # Group-container for published noobships + + # Dictionary of items with forced meta groups, uses following format: + # Item name: (metagroup name, parent type name) + self.ITEMS_FORCEDMETAGROUP = { + "'Habitat' Miner I": ("Storyline", "Miner I"), + "'Wild' Miner I": ("Storyline", "Miner I"), + "Medium Nano Armor Repair Unit I": ("Tech I", "Medium Armor Repairer I"), + "Large 'Reprieve' Vestment Reconstructer I": ("Storyline", "Large Armor Repairer I"), + "Khanid Navy Siege Missile Launcher": ("Faction", "Siege Missile Launcher I"), + "Dark Blood Tracking Disruptor": ("Faction", "Tracking Disruptor I"), + "True Sansha Tracking Disruptor": ("Faction", "Tracking Disruptor I"), + "Shadow Serpentis Remote Sensor Dampener": ("Faction", "Remote Sensor Dampener I") } + # Parent type name: set(item names) + self.ITEMS_FORCEDMETAGROUP_R = {} + for item, value in self.ITEMS_FORCEDMETAGROUP.items(): + parent = value[1] + if not parent in self.ITEMS_FORCEDMETAGROUP_R: + self.ITEMS_FORCEDMETAGROUP_R[parent] = set() + self.ITEMS_FORCEDMETAGROUP_R[parent].add(item) + # Dictionary of items with forced market group + self.ITEMS_FORCEDMARKETGROUP = { + "'Alpha' Codebreaker I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners + "'Codex' Codebreaker I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners + "'Daemon' Codebreaker I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners + "'Libram' Codebreaker I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners + "Akemon's Modified 'Noble' ZET5000": 1185, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 10 > Armor Implants + "Cerebral Accelerator": 977, # Implants & Boosters > Booster + "Civilian Ballistic Deflection Field": 760, # Ship Equipment > Civilian Modules + "Civilian Bloodclaw Light Missile": 920, # Ammunition & Charges > Missiles > Light Missiles > Standard Light Missiles + "Civilian Damage Control": 760, # Ship Equipment > Civilian Modules + "Civilian Explosion Dampening Field": 760, # Ship Equipment > Civilian Modules + "Civilian Heat Dissipation Field": 760, # Ship Equipment > Civilian Modules + "Civilian Hobgoblin": 837, # Drones > Combat Drones > Light Scout Drones + "Civilian Photon Scattering Field": 760, # Ship Equipment > Civilian Modules + "Civilian Remote Armor Repair System": 760, # Ship Equipment > Civilian Modules + "Civilian Remote Shield Transporter": 760, # Ship Equipment > Civilian Modules + "Civilian Standard Missile Launcher": 760, # Ship Equipment > Civilian Modules + "Civilian Stasis Webifier": 760, # Ship Equipment > Civilian Modules + "Civilian Warp Disruptor": 760, # Ship Equipment > Civilian Modules + "Hardwiring - Inherent Implants 'Gentry' ZEX10": 1152, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Armor Implants + "Hardwiring - Inherent Implants 'Gentry' ZEX100": 1152, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Armor Implants + "Hardwiring - Inherent Implants 'Gentry' ZEX1000": 1152, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Armor Implants + "Hardwiring - Inherent Implants 'Gentry' ZEX20": 1160, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 7 > Armor Implants + "Hardwiring - Inherent Implants 'Gentry' ZEX200": 1160, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 7 > Armor Implants + "Hardwiring - Inherent Implants 'Gentry' ZEX2000": 1160, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 7 > Armor Implants + "Hardwiring - Zainou 'Sharpshooter' ZMX10": 1156, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Missile Implants + "Hardwiring - Zainou 'Sharpshooter' ZMX100": 1156, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Missile Implants + "Hardwiring - Zainou 'Sharpshooter' ZMX1000": 1156, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Missile Implants + "Hardwiring - Zainou 'Sharpshooter' ZMX11": 1156, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Missile Implants + "Hardwiring - Zainou 'Sharpshooter' ZMX110": 1156, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Missile Implants + "Hardwiring - Zainou 'Sharpshooter' ZMX1100": 1156, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Missile Implants + "Hardwiring - Zainou 'Sprite' KXX1000": 1154, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Engineering Implants + "Hardwiring - Zainou 'Sprite' KXX2000": 1154, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Engineering Implants + "Hardwiring - Zainou 'Sprite' KXX500": 1154, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Engineering Implants + "Imperial Navy Modified 'Noble' Implant": 1185, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 10 > Armor Implants + "Imperial Special Ops Field Enhancer - Standard": 618, # Implants & Boosters > Implants > Attribute Enhancers > Implant Slot 1 + "Michi's Excavation Augmentor": 1187, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 10 > Industry Implants + "Nugoehuvi Synth Blue Pill Booster": 977, # Implants & Boosters > Booster + "Numon Family Heirloom": 1152, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Armor Implants + "Ogdin's Eye Coordination Enhancer": 1163, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 7 > Gunnery Implants + "Pashan's Turret Customization Mindlink": 1180, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 9 > Gunnery Implants + "Pashan's Turret Handling Mindlink": 1186, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 10 > Gunnery Implants + "Prototype Iris Probe Launcher": 712, # Ship Equipment > Turrets & Bays > Scan Probe Launchers + "Quafe Zero": 977, # Implants & Boosters > Booster + "Republic Special Ops Field Enhancer - Gamma": 620, # Implants & Boosters > Implants > Attribute Enhancers > Implant Slot 3 + "Sansha Modified 'Gnome' Implant": 1167, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 7 > Shield Implants + "Shaqil's Speed Enhancer": 1157, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 6 > Navigation Implants + "Sleeper Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners + "Talocan Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners + "Terran Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners + "Tetrimon Data Analyzer I": 714, # Ship Equipment > Electronics and Sensor Upgrades > Scanners > Data and Composition Scanners + "Whelan Machorin's Ballistic Smartlink": 1189, # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 10 > Missile Implants + "Zor's Custom Navigation Hyper-Link": 1176 } # Implants & Boosters > Implants > Skill Hardwiring > Implant Slot 8 > Navigation Implants + self.ITEMS_FORCEDMARKETGROUP_R = self.__makeRevDict(self.ITEMS_FORCEDMARKETGROUP) + + # Misc definitions + self.META_MAP = OrderedDict([("normal", (1, 2, 14)), + ("faction", (4, 3)), + ("complex", (6,)), + ("officer", (5,))]) + self.SEARCH_CATEGORIES = ("Drone", "Module", "Subsystem", "Charge", "Implant") + + # Tell other threads that Market is at their service + mktRdy.set() @classmethod def getInstance(cls): if cls.instance == None: cls.instance = Market() - return cls.instance - def __init__(self): - self.activeMetas = set() - self.priceCache = {} + def __makeRevDict(self, orig): + """Creates reverse dictionary""" + rev = {} + for item, value in orig.items(): + if not value in rev: + rev[value] = set() + rev[value].add(item) + return rev - self.priceWorkerThread = PriceWorkerThread() - self.priceWorkerThread.daemon = True - self.priceWorkerThread.start() + def getItem(self, identity, *args, **kwargs): + """Get item by its ID or name""" + if isinstance(identity, eos.types.Item): + return identity + elif isinstance(identity, (int, float, basestring)): + return eos.db.getItem(identity, *args, **kwargs) + else: + raise TypeError("Need Item object, integer, float or string as argument") - self.searchWorkerThread = SearchWorkerThread() - self.searchWorkerThread.daemon = True - self.searchWorkerThread.start() + def getGroup(self, identity, *args, **kwargs): + """Get group by its ID or name""" + if isinstance(identity, eos.types.Group): + return identity + elif isinstance(identity, (int, float, basestring)): + # Attempt to convert float to int + try: + id = int(identity) + except ValueError: + id = None + # Check custom groups + for cgrp in self.customGroups: + # During first comparison we need exact int, not float for matching + if cgrp.ID == id or cgrp.name == identity: + # Return first match + return cgrp + # Return eos group if everything else returned nothing + return eos.db.getGroup(identity, *args, **kwargs) + else: + raise TypeError("Need Group object, integer, float or string as argument") - self.shipBrowserWorkerThread = ShipBrowserWorkerThread() - self.shipBrowserWorkerThread.daemon = True - self.shipBrowserWorkerThread.start() + def getCategory(self, identity, *args, **kwargs): + """Get category by its ID or name""" + if isinstance(identity, eos.types.Category): + return identity + elif isinstance(identity, (int, float, basestring)): + return eos.db.getCategory(identity, *args, **kwargs) + else: + raise TypeError("Need Category object, integer, float or string as argument") - def getChildren(self, id): + def getMetaGroup(self, identity, *args, **kwargs): + """Get meta group by its ID or name""" + if isinstance(identity, eos.types.MetaGroup): + return identity + elif isinstance(identity, (int, float, basestring)): + return eos.db.getMetaGroup(identity, *args, **kwargs) + else: + raise TypeError("Need MetaGroup object, integer, float or string as argument") + + def getMarketGroup(self, identity, *args, **kwargs): + """Get market group by its ID""" + if isinstance(identity, eos.types.MarketGroup): + return identity + elif isinstance(identity, (int, float)): + return eos.db.getMarketGroup(identity, *args, **kwargs) + else: + raise TypeError("Need MarketGroup object, integer or float as argument") + + def getGroupByItem(self, item): + """Get group by item""" + if item.name in self.ITEMS_FORCEGROUP: + group = self.ITEMS_FORCEGROUP[item.name] + else: + group = item.group + return group + + def getMetaGroupByItem(self, item): + """Get meta group by item""" + # Check if item is in forced metagroup map + if item.name in self.ITEMS_FORCEDMETAGROUP: + # Create meta group from scratch + metaGroup = eos.types.MetaType() + # Get meta group info object based on meta group name + metaGroupInfo = self.getMetaGroup(self.ITEMS_FORCEDMETAGROUP[item.name][0]) + # Get parent item based on its name + parent = self.getItem(self.ITEMS_FORCEDMETAGROUP[item.name][1]) + # Assign all required for metaGroup variables + metaGroup.info = metaGroupInfo + metaGroup.items = item + metaGroup.parent = parent + metaGroup.metaGroupID = metaGroupInfo.ID + metaGroup.parentTypeID = parent.ID + metaGroup.typeID = item.ID + # If no forced meta group is provided, try to use item's + # meta group if any + else: + metaGroup = item.metaGroup + return metaGroup + + def getMarketGroupByItem(self, item): + """Get market group by item, its ID or name""" + # Check if we force market group for given item + if item.name in self.ITEMS_FORCEDMARKETGROUP: + mgid = self.ITEMS_FORCEDMARKETGROUP[item.name] + # Check if item itself has market group + elif item.marketGroupID: + mgid = item.marketGroupID + # If item doesn't have marketgroup, check if it has parent + # item and use its market group + elif self.getMetaGroupByItem(item.ID): + parent = self.getItem(self.getMetaGroupByItem(item.ID).parentTypeID) + mgid = parent.marketGroupID + else: + mgid = None + mg = self.getMarketGroup(mgid) + return mg + + def getParentItemByItem(self, item): + """Get parent item by item""" + mg = self.getMetaGroupByItem(item) + if mg: + parent = mg.parent + # Consider self as parent if item has no parent in database + else: + parent = item + return parent + + def getVariationsByItem(self, item): + """Get item variations by item, its ID or name""" + # Get parent item + parent = self.getParentItemByItem(item) + # All its variations + vars = eos.db.getVariations(parent) + # Combine both in the same list + vars.insert(0, parent) + # Check for overrides and add them if any + if parent.name in self.ITEMS_FORCEDMETAGROUP_R: + for itmn in self.ITEMS_FORCEDMETAGROUP_R[parent.name]: + vars.append(self.getItem(itmn)) + return vars + + def getGroupsByCategory(self, cat): + """Get groups from given category""" + groups = list(filter(lambda grp: self.getPublicityByGroup(grp), cat.groups)) + return groups + + def getMarketGroupChildren(self, mg): """ - Get the children of the group or marketGroup with the passed id. - Returns a list, where each element is a tuple containing: - the id, the name, the icon, wether the group has more children. + Get the children marketGroups of marketGroup with the passed id. + Returns a list, where each element is: + (id, name, icon, does it has child market groups or not) """ - - group = eos.db.getMarketGroup(id, eager="icon") children = [] - for child in group.children: - children.append((child.ID, child.name, self.figureIcon(child), not child.hasTypes)) - + for child in mg.children: + children.append((child.ID, child.name, self.getIconByMarketGroup(child), not child.hasTypes)) return children - def getShipRoot(self): - cat = eos.db.getCategory(6) - root = [(-1, "Limited Issue Ships")] - for grp in cat.groups: - if grp.published or grp.name in self.FORCEPUBLISHED_GROUPS: - root.append((grp.ID, grp.name)) - zephyr = eos.db.getGroup("Prototype Exploration Ship") - root.remove((zephyr.ID, zephyr.name)) - return root + def getItemsByMarketGroup(self, mg): + """Get items in the given market group""" + res = set() + baseitms = mg.items + if mg.ID in self.ITEMS_FORCEDMARKETGROUP_R: + baseitms += list(self.getItem(itmn) for itmn in self.ITEMS_FORCEDMARKETGROUP_R[mg.ID]) + for item in baseitms: + res.add(item) + vars = self.getVariationsByItem(item) + for var in vars: + res.add(var) + return res - - LIMITED_EDITION = ("Gold Magnate", "Silver Magnate", "Guardian-Vexor", - "Opux Luxury Yacht", "Armageddon Imperial Issue", - "Apocalypse Imperial Issue", "Raven State Issue", - "Megathron Federate Issue", "Tempest Tribal Issue", - "Apotheosis", "Zephyr", "Primae", "Mimir", "Freki", - "Adrestia", "Utu", "Echelon") - def getShipList(self, id): - ships = [] - if id == -1: - for name in self.LIMITED_EDITION: - item = eos.db.getItem(name) - ships.append((item.ID, item.name, item.race)) - - return ships - - grp = eos.db.getGroup(id, eager=("items", "items.marketGroup", "items.attributes")) - for item in grp.items: - if (item.published or item.name in self.FORCEPUBLISHED_SHIPS) and item.name not in self.LIMITED_EDITION: - ships.append((item.ID, item.name, item.race)) - - return ships - - def getShipListDelayed(self, id, callback): - self.shipBrowserWorkerThread.queue.put((id, callback)) - - def searchShips(self, name): - results = eos.db.searchItems(name) - ships = [] - for item in results: - if item.category.name == "Ship" and (item.published or item.name in self.FORCEPUBLISHED_SHIPS or item.name in self.LIMITED_EDITION): - ships.append((item.ID, item.name, item.race)) - - return ships - - def searchItems(self, name, callback): - self.searchWorkerThread.scheduleSearch(name, callback) - - def getImplantTree(self): - return self.getChildren(27) - - def getItem(self, itemId): - return eos.db.getItem(itemId) - - def getGroup(self, groupId): - return eos.db.getGroup(groupId) - - def getMarketGroup(self, marketGroupId): - return eos.db.getMarketGroup(marketGroupId) - - def getForcedMarketGroupID(self,itemID): - if itemID in self.FORCED_ITEM_MKTGRPS: - grpID,meta = self.FORCED_ITEM_MKTGRPS[itemID] - return grpID - return None - - def getMarketGroupName(self, item): - if item.marketGroup == None: - marketGroupID = self.getForcedMarketGroupID(item.ID) - marketGroup = self.getMarketGroup(marketGroupID) - groupName = marketGroup.name - else: - groupName = item.marketGroup.name - - return groupName - - MARKET_GROUPS = (9, #Modules - 1111, #Rigs - 157, #Drones - 11, #Ammo - 1112, #Subsystems - 24) #Implants & Boosters - - def getMarketRoot(self): - """ - Get the root of the market tree. - Returns a list, where each element is a tuple containing: - the ID, the name and the icon of the group - """ - - - root = [] - for id in self.MARKET_GROUPS: - mg = eos.db.getMarketGroup(id, eager="icon") - root.append((id, mg.name, self.figureIcon(mg))) - - return root - - def figureIcon(self, mg): + def getIconByMarketGroup(self, mg): + """Return icon associated to marketgroup""" if mg.icon: return mg.icon.iconFile else: @@ -283,67 +472,123 @@ class Market(): item = mg.items[0] return item.icon.iconFile if item.icon else "" elif len(mg.children) > 0: - return self.figureIcon(mg.children[0]) + return self.getIconByMarketGroup(mg.children[0]) else: return "" - def activateMetaGroup(self, name): - for meta in self.META_MAP[name]: - self.activeMetas.add(meta) + def getPublicityByItem(self, item): + """Return if an item is published""" + if item.name in self.ITEMS_FORCEPUBLISHED: + pub = self.ITEMS_FORCEPUBLISHED[item.name] + else: + pub = item.published + return pub - def disableMetaGroup(self, name): - for meta in self.META_MAP[name]: - if meta in self.activeMetas: - self.activeMetas.remove(meta) + def getPublicityByGroup(self, group): + """Return if an group is published""" + if group.name in self.GROUPS_FORCEPUBLISHED: + pub = self.GROUPS_FORCEPUBLISHED[group.name] + else: + pub = group.published + return pub - def isMetaIdActive(self, meta): - return meta in self.activeMetas + def getShipRoot(self): + cat = self.getCategory("Ship") + root = [] + for grp in self.getGroupsByCategory(cat): + root.append((grp.ID, grp.name)) + return root - def filterItems(self, items): - filtered = [] - activeMetas = self.activeMetas - for it in items: - if (it.metaGroup.ID if it.metaGroup is not None else 1) in activeMetas: - filtered.append(it) + ROOT_MARKET_GROUPS = (9, #Modules + 1111, #Rigs + 157, #Drones + 11, #Ammo + 1112, #Subsystems + 24) #Implants & Boosters - return filtered + def getMarketRoot(self): + """ + Get the root of the market tree. + Returns a list, where each element is a tuple containing: + the ID, the name and the icon of the group + """ + root = [] + for id in self.ROOT_MARKET_GROUPS: + mg = self.getMarketGroup(id, eager="icon") + root.append((id, mg.name, self.getIconByMarketGroup(mg))) - def getMetaName(self, metaId): - for name, ids in self.META_MAP.items(): - for id in ids: - if metaId == id: - return name + return root - def getVariations(self, marketGroupId): - if len(self.activeMetas) == 0: - return tuple() + def getShipList(self, grpid): + """Get ships for given group id""" + ships = [] + grp = self.getGroup(id, eager=("items", "items.marketGroup", "items.attributes")) + for item in grp.items: + if self.getPublicityByItem(item): + ships.append((item.ID, item.name, item.race)) + return ships - mg = eos.db.getMarketGroup(marketGroupId) - l = set() - populatedMetas = set() + def getShipListDelayed(self, id, callback): + """Background version of getShipList""" + self.shipBrowserWorkerThread.queue.put((id, callback)) - for item in mg.items: - populatedMetas.add(1) - if 1 in self.activeMetas: - l.add(item) + def searchShips(self, name): + """Find ships according to given text pattern""" + results = eos.db.searchItems(name) + ships = [] + for item in results: + if self.getGroupByItem(item).category.name == "Ship" and self.getPublicityByItem(item): + ships.append((item.ID, item.name, item.race)) + return ships - vars = eos.db.getVariations(item, eager=("icon", "metaGroup")) - for var in vars: - populatedMetas.add(var.metaGroup.ID) - if var.metaGroup.ID in self.activeMetas: - l.add(var) + def searchItems(self, name, callback): + """Find items according to given text pattern""" + self.searchWorkerThread.scheduleSearch(name, callback) - forceditemids = filter(lambda typeid: self.FORCED_ITEM_MKTGRPS[typeid][0] == marketGroupId, self.FORCED_ITEM_MKTGRPS) - forceditems = list(eos.db.getItem(typeID) for typeID in forceditemids) - for item in forceditems: - meta = self.FORCED_ITEM_MKTGRPS[item.ID][1] - populatedMetas.add(meta) - if meta in self.activeMetas: - l.add(item) + def directAttrRequest(self, items, attrID): + itemIDs = map(lambda i: i.ID, items) + info = {} + for ID, val in eos.db.directAttributeRequest(itemIDs, attrID): + info[ID] = val - return list(l), populatedMetas + return info + def getImplantTree(self): + """Return implant market group children""" + return self.getMarketGroupChildren(27) + +# def activateMetaGroup(self, name): +# for meta in self.META_MAP[name]: +# self.activeMetas.add(meta) +# +# def disableMetaGroup(self, name): +# for meta in self.META_MAP[name]: +# if meta in self.activeMetas: +# self.activeMetas.remove(meta) +# +# def isMetaIdActive(self, meta): +# return meta in self.activeMetas +# +# def filterItems(self, items): +# filtered = [] +# activeMetas = self.activeMetas +# for it in items: +# if (it.metaGroup.ID if it.metaGroup is not None else 1) in activeMetas: +# filtered.append(it) +# +# return filtered +# +# def getMetaName(self, metaId): +# for name, ids in self.META_MAP.items(): +# for id in ids: +# if metaId == id: +# return name + + ################################# + # Price stuff, didn't modify it # + ################################# def getPriceNow(self, typeID): + """Get price for provided typeID""" price = self.priceCache.get(typeID) if price is None: try: @@ -357,9 +602,11 @@ class Market(): return price def getPricesNow(self, typeIDs): + """Return map of calls to get price against list of typeIDs""" return map(self.getPrice, typeIDs) def getPrices(self, typeIDs, callback): + """Get prices for multiple typeIDs""" requests = [] for typeID in typeIDs: price = self.getPriceNow(typeID) @@ -373,12 +620,3 @@ class Market(): eos.db.commit() self.priceWorkerThread.trigger(requests, cb) - - def directRequest(self, items, attrID): - itemIDs = map(lambda i: i.ID, items) - info = {} - for ID, val in eos.db.directAttributeRequest(itemIDs, attrID): - info[ID] = val - - return info -