예제 #1
0
 def __init__(self):
     self.inventory = InventoryRequester()
     self.stats = StatsRequester()
     self.dossiers = DossierRequester()
     self.goodies = GoodiesRequester()
     self.shop = ShopRequester(self.goodies)
     self.__itemsCache = defaultdict(dict)
예제 #2
0
 def __init__(self):
     self.inventory = InventoryRequester()
     self.stats = StatsRequester()
     self.dossiers = DossierRequester()
     self.goodies = GoodiesRequester()
     self.shop = ShopRequester(self.goodies)
     self.recycleBin = RecycleBinRequester()
     self.__itemsCache = defaultdict(dict)
     self.__vehCustomStateCache = defaultdict(dict)
예제 #3
0
 def __init__(self):
     self.inventory = InventoryRequester()
     self.stats = StatsRequester()
     self.dossiers = DossierRequester()
     self.goodies = GoodiesRequester()
     self.shop = ShopRequester(self.goodies)
     self.__itemsCache = defaultdict(dict)
예제 #4
0
class ItemsRequester(object):
    """
    GUI items getting interface. Before using any method
    must be completed async server request (ItemsRequester.request).
    """
    ITEM_TYPES_MAPPING = {GUI_ITEM_TYPE.SHELL: Shell,
     GUI_ITEM_TYPE.EQUIPMENT: Equipment,
     GUI_ITEM_TYPE.OPTIONALDEVICE: OptionalDevice,
     GUI_ITEM_TYPE.GUN: VehicleGun,
     GUI_ITEM_TYPE.CHASSIS: VehicleChassis,
     GUI_ITEM_TYPE.TURRET: VehicleTurret,
     GUI_ITEM_TYPE.ENGINE: VehicleEngine,
     GUI_ITEM_TYPE.RADIO: VehicleRadio,
     GUI_ITEM_TYPE.VEHICLE: Vehicle,
     GUI_ITEM_TYPE.TANKMAN: Tankman}

    def __init__(self):
        self.inventory = InventoryRequester()
        self.stats = StatsRequester()
        self.dossiers = DossierRequester()
        self.goodies = GoodiesRequester()
        self.shop = ShopRequester(self.goodies)
        self.__itemsCache = defaultdict(dict)

    @async
    @process
    def request(self, callback = None):
        from gui.Scaleform.Waiting import Waiting
        Waiting.show('download/inventory')
        yield self.stats.request()
        yield self.inventory.request()
        Waiting.hide('download/inventory')
        Waiting.show('download/shop')
        yield self.shop.request()
        Waiting.hide('download/shop')
        Waiting.show('download/dossier')
        yield self.dossiers.request()
        Waiting.hide('download/dossier')
        Waiting.show('download/discounts')
        yield self.goodies.request()
        Waiting.hide('download/discounts')
        callback(self)

    def isSynced(self):
        return self.stats.isSynced() and self.inventory.isSynced() and self.shop.isSynced() and self.dossiers.isSynced() and self.goodies.isSynced()

    @async
    @process
    def requestUserDossier(self, databaseID, callback):
        dr = self.dossiers.getUserDossierRequester(databaseID)
        userAccDossier = yield dr.getAccountDossier()
        clanInfo = yield dr.getClanInfo()
        seasons = yield dr.getRated7x7Seasons()
        container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER]
        container[databaseID] = (userAccDossier, clanInfo, seasons)
        callback((userAccDossier, clanInfo, dr.isHidden))

    def unloadUserDossier(self, databaseID):
        container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER]
        if databaseID in container:
            del container[databaseID]
            self.dossiers.closeUserDossier(databaseID)

    @async
    @process
    def requestUserVehicleDossier(self, databaseID, vehTypeCompDescr, callback):
        dr = self.dossiers.getUserDossierRequester(databaseID)
        userVehDossier = yield dr.getVehicleDossier(vehTypeCompDescr)
        container = self.__itemsCache[GUI_ITEM_TYPE.VEHICLE_DOSSIER]
        container[databaseID, vehTypeCompDescr] = userVehDossier
        callback(userVehDossier)

    def clear(self):
        while len(self.__itemsCache):
            _, cache = self.__itemsCache.popitem()
            cache.clear()

        self.inventory.clear()
        self.shop.clear()
        self.stats.clear()
        self.dossiers.clear()
        self.goodies.clear()

    def invalidateCache(self, diff = None):
        invalidate = defaultdict(set)
        if diff is None:
            LOG_DEBUG('Gui items cache full invalidation')
            for itemTypeID, cache in self.__itemsCache.iteritems():
                if itemTypeID not in (GUI_ITEM_TYPE.ACCOUNT_DOSSIER, GUI_ITEM_TYPE.VEHICLE_DOSSIER):
                    cache.clear()

        else:
            for statName, data in diff.get('stats', {}).iteritems():
                if statName == 'unlocks':
                    self._invalidateUnlocks(data, invalidate)
                elif statName == 'eliteVehicles':
                    invalidate[GUI_ITEM_TYPE.VEHICLE].update(data)
                elif statName in ('vehTypeXP', 'vehTypeLocks'):
                    invalidate[GUI_ITEM_TYPE.VEHICLE].update(data.keys())
                elif statName in (('multipliedXPVehs', '_r'),):
                    inventoryVehiclesCDs = map(lambda v: vehicles.getVehicleTypeCompactDescr(v['compDescr']), self.inventory.getItems(GUI_ITEM_TYPE.VEHICLE).itervalues())
                    invalidate[GUI_ITEM_TYPE.VEHICLE].update(inventoryVehiclesCDs)

            for cacheType, data in diff.get('cache', {}).iteritems():
                if cacheType == 'vehsLock':
                    for id in data.keys():
                        vehData = self.inventory.getVehicleData(_getDiffID(id))
                        if vehData is not None:
                            invalidate[GUI_ITEM_TYPE.VEHICLE].add(vehData.descriptor.type.compactDescr)

            for itemTypeID, itemsDiff in diff.get('inventory', {}).iteritems():
                if itemTypeID == GUI_ITEM_TYPE.VEHICLE:
                    if 'compDescr' in itemsDiff:
                        for strCD in itemsDiff['compDescr'].itervalues():
                            if strCD is not None:
                                invalidate[itemTypeID].add(vehicles.getVehicleTypeCompactDescr(strCD))

                    for data in itemsDiff.itervalues():
                        for id in data.iterkeys():
                            vehData = self.inventory.getVehicleData(_getDiffID(id))
                            if vehData is not None:
                                invalidate[itemTypeID].add(vehData.descriptor.type.compactDescr)
                                invalidate[GUI_ITEM_TYPE.TANKMAN].update(self.__getTankmenIDsForVehicle(vehData))

                elif itemTypeID == GUI_ITEM_TYPE.TANKMAN:
                    for data in itemsDiff.itervalues():
                        invalidate[itemTypeID].update(data.keys())
                        for id in data.keys():
                            tmanInvID = _getDiffID(id)
                            tmanData = self.inventory.getTankmanData(tmanInvID)
                            if tmanData is not None and tmanData.vehicle != -1:
                                invalidate[GUI_ITEM_TYPE.VEHICLE].update(self.__getVehicleCDForTankman(tmanData))
                                invalidate[GUI_ITEM_TYPE.TANKMAN].update(self.__getTankmenIDsForTankman(tmanData))

                elif itemTypeID == GUI_ITEM_TYPE.SHELL:
                    invalidate[itemTypeID].update(itemsDiff.keys())
                    for shellIntCD in itemsDiff.iterkeys():
                        for vehicle in self.inventory.getItems(GUI_ITEM_TYPE.VEHICLE).itervalues():
                            shells = vehicle['shells']
                            for intCD, _, _ in LayoutIterator(shells):
                                if shellIntCD == intCD:
                                    vehicleIntCD = vehicles.getVehicleTypeCompactDescr(vehicle['compDescr'])
                                    invalidate[GUI_ITEM_TYPE.VEHICLE].add(vehicleIntCD)
                                    vehicelData = self.inventory.getItemData(vehicleIntCD)
                                    gunIntCD = vehicelData.descriptor.gun['compactDescr']
                                    invalidate[GUI_ITEM_TYPE.GUN].add(gunIntCD)

                else:
                    invalidate[itemTypeID].update(itemsDiff.keys())

            for itemTypeID, uniqueIDs in invalidate.iteritems():
                self._invalidateItems(itemTypeID, uniqueIDs)

        return invalidate

    def getVehicle(self, vehInvID):
        vehInvData = self.inventory.getVehicleData(vehInvID)
        if vehInvData is not None:
            return self.__makeVehicle(vehInvData.descriptor.type.compactDescr, vehInvData)
        else:
            return

    def getTankman(self, tmanInvID):
        tmanInvData = self.inventory.getTankmanData(tmanInvID)
        if tmanInvData is not None:
            return self.__makeTankman(tmanInvID, tmanInvData)
        else:
            return

    def getItems(self, itemTypeID = None, criteria = REQ_CRITERIA.EMPTY, nationID = None):
        shopParser = ShopDataParser(self.shop.getItemsData())
        result = ItemsCollection()
        if not isinstance(itemTypeID, tuple):
            itemTypeID = (itemTypeID,)
        for typeID in itemTypeID:
            for intCD, _, _, _ in shopParser.getItemsIterator(nationID=nationID, itemTypeID=typeID):
                item = self.getItemByCD(intCD)
                if criteria(item):
                    result[intCD] = item

        return result

    def getTankmen(self, criteria = REQ_CRITERIA.EMPTY):
        result = ItemsCollection()
        tmanInvData = self.inventory.getItemsData(GUI_ITEM_TYPE.TANKMAN)
        for invID, invData in tmanInvData.iteritems():
            item = self.__makeTankman(invID, invData)
            if criteria(item):
                result[invID] = item

        return result

    def getVehicles(self, criteria = REQ_CRITERIA.EMPTY):
        return self.getItems(GUI_ITEM_TYPE.VEHICLE, criteria=criteria)

    def getItemByCD(self, typeCompDescr):
        """
        Trying to return item from inventory by item int
        compact descriptor, otherwise - from shop.
        
        @param typeCompDescr: item int compact descriptor
        @return: item object
        """
        if getTypeOfCompactDescr(typeCompDescr) == GUI_ITEM_TYPE.VEHICLE:
            return self.__makeVehicle(typeCompDescr)
        return self.__makeSimpleItem(typeCompDescr)

    def getItem(self, itemTypeID, nationID, innationID):
        """
        Returns item from inventory by given criteria or
        from shop.
        
        @param itemTypeID: item type index from common.items.ITEM_TYPE_NAMES
        @param nationID: nation index from nations.NAMES
        @param innationID: item index within its nation
        @return: gui item
        """
        typeCompDescr = vehicles.makeIntCompactDescrByID(GUI_ITEM_TYPE_NAMES[itemTypeID], nationID, innationID)
        if itemTypeID == GUI_ITEM_TYPE.VEHICLE:
            return self.__makeVehicle(typeCompDescr)
        return self.__makeSimpleItem(typeCompDescr)

    def getTankmanDossier(self, tmanInvID):
        """
        Returns tankman dossier item by given tankman
        inventory id
        
        @param tmanInvID: tankman inventory id
        @return: TankmanDossier object
        """
        tankman = self.getTankman(tmanInvID)
        tmanDossierDescr = self.__getTankmanDossierDescr(tmanInvID)
        currentVehicleItem = None
        if tankman.isInTank:
            extDossier = self.getVehicleDossier(tankman.vehicleDescr.type.compactDescr)
            currentVehicleItem = self.getItemByCD(tankman.vehicleDescr.type.compactDescr)
        else:
            extDossier = self.getAccountDossier()
        return TankmanDossier(tankman.descriptor, tmanDossierDescr, extDossier, currentVehicleItem=currentVehicleItem)

    def getVehicleDossier(self, vehTypeCompDescr, databaseID = None):
        """
        Returns vehicle dossier item by given vehicle type
        int compact descriptor
        
        @param vehTypeCompDescr: vehicle type in compact descriptor
        @return: VehicleDossier object
        """
        if databaseID is None:
            return VehicleDossier(self.__getVehicleDossierDescr(vehTypeCompDescr), vehTypeCompDescr)
        container = self.__itemsCache[GUI_ITEM_TYPE.VEHICLE_DOSSIER]
        dossier = container.get((int(databaseID), vehTypeCompDescr))
        if dossier is None:
            LOG_WARNING('Vehicle dossier for this user is empty', vehTypeCompDescr, databaseID)
            return
        else:
            return VehicleDossier(dossier, vehTypeCompDescr, playerDBID=databaseID)

    def getAccountDossier(self, databaseID = None):
        """
        Returns account dossier item
        @return: AccountDossier object
        """
        if databaseID is None:
            from gui.clubs.ClubsController import g_clubsCtrl
            dossierDescr = self.__getAccountDossierDescr()
            seasonDossiers = dict(((s.getSeasonID(), s.getDossierDescr()) for s in g_clubsCtrl.getSeasons()))
            return AccountDossier(dossierDescr, rated7x7Seasons=seasonDossiers)
        container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER]
        dossier, _, seasons = container.get(int(databaseID))
        if dossier is None:
            LOG_WARNING('Trying to get empty user dossier', databaseID)
            return
        else:
            return AccountDossier(dossier, databaseID, seasons)

    def getClanInfo(self, databaseID = None):
        if databaseID is None:
            return (self.stats.clanDBID, self.stats.clanInfo)
        container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER]
        _, clanInfo, _ = container.get(int(databaseID))
        if clanInfo is None:
            LOG_WARNING('Trying to get empty user clan info', databaseID)
            return
        else:
            return clanInfo

    def getPreviousItem(self, itemTypeID, invDataIdx):
        itemData = self.inventory.getPreviousItem(itemTypeID, invDataIdx)
        return self.__makeItem(itemTypeID, invDataIdx, strCompactDescr=itemData.compDescr, inventoryID=itemData.invID, proxy=self)

    def _invalidateItems(self, itemTypeID, uniqueIDs):
        cache = self.__itemsCache[itemTypeID]
        for uid in uniqueIDs:
            invRes = self.inventory.invalidateItem(itemTypeID, uid)
            if uid in cache:
                LOG_DEBUG('Item marked as invalid', uid, cache[uid], invRes)
                del cache[uid]
            else:
                LOG_DEBUG('No cached item', uid, invRes)

    def _invalidateUnlocks(self, unlocked, result):
        vehInCache = self.__itemsCache[GUI_ITEM_TYPE.VEHICLE]
        for itemCD in unlocked:
            itemTypeID = getTypeOfCompactDescr(itemCD)
            if itemTypeID == GUI_ITEM_TYPE.VEHICLE:
                result[itemTypeID].add(itemCD)
                if itemCD in vehInCache:
                    self._invalidateUnlocks(vehInCache[itemCD].getAutoUnlockedItems(), result)
            elif itemTypeID in GUI_ITEM_TYPE.VEHICLE_MODULES:
                result[itemTypeID].add(itemCD)
            elif itemTypeID != GUI_ITEM_TYPE.FUEL_TANK:
                LOG_WARNING('Item is not vehicle or module', itemTypeID)

    def __getAccountDossierDescr(self):
        """
        @return: account descriptor
        """
        return dossiers2.getAccountDossierDescr(self.stats.accountDossier)

    def __getTankmanDossierDescr(self, tmanInvID):
        """
        @param tmanInvID: tankman inventory id
        @return: tankman dossier descriptor
        """
        tmanData = self.inventory.getTankmanData(tmanInvID)
        if tmanData is not None:
            return dossiers2.getTankmanDossierDescr(tmanData.descriptor.dossierCompactDescr)
        else:
            return dossiers2.getTankmanDossierDescr()

    def __getVehicleDossierDescr(self, vehTypeCompDescr):
        """
        @param vehTypeCompDescr: vehicle type int compact descriptor
        @return : vehicle dossier descriptor
        """
        return dossiers2.getVehicleDossierDescr(self.dossiers.getVehicleDossier(vehTypeCompDescr))

    def __makeItem(self, itemTypeIdx, uid, *args, **kwargs):
        container = self.__itemsCache[itemTypeIdx]
        if uid in container:
            return container[uid]
        else:
            item = None
            cls = ItemsRequester.ITEM_TYPES_MAPPING.get(itemTypeIdx)
            if cls is not None:
                container[uid] = item = cls(*args, **kwargs)
            return item

    def __makeVehicle(self, typeCompDescr, vehInvData = None):
        vehInvData = vehInvData or self.inventory.getItemData(typeCompDescr)
        if vehInvData is not None:
            return self.__makeItem(GUI_ITEM_TYPE.VEHICLE, typeCompDescr, strCompactDescr=vehInvData.compDescr, inventoryID=vehInvData.invID, proxy=self)
        else:
            return self.__makeItem(GUI_ITEM_TYPE.VEHICLE, typeCompDescr, typeCompDescr=typeCompDescr, proxy=self)

    def __makeTankman(self, tmanInvID, tmanInvData = None):
        tmanInvData = tmanInvData or self.inventory.getTankmanData(tmanInvID)
        if tmanInvData is not None:
            vehicle = None
            if tmanInvData.vehicle > 0:
                vehicle = self.getVehicle(tmanInvData.vehicle)
            return self.__makeItem(GUI_ITEM_TYPE.TANKMAN, tmanInvID, strCompactDescr=tmanInvData.compDescr, inventoryID=tmanInvID, vehicle=vehicle, proxy=self)
        else:
            return

    def __makeSimpleItem(self, typeCompDescr):
        return self.__makeItem(getTypeOfCompactDescr(typeCompDescr), typeCompDescr, intCompactDescr=typeCompDescr, proxy=self)

    def __getTankmenIDsForVehicle(self, vehData):
        vehTmanIDs = set()
        for tmanInvID in vehData.crew:
            if tmanInvID is not None:
                vehTmanIDs.add(tmanInvID)

        return vehTmanIDs

    def __getTankmenIDsForTankman(self, tmanData):
        vehData = self.inventory.getVehicleData(tmanData.vehicle)
        if vehData is not None:
            return self.__getTankmenIDsForVehicle(vehData)
        else:
            return set()

    def __getVehicleCDForTankman(self, tmanData):
        vehData = self.inventory.getVehicleData(tmanData.vehicle)
        if vehData is not None:
            return {vehData.descriptor.type.compactDescr}
        else:
            return set()
예제 #5
0
class ItemsRequester(object):
    """
    GUI items getting interface. Before using any method
    must be completed async server request (ItemsRequester.request).
    """
    ITEM_TYPES_MAPPING = {
        GUI_ITEM_TYPE.SHELL: Shell,
        GUI_ITEM_TYPE.EQUIPMENT: Equipment,
        GUI_ITEM_TYPE.OPTIONALDEVICE: OptionalDevice,
        GUI_ITEM_TYPE.GUN: VehicleGun,
        GUI_ITEM_TYPE.CHASSIS: VehicleChassis,
        GUI_ITEM_TYPE.TURRET: VehicleTurret,
        GUI_ITEM_TYPE.ENGINE: VehicleEngine,
        GUI_ITEM_TYPE.RADIO: VehicleRadio,
        GUI_ITEM_TYPE.VEHICLE: Vehicle,
        GUI_ITEM_TYPE.TANKMAN: Tankman
    }

    def __init__(self):
        self.inventory = InventoryRequester()
        self.stats = StatsRequester()
        self.dossiers = DossierRequester()
        self.goodies = GoodiesRequester()
        self.shop = ShopRequester(self.goodies)
        self.__itemsCache = defaultdict(dict)

    @async
    @process
    def request(self, callback=None):
        from gui.Scaleform.Waiting import Waiting
        Waiting.show('download/inventory')
        yield self.stats.request()
        yield self.inventory.request()
        Waiting.hide('download/inventory')
        Waiting.show('download/shop')
        yield self.shop.request()
        Waiting.hide('download/shop')
        Waiting.show('download/dossier')
        yield self.dossiers.request()
        Waiting.hide('download/dossier')
        Waiting.show('download/discounts')
        yield self.goodies.request()
        Waiting.hide('download/discounts')
        callback(self)

    def isSynced(self):
        return self.stats.isSynced() and self.inventory.isSynced(
        ) and self.shop.isSynced() and self.dossiers.isSynced(
        ) and self.goodies.isSynced()

    @async
    @process
    def requestUserDossier(self, databaseID, callback):
        dr = self.dossiers.getUserDossierRequester(databaseID)
        userAccDossier = yield dr.getAccountDossier()
        clanInfo = yield dr.getClanInfo()
        seasons = yield dr.getRated7x7Seasons()
        container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER]
        container[databaseID] = (userAccDossier, clanInfo, seasons)
        callback((userAccDossier, clanInfo, dr.isHidden))

    def unloadUserDossier(self, databaseID):
        container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER]
        if databaseID in container:
            del container[databaseID]
            self.dossiers.closeUserDossier(databaseID)

    @async
    @process
    def requestUserVehicleDossier(self, databaseID, vehTypeCompDescr,
                                  callback):
        dr = self.dossiers.getUserDossierRequester(databaseID)
        userVehDossier = yield dr.getVehicleDossier(vehTypeCompDescr)
        container = self.__itemsCache[GUI_ITEM_TYPE.VEHICLE_DOSSIER]
        container[databaseID, vehTypeCompDescr] = userVehDossier
        callback(userVehDossier)

    def clear(self):
        while len(self.__itemsCache):
            _, cache = self.__itemsCache.popitem()
            cache.clear()

        self.inventory.clear()
        self.shop.clear()
        self.stats.clear()
        self.dossiers.clear()
        self.goodies.clear()

    def invalidateCache(self, diff=None):
        invalidate = defaultdict(set)
        if diff is None:
            LOG_DEBUG('Gui items cache full invalidation')
            for itemTypeID, cache in self.__itemsCache.iteritems():
                if itemTypeID not in (GUI_ITEM_TYPE.ACCOUNT_DOSSIER,
                                      GUI_ITEM_TYPE.VEHICLE_DOSSIER):
                    cache.clear()

        else:
            for statName, data in diff.get('stats', {}).iteritems():
                if statName == 'unlocks':
                    self._invalidateUnlocks(data, invalidate)
                elif statName == 'eliteVehicles':
                    invalidate[GUI_ITEM_TYPE.VEHICLE].update(data)
                elif statName in ('vehTypeXP', 'vehTypeLocks'):
                    invalidate[GUI_ITEM_TYPE.VEHICLE].update(data.keys())
                elif statName in (('multipliedXPVehs', '_r'), ):
                    inventoryVehiclesCDs = map(
                        lambda v: vehicles.getVehicleTypeCompactDescr(v[
                            'compDescr']),
                        self.inventory.getItems(
                            GUI_ITEM_TYPE.VEHICLE).itervalues())
                    invalidate[GUI_ITEM_TYPE.VEHICLE].update(
                        inventoryVehiclesCDs)

            for cacheType, data in diff.get('cache', {}).iteritems():
                if cacheType == 'vehsLock':
                    for id in data.keys():
                        vehData = self.inventory.getVehicleData(_getDiffID(id))
                        if vehData is not None:
                            invalidate[GUI_ITEM_TYPE.VEHICLE].add(
                                vehData.descriptor.type.compactDescr)

            for itemTypeID, itemsDiff in diff.get('inventory', {}).iteritems():
                if itemTypeID == GUI_ITEM_TYPE.VEHICLE:
                    if 'compDescr' in itemsDiff:
                        for strCD in itemsDiff['compDescr'].itervalues():
                            if strCD is not None:
                                invalidate[itemTypeID].add(
                                    vehicles.getVehicleTypeCompactDescr(strCD))

                    for data in itemsDiff.itervalues():
                        for id in data.iterkeys():
                            vehData = self.inventory.getVehicleData(
                                _getDiffID(id))
                            if vehData is not None:
                                invalidate[itemTypeID].add(
                                    vehData.descriptor.type.compactDescr)
                                invalidate[GUI_ITEM_TYPE.TANKMAN].update(
                                    self.__getTankmenIDsForVehicle(vehData))

                elif itemTypeID == GUI_ITEM_TYPE.TANKMAN:
                    for data in itemsDiff.itervalues():
                        invalidate[itemTypeID].update(data.keys())
                        for id in data.keys():
                            tmanInvID = _getDiffID(id)
                            tmanData = self.inventory.getTankmanData(tmanInvID)
                            if tmanData is not None and tmanData.vehicle != -1:
                                invalidate[GUI_ITEM_TYPE.VEHICLE].update(
                                    self.__getVehicleCDForTankman(tmanData))
                                invalidate[GUI_ITEM_TYPE.TANKMAN].update(
                                    self.__getTankmenIDsForTankman(tmanData))

                elif itemTypeID == GUI_ITEM_TYPE.SHELL:
                    invalidate[itemTypeID].update(itemsDiff.keys())
                    for shellIntCD in itemsDiff.iterkeys():
                        for vehicle in self.inventory.getItems(
                                GUI_ITEM_TYPE.VEHICLE).itervalues():
                            shells = vehicle['shells']
                            for intCD, _, _ in LayoutIterator(shells):
                                if shellIntCD == intCD:
                                    vehicleIntCD = vehicles.getVehicleTypeCompactDescr(
                                        vehicle['compDescr'])
                                    invalidate[GUI_ITEM_TYPE.VEHICLE].add(
                                        vehicleIntCD)
                                    vehicelData = self.inventory.getItemData(
                                        vehicleIntCD)
                                    gunIntCD = vehicelData.descriptor.gun[
                                        'compactDescr']
                                    invalidate[GUI_ITEM_TYPE.GUN].add(gunIntCD)

                else:
                    invalidate[itemTypeID].update(itemsDiff.keys())

            for itemTypeID, uniqueIDs in invalidate.iteritems():
                self._invalidateItems(itemTypeID, uniqueIDs)

        return invalidate

    def getVehicle(self, vehInvID):
        vehInvData = self.inventory.getVehicleData(vehInvID)
        if vehInvData is not None:
            return self.__makeVehicle(vehInvData.descriptor.type.compactDescr,
                                      vehInvData)

    def getTankman(self, tmanInvID):
        tmanInvData = self.inventory.getTankmanData(tmanInvID)
        if tmanInvData is not None:
            return self.__makeTankman(tmanInvID, tmanInvData)

    def getItems(self,
                 itemTypeID=None,
                 criteria=REQ_CRITERIA.EMPTY,
                 nationID=None):
        shopParser = ShopDataParser(self.shop.getItemsData())
        result = ItemsCollection()
        if not isinstance(itemTypeID, tuple):
            itemTypeID = (itemTypeID, )
        for typeID in itemTypeID:
            for intCD, _, _, _ in shopParser.getItemsIterator(
                    nationID=nationID, itemTypeID=typeID):
                item = self.getItemByCD(intCD)
                if criteria(item):
                    result[intCD] = item

        return result

    def getTankmen(self, criteria=REQ_CRITERIA.EMPTY):
        result = ItemsCollection()
        tmanInvData = self.inventory.getItemsData(GUI_ITEM_TYPE.TANKMAN)
        for invID, invData in tmanInvData.iteritems():
            item = self.__makeTankman(invID, invData)
            if criteria(item):
                result[invID] = item

        return result

    def getVehicles(self, criteria=REQ_CRITERIA.EMPTY):
        return self.getItems(GUI_ITEM_TYPE.VEHICLE, criteria=criteria)

    def getItemByCD(self, typeCompDescr):
        """
        Trying to return item from inventory by item int
        compact descriptor, otherwise - from shop.
        
        @param typeCompDescr: item int compact descriptor
        @return: item object
        """
        if getTypeOfCompactDescr(typeCompDescr) == GUI_ITEM_TYPE.VEHICLE:
            return self.__makeVehicle(typeCompDescr)
        return self.__makeSimpleItem(typeCompDescr)

    def getItem(self, itemTypeID, nationID, innationID):
        """
        Returns item from inventory by given criteria or
        from shop.
        
        @param itemTypeID: item type index from common.items.ITEM_TYPE_NAMES
        @param nationID: nation index from nations.NAMES
        @param innationID: item index within its nation
        @return: gui item
        """
        typeCompDescr = vehicles.makeIntCompactDescrByID(
            GUI_ITEM_TYPE_NAMES[itemTypeID], nationID, innationID)
        if itemTypeID == GUI_ITEM_TYPE.VEHICLE:
            return self.__makeVehicle(typeCompDescr)
        return self.__makeSimpleItem(typeCompDescr)

    def getTankmanDossier(self, tmanInvID):
        """
        Returns tankman dossier item by given tankman
        inventory id
        
        @param tmanInvID: tankman inventory id
        @return: TankmanDossier object
        """
        tankman = self.getTankman(tmanInvID)
        tmanDossierDescr = self.__getTankmanDossierDescr(tmanInvID)
        currentVehicleItem = None
        if tankman.isInTank:
            extDossier = self.getVehicleDossier(
                tankman.vehicleDescr.type.compactDescr)
            currentVehicleItem = self.getItemByCD(
                tankman.vehicleDescr.type.compactDescr)
        else:
            extDossier = self.getAccountDossier()
        return TankmanDossier(tankman.descriptor,
                              tmanDossierDescr,
                              extDossier,
                              currentVehicleItem=currentVehicleItem)

    def getVehicleDossier(self, vehTypeCompDescr, databaseID=None):
        """
        Returns vehicle dossier item by given vehicle type
        int compact descriptor
        
        @param vehTypeCompDescr: vehicle type in compact descriptor
        @return: VehicleDossier object
        """
        if databaseID is None:
            return VehicleDossier(
                self.__getVehicleDossierDescr(vehTypeCompDescr),
                vehTypeCompDescr)
        container = self.__itemsCache[GUI_ITEM_TYPE.VEHICLE_DOSSIER]
        dossier = container.get((int(databaseID), vehTypeCompDescr))
        if dossier is None:
            LOG_WARNING("Trying to get empty user vehicle' dossier",
                        vehTypeCompDescr, databaseID)
            return
        return VehicleDossier(dossier, vehTypeCompDescr, playerDBID=databaseID)

    def getAccountDossier(self, databaseID=None):
        """
        Returns account dossier item
        @return: AccountDossier object
        """
        if databaseID is None:
            from gui.clubs.ClubsController import g_clubsCtrl
            dossierDescr = self.__getAccountDossierDescr()
            seasonDossiers = dict(((s.getSeasonID(), s.getDossierDescr())
                                   for s in g_clubsCtrl.getSeasons()))
            return AccountDossier(dossierDescr, rated7x7Seasons=seasonDossiers)
        container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER]
        dossier, _, seasons = container.get(int(databaseID))
        if dossier is None:
            LOG_WARNING('Trying to get empty user dossier', databaseID)
            return
        return AccountDossier(dossier, databaseID, seasons)

    def getClanInfo(self, databaseID=None):
        if databaseID is None:
            return (self.stats.clanDBID, self.stats.clanInfo)
        container = self.__itemsCache[GUI_ITEM_TYPE.ACCOUNT_DOSSIER]
        _, clanInfo, _ = container.get(int(databaseID))
        if clanInfo is None:
            LOG_WARNING('Trying to get empty user clan info', databaseID)
            return
        return clanInfo

    def getPreviousItem(self, itemTypeID, invDataIdx):
        itemData = self.inventory.getPreviousItem(itemTypeID, invDataIdx)
        return self.__makeItem(itemTypeID,
                               invDataIdx,
                               strCompactDescr=itemData.compDescr,
                               inventoryID=itemData.invID,
                               proxy=self)

    def _invalidateItems(self, itemTypeID, uniqueIDs):
        cache = self.__itemsCache[itemTypeID]
        for uid in uniqueIDs:
            invRes = self.inventory.invalidateItem(itemTypeID, uid)
            if uid in cache:
                LOG_DEBUG('Item marked as invalid', uid, cache[uid], invRes)
                del cache[uid]
            else:
                LOG_DEBUG('No cached item', uid, invRes)

    def _invalidateUnlocks(self, unlocked, result):
        vehInCache = self.__itemsCache[GUI_ITEM_TYPE.VEHICLE]
        for itemCD in unlocked:
            itemTypeID = getTypeOfCompactDescr(itemCD)
            if itemTypeID == GUI_ITEM_TYPE.VEHICLE:
                result[itemTypeID].add(itemCD)
                if itemCD in vehInCache:
                    self._invalidateUnlocks(
                        vehInCache[itemCD].getAutoUnlockedItems(), result)
            elif itemTypeID in GUI_ITEM_TYPE.VEHICLE_MODULES:
                result[itemTypeID].add(itemCD)
            elif itemTypeID != GUI_ITEM_TYPE.FUEL_TANK:
                LOG_WARNING('Item is not vehicle or module', itemTypeID)

    def __getAccountDossierDescr(self):
        """
        @return: account descriptor
        """
        return dossiers2.getAccountDossierDescr(self.stats.accountDossier)

    def __getTankmanDossierDescr(self, tmanInvID):
        """
        @param tmanInvID: tankman inventory id
        @return: tankman dossier descriptor
        """
        tmanData = self.inventory.getTankmanData(tmanInvID)
        if tmanData is not None:
            return dossiers2.getTankmanDossierDescr(
                tmanData.descriptor.dossierCompactDescr)
        return dossiers2.getTankmanDossierDescr()

    def __getVehicleDossierDescr(self, vehTypeCompDescr):
        """
        @param vehTypeCompDescr: vehicle type int compact descriptor
        @return : vehicle dossier descriptor
        """
        return dossiers2.getVehicleDossierDescr(
            self.dossiers.getVehicleDossier(vehTypeCompDescr))

    def __makeItem(self, itemTypeIdx, uid, *args, **kwargs):
        container = self.__itemsCache[itemTypeIdx]
        if uid in container:
            return container[uid]
        item = None
        cls = ItemsRequester.ITEM_TYPES_MAPPING.get(itemTypeIdx)
        if cls is not None:
            container[uid] = item = cls(*args, **kwargs)
        return item

    def __makeVehicle(self, typeCompDescr, vehInvData=None):
        vehInvData = vehInvData or self.inventory.getItemData(typeCompDescr)
        if vehInvData is not None:
            return self.__makeItem(GUI_ITEM_TYPE.VEHICLE,
                                   typeCompDescr,
                                   strCompactDescr=vehInvData.compDescr,
                                   inventoryID=vehInvData.invID,
                                   proxy=self)
        return self.__makeItem(GUI_ITEM_TYPE.VEHICLE,
                               typeCompDescr,
                               typeCompDescr=typeCompDescr,
                               proxy=self)

    def __makeTankman(self, tmanInvID, tmanInvData=None):
        tmanInvData = tmanInvData or self.inventory.getTankmanData(tmanInvID)
        if tmanInvData is not None:
            vehicle = None
            if tmanInvData.vehicle > 0:
                vehicle = self.getVehicle(tmanInvData.vehicle)
            return self.__makeItem(GUI_ITEM_TYPE.TANKMAN,
                                   tmanInvID,
                                   strCompactDescr=tmanInvData.compDescr,
                                   inventoryID=tmanInvID,
                                   vehicle=vehicle,
                                   proxy=self)

    def __makeSimpleItem(self, typeCompDescr):
        return self.__makeItem(getTypeOfCompactDescr(typeCompDescr),
                               typeCompDescr,
                               intCompactDescr=typeCompDescr,
                               proxy=self)

    def __getTankmenIDsForVehicle(self, vehData):
        vehTmanIDs = set()
        for tmanInvID in vehData.crew:
            if tmanInvID is not None:
                vehTmanIDs.add(tmanInvID)

        return vehTmanIDs

    def __getTankmenIDsForTankman(self, tmanData):
        vehData = self.inventory.getVehicleData(tmanData.vehicle)
        if vehData is not None:
            return self.__getTankmenIDsForVehicle(vehData)
        return set()

    def __getVehicleCDForTankman(self, tmanData):
        vehData = self.inventory.getVehicleData(tmanData.vehicle)
        if vehData is not None:
            return {vehData.descriptor.type.compactDescr}
        return set()