class OpenBrowserOnClickComponent(CGFComponent): urlProvider = ComponentProperty(type=CGFMetaTypes.STRING, editorName='url provider', value='MARATHON_VIDEO_URL_PROVIDER') def __init__(self): super(OpenBrowserOnClickComponent, self).__init__() self.__urlParser = URLMacros() def doAction(self): self.__openBrowser() @process def __openBrowser(self): getterFunc = URL_PROVIDERS[self.urlProvider] unparsedUrl = getterFunc() url = yield self.__urlParser.parse(unparsedUrl) showBrowserOverlayView(url, alias=VIEW_ALIAS.BROWSER_OVERLAY)
class EpicBattleMetaGameController(Notifiable, SeasonProvider, IEpicBattleMetaGameController, IGlobalListener): bootcampController = dependency.descriptor(IBootcampController) __itemsCache = dependency.descriptor(IItemsCache) __eventsCache = dependency.descriptor(IEventsCache) __settingsCore = dependency.descriptor(ISettingsCore) __lobbyContext = dependency.descriptor(ILobbyContext) __battleResultsService = dependency.descriptor(IBattleResultsService) __offersProvider = dependency.descriptor(IOffersDataProvider) MAX_STORED_ARENAS_RESULTS = 20 DAILY_QUEST_ID = 'front_line' FINAL_BADGE_QUEST_ID = 'epicmetagame:progression_finish' def __init__(self): super(EpicBattleMetaGameController, self).__init__() self.onUpdated = Event.Event() self.onPrimeTimeStatusUpdated = Event.Event() self.onEventEnded = Event.Event() self.onGameModeStatusTick = Event.Event() self.__skillData = {} self.__playerMaxLevel = 0 self.__levelProgress = tuple() self.__abilityPointsForLevel = list() self.__performanceGroup = None self.__isEpicSoundMode = False self.__rankSettings = {} self.__showedResultsForArenas = [] self.__eventEndedNotifier = None self.__urlMacros = None return def init(self): super(EpicBattleMetaGameController, self).init() self.__urlMacros = URLMacros() self.addNotificator(SimpleNotifier(self.getTimer, self.__timerUpdate)) self.addNotificator(PeriodicNotifier(self.getTimer, self.__timerTick)) self.__eventEndedNotifier = SimpleNotifier(self.getEventTimeLeft, self.__onEventEnded) self.addNotificator(self.__eventEndedNotifier) def fini(self): del self.__showedResultsForArenas[:] self.onUpdated.clear() self.onPrimeTimeStatusUpdated.clear() self.onGameModeStatusTick.clear() self.onEventEnded.clear() self.clearNotification() self.stopGlobalListening() self.__urlMacros = None super(EpicBattleMetaGameController, self).fini() return def onLobbyInited(self, ctx): self.__lobbyContext.getServerSettings( ).onServerSettingsChange += self.__updateEpicMetaGameSettings g_currentVehicle.onChanged += self.__invalidateBattleAbilities self.__itemsCache.onSyncCompleted += self.__invalidateBattleAbilities g_clientUpdateManager.addCallbacks({ 'epicMetaGame': self.__updateEpic, 'inventory': self.__onInventoryUpdate, 'tokens': self.__onTokensUpdate }) self.startGlobalListening() self.__setData() self.__invalidateBattleAbilities() self.startNotification() if self.getPerformanceGroup() == EPIC_PERF_GROUP.HIGH_RISK: self.__lobbyContext.addFightButtonConfirmator( self.__confirmFightButtonPressEnabled) self.__isEpicSoundMode = False if self.prbEntity is not None: enableSound = bool(self.prbEntity.getModeFlags() & FUNCTIONAL_FLAG.EPIC) self.__updateSounds(enableSound) return def onDisconnected(self): self.__clear() def onPrbEntitySwitching(self): if self.prbEntity is None: return else: switchedFromEpic = bool(self.prbEntity.getModeFlags() & FUNCTIONAL_FLAG.EPIC) if switchedFromEpic: self.__updateSounds(False) return def onPrbEntitySwitched(self): self.__invalidateBattleAbilities() if self.prbEntity is None: return else: isEpicSoundMode = bool(self.prbEntity.getModeFlags() & FUNCTIONAL_FLAG.EPIC) if isEpicSoundMode: self.__updateSounds(True) return def onAccountBecomePlayer(self): self.__battleResultsService.onResultPosted += self.__showBattleResults def onAvatarBecomePlayer(self): self.__clear() self.__battleResultsService.onResultPosted -= self.__showBattleResults def getModeSettings(self): return self.__lobbyContext.getServerSettings().epicBattles def isEnabled(self): return self.getModeSettings().isEnabled def isEpicPrbActive(self): return False if self.prbEntity is None else bool( self.prbEntity.getModeFlags() & FUNCTIONAL_FLAG.EPIC) def isCurrentCycleActive(self): season = self.getCurrentSeason() return season.hasActiveCycle(time_utils.getCurrentLocalServerTimestamp( )) if season is not None else False def isUnlockVehiclesInBattleEnabled(self): return any(self.getUnlockableInBattleVehLevels()) def isDailyQuestsUnlocked(self): currrentLevel, _ = self.getPlayerLevelInfo() return currrentLevel >= self.getMaxPlayerLevel() def isDailyQuestsRefreshAvailable(self): if self.hasPrimeTimesLeftForCurrentCycle(): return True primeTimePeriodsForDay = self.getPrimeTimesForDay( time_utils.getCurrentLocalServerTimestamp()) if primeTimePeriodsForDay: _, periodTimeEnd = max(primeTimePeriodsForDay.values(), key=itemgetter(1)) periodTimeLeft = periodTimeEnd - time_utils.getCurrentLocalServerTimestamp( ) return periodTimeLeft > time_utils.getDayTimeLeft() return False def getPerformanceGroup(self): if not self.__performanceGroup: self.__analyzeClientSystem() _logger.debug('Current performance group %s', self.__performanceGroup) return self.__performanceGroup def getMaxPlayerLevel(self): return self.__playerMaxLevel def getStageLimit(self): return self.__stageLimit def getAbilityPointsForLevel(self): return self.__abilityPointsForLevel def getValidVehicleLevels(self): return self.getModeSettings().validVehicleLevels def getUnlockableInBattleVehLevels(self): return self.getModeSettings().unlockableInBattleVehLevels def getSuitableForQueueVehicleLevels(self): return set(self.getValidVehicleLevels()) - set( self.getUnlockableInBattleVehLevels()) def getPointsProgressForLevel(self, level): return self.__levelProgress[level] def getPointsForLevel(self, level): return sum( (self.__levelProgress[level] for level in xrange(level - 1))) def getLevelProgress(self): return self.__levelProgress def getLevelForPoints(self, points): lvl = 0 while points >= 0 and lvl <= self.__playerMaxLevel: points -= self.__levelProgress[lvl] lvl += 1 return lvl - 1 def getAllSkillsInformation(self): return self.__skillData def getPlayerLevelInfo(self): return self.__itemsCache.items.epicMetaGame.playerLevelInfo def getPlayerRanksInfo(self): if not self.__rankSettings: famePtsByRank = self.__metaSettings.metaLevel.get( 'famePtsByRank', {}) rankSettings = getRankSettings() self.__rankSettings = { rankLvl: (extraFamePts, rankSettings.bonus.factor100ByRank[rankLvl]) for rankLvl, extraFamePts in famePtsByRank.iteritems() } return self.__rankSettings def getSeasonData(self): return self.__itemsCache.items.epicMetaGame.seasonData def getSkillPoints(self): return self.__itemsCache.items.epicMetaGame.skillPoints def getSkillLevels(self): return self.__itemsCache.items.epicMetaGame.skillLevels def getSelectedSkills(self, vehicleCD): selected = self.__itemsCache.items.epicMetaGame.selectedSkills( vehicleCD) numSlots = self.getNumAbilitySlots(vehicles.getVehicleType(vehicleCD)) while len(selected) < numSlots: selected.append(-1) return selected def hasSuitableVehicles(self): requiredLevel = self.getModeSettings().validVehicleLevels v = self.__itemsCache.items.getVehicles( REQ_CRITERIA.INVENTORY | REQ_CRITERIA.VEHICLE.LEVELS(requiredLevel)) return len(v) > 0 def increaseSkillLevel(self, skillID): BigWorld.player().epicMetaGame.increaseAbility(skillID) def changeEquippedSkills(self, skillIDArray, vehicleCD, callback=None, classVehs=False): if classVehs: if callback is None: BigWorld.player().epicMetaGame.setSelectedAbilitiesVehsClass( skillIDArray, vehicleCD) else: BigWorld.player().epicMetaGame.setSelectedAbilitiesVehsClass( skillIDArray, vehicleCD, callback) elif callback is None: BigWorld.player().epicMetaGame.setSelectedAbilities( skillIDArray, vehicleCD) else: BigWorld.player().epicMetaGame.setSelectedAbilities( skillIDArray, vehicleCD, callback) return def getCycleInfo(self, cycleID=None): season = self.getCurrentSeason() if season is not None: return season.getCycleInfo(cycleID) else: _logger.warning('No current season') return def getCycleOrdinalNumber(self, cycleID): cycleInfo = self.getCycleInfo(cycleID) return cycleInfo.ordinalNumber if cycleInfo else None def getSeasonTimeRange(self): season = self.getCurrentSeason() or self.getNextSeason() if season is not None: cycles = season.getAllCycles() if cycles: cycles = list( sorted(cycles.values(), key=lambda c: c.ordinalNumber)) return (cycles[0].startDate, cycles[-1].endDate) return (0, 0) def getAllUnlockedSkillInfoBySkillId(self): return { skillID: skill.getSkillInfo() for skillID, skill in self.__skillData.iteritems() if skill.isActivated } def getUnlockedAbilityIds(self): return (skill.getSkillInfo().eqID for skill in self.getAllSkillsInformation().itervalues() if skill.isActivated and skill.getSkillInfo() is not None) def getStoredEpicDiscount(self): return BigWorld.player().epicMetaGame.getStoredDiscount() def getEventTimeLeft(self): timeLeft = self.getSeasonTimeRange( )[1] - time_utils.getCurrentLocalServerTimestamp() return timeLeft + 1 if timeLeft > 0 else time_utils.ONE_MINUTE def getStats(self): return self.__itemsCache.items.epicMetaGame @process def openURL(self, url=None): requestUrl = url or self.getModeSettings().url if requestUrl: parsedUrl = yield self.__urlMacros.parse(requestUrl) if parsedUrl: self.__showBrowserView(parsedUrl) def showCustomScreen(self, screen): if self.getModeSettings().url and EpicBattleScreens.hasValue(screen): self.openURL('/'.join((self.getModeSettings().url.strip('/'), screen.value.strip('/')))) def getNumAbilitySlots(self, vehicleType): vehClass = getVehicleClassFromVehicleType(vehicleType) return self.__metaSettings.defaultSlots.get(vehClass, 0) def getAbilitySlotsOrder(self, vehicleType): vehClass = getVehicleClassFromVehicleType(vehicleType) return self.__metaSettings.slots.get(vehClass, (0, 0, 0)) def getAbilitySlotsUnlockOrder(self, vehicleType): vehClass = getVehicleClassFromVehicleType(vehicleType) return self.__metaSettings.inBattleReservesByRank.get( 'slotActions').get(vehClass, [[0], [0], [0]]) def getAllLevelRewards(self): rewardsData = dict() allQuests = self.__eventsCache.getAllQuests() for questKey, questData in allQuests.iteritems(): if LEVELUP_TOKEN_TEMPLATE in questKey: _, _, questNum = questKey.partition(LEVELUP_TOKEN_TEMPLATE) if questNum: questLvl = int(questNum) rewardsData[questLvl] = questData return rewardsData def isNeedToTakeReward(self): currentLevel, _ = self.getPlayerLevelInfo() rewardsData = self.getAllLevelRewards() for bonuses in (rewards.getBonuses() for level, rewards in rewardsData.iteritems() if level <= currentLevel): for bonus in bonuses: if bonus.getName() == EPIC_SELECT_BONUS_NAME: for tokenID in bonus.getTokens().iterkeys(): if self.__itemsCache.items.tokens.getToken(tokenID): return True return False def getNotChosenRewardCount(self): count = 0 for token in self.__itemsCache.items.tokens.getTokens().iterkeys(): if not token.startswith(EPIC_CHOICE_REWARD_OFFER_GIFT_TOKENS): continue if not self.__offersProvider.getOfferByToken( token.replace('_gift', '')): continue if self.__itemsCache.items.tokens.isTokenAvailable(token): count += self.__itemsCache.items.tokens.getTokenCount(token) return count def hasAnyOfferGiftToken(self): return any((token.startswith(EPIC_CHOICE_REWARD_OFFER_GIFT_TOKENS) for token in self.__itemsCache.items.tokens.getTokens().iterkeys())) def replaceOfferByGift(self, bonuses): result = [] for bonus in bonuses: gift = self.__getReceivedGift(bonus) if gift: result.extend(gift.bonuses) result.append(bonus) return result def replaceOfferByReward(self, bonuses): result = [] for bonus in bonuses: if bool(self.__getReceivedGift(bonus)): bonus.updateContext({'isReceived': True}) result.append(bonus) return result def __getReceivedGift(self, bonus): if bonus.getName() == EPIC_SELECT_BONUS_NAME: bonus.updateContext({'isReceived': False}) for tokenID in bonus.getTokens().iterkeys(): offer = self.__offersProvider.getOfferByToken( tokenID.replace('_gift', '')) if offer: receivedGifts = self.__offersProvider.getReceivedGifts( offer.id) if receivedGifts: for giftId, count in receivedGifts.iteritems(): if count > 0: return offer.getGift(giftId) return None def __invalidateBattleAbilities(self, *_): if not self.__itemsCache.isSynced(): return self.__invalidateBattleAbilityItems() self.__invalidateBattleAbilitiesForVehicle() def __setData(self): self.__skillData = {} skills = self.__metaSettings.rewards.get('combatReserves', {}) maxSkillLvl = self.__metaSettings.maxCombatReserveLevel eqs = vehicles.g_cache.equipments() if skills != {}: for key, value in skills.iteritems(): self.__skillData[key] = EpicMetaGameSkill( key, maxSkillLvl, value.get('tags'), value.get('price', 0)) lvls = value['levels'] lvlAmount = len(lvls) found = 0 for eq in eqs.values(): if eq.name in lvls: lvl = lvls.index(eq.name) + 1 self.__skillData[key].levels[ lvl] = EpicMetaGameSkillLevel( lvl, eq.id[1], i18n.makeString(eq.userString), i18n.makeString(eq.shortDescription), i18n.makeString(eq.longDescription), i18n.makeString(eq.shortFilterAlert), i18n.makeString(eq.longFilterAlert), eq.icon[0]) found += 1 if found == lvlAmount: break metaLevel = self.__metaSettings.metaLevel self.__playerMaxLevel = metaLevel.get('maxLevel', 0) self.__stageLimit = metaLevel.get('stageLimit', -1) self.__abilityPointsForLevel = metaLevel.get('abilityPointsForLevel', []) levelProgress = metaLevel.get('famePtsToProgress', [])[:] levelProgress.insert(0, 0) self.__levelProgress = tuple(levelProgress) def __clear(self): self.stopNotification() self.stopGlobalListening() self.__lobbyContext.getServerSettings( ).onServerSettingsChange -= self.__updateEpicMetaGameSettings g_currentVehicle.onChanged -= self.__invalidateBattleAbilities self.__itemsCache.onSyncCompleted -= self.__invalidateBattleAbilities g_clientUpdateManager.removeObjectCallbacks(self) if self.getPerformanceGroup() == EPIC_PERF_GROUP.HIGH_RISK: self.__lobbyContext.deleteFightButtonConfirmator( self.__confirmFightButtonPressEnabled) def __updateEpic(self, diff): changes = set(diff.keys()) self.__invalidateBattleAbilities() if changes: self.onUpdated(diff) def __updateEpicMetaGameSettings(self, diff): if 'epic_config' in diff: self.__setData() self.onUpdated(diff['epic_config']) self.__resetTimer() def __resetTimer(self): self.startNotification() self.__timerUpdate() self.__timerTick() def __timerUpdate(self): status, _, _ = self.getPrimeTimeStatus() self.onPrimeTimeStatusUpdated(status) def __timerTick(self): self.onGameModeStatusTick() def __onEventEnded(self): self.onEventEnded() self.__eventEndedNotifier.stopNotification() self.__eventEndedNotifier.clear() def __showBattleResults(self, reusableInfo, _, resultsWindow): if reusableInfo.common.arenaBonusType == ARENA_BONUS_TYPE.EPIC_BATTLE: arenaUniqueID = reusableInfo.arenaUniqueID if arenaUniqueID not in self.__showedResultsForArenas: self.__showedResultsForArenas.append(arenaUniqueID) self.__showedResultsForArenas = self.__showedResultsForArenas[ -self.MAX_STORED_ARENAS_RESULTS:] extensionInfo = reusableInfo.personal.avatar.extensionInfo levelUpInfo = { 'metaLevel': extensionInfo.get('metaLevel'), 'prevMetaLevel': extensionInfo.get('prevMetaLevel'), 'playerRank': extensionInfo.get('playerRank'), 'originalFlXP': extensionInfo.get('originalFlXP'), 'boosterFlXP': extensionInfo.get('boosterFlXP') } event_dispatcher.showEpicBattlesAfterBattleWindow( levelUpInfo, resultsWindow) def __isInValidPrebattle(self): if g_prbLoader and g_prbLoader.getDispatcher( ) and g_prbLoader.getDispatcher().getEntity(): currentPrbEntity = g_prbLoader.getDispatcher().getEntity( ).getEntityType() return currentPrbEntity in (QUEUE_TYPE.EPIC, PREBATTLE_TYPE.EPIC, PREBATTLE_TYPE.EPIC_TRAINING) else: return None def __invalidateBattleAbilityItems(self): data = self.__itemsCache.items.getItems(GUI_ITEM_TYPE.BATTLE_ABILITY, REQ_CRITERIA.EMPTY) vehicle = g_currentVehicle.item for item in data.values(): if self.__isInValidPrebattle(): item.isUnlocked = item.innationID in self.getUnlockedAbilityIds( ) if vehicle is not None: mayInstall, _ = item.mayInstall(vehicle) if not mayInstall: item.isUnlocked = False item.isUnlocked = False return def __invalidateBattleAbilitiesForVehicle(self): vehicle = g_currentVehicle.item if vehicle is None or vehicle.descriptor.type.level not in self.__lobbyContext.getServerSettings( ).epicBattles.validVehicleLevels or not self.__isInValidPrebattle(): return else: amountOfSlots = self.getNumAbilitySlots(vehicle.descriptor.type) selectedItems = [None] * amountOfSlots skillInfo = self.getAllSkillsInformation() selectedSkills = self.getSelectedSkills(vehicle.intCD) battleAbilities = self.__itemsCache.items.getItems( GUI_ITEM_TYPE.BATTLE_ABILITY, REQ_CRITERIA.EMPTY) for item in battleAbilities.values(): for index, skillID in enumerate(selectedSkills): if skillID is not None and skillID >= 0: if skillInfo[skillID].getSkillInfo( ) and item.innationID == skillInfo[ skillID].getSkillInfo().eqID: selectedItems[index] = item vehicle.battleAbilities.setLayout(*selectedItems) vehicle.battleAbilities.setInstalled(*selectedItems) return def __analyzeClientSystem(self): stats = BigWorld.wg_getClientStatistics() stats['graphicsEngine'] = self.__settingsCore.getSetting( GRAPHICS.RENDER_PIPELINE) self.__performanceGroup = EPIC_PERF_GROUP.LOW_RISK for groupName, conditions in PERFORMANCE_GROUP_LIMITS.iteritems(): for currentLimit in conditions: condValid = True systemStats = currentLimit.get( EPIC_META_GAME_LIMIT_TYPE.SYSTEM_DATA, {}) for key, limit in systemStats.iteritems(): currValue = stats.get(key, None) if currValue is None or currValue != limit: condValid = False hardwareParams = currentLimit.get( EPIC_META_GAME_LIMIT_TYPE.HARDWARE_PARAMS, {}) for key, limit in hardwareParams.iteritems(): currValue = BigWorld.getAutoDetectGraphicsSettingsScore( key) if currValue >= limit: condValid = False if condValid: self.__performanceGroup = groupName return return def __onInventoryUpdate(self, invDiff): items = { GUI_ITEM_TYPE.VEHICLE, GUI_ITEM_TYPE.BATTLE_ABILITY, GUI_ITEM_TYPE.CUSTOMIZATION } if items.intersection(invDiff): self.__invalidateBattleAbilities() def __updateSounds(self, isEpicSoundMode): if isEpicSoundMode != self.__isEpicSoundMode: _FrontLineSounds.onChange(isEpicSoundMode) self.__isEpicSoundMode = isEpicSoundMode @async @process def __confirmFightButtonPressEnabled(self, callback): if not self.__isInValidPrebattle(): callback(True) return defaults = AccountSettings.getFilterDefault(GUI_START_BEHAVIOR) filters = self.__settingsCore.serverSettings.getSection( GUI_START_BEHAVIOR, defaults) isEpicPerformanceWarningEnabled = not AccountSettings.getSettings( 'isEpicPerformanceWarningClicked') if isEpicPerformanceWarningEnabled: result, checkboxChecked = yield DialogsInterface.showI18nCheckBoxDialog( 'epicBattleConfirmDialog') filters['isEpicPerformanceWarningClicked'] = checkboxChecked AccountSettings.setSettings('isEpicPerformanceWarningClicked', checkboxChecked) else: result = True callback(result) def __showBrowserView(self, url): from gui.Scaleform.daapi.view.lobby.epicBattle.web_handlers import createFrontlineWebHandlers webHandlers = createFrontlineWebHandlers() alias = VIEW_ALIAS.BROWSER_VIEW g_eventBus.handleEvent( events.LoadViewEvent(SFViewLoadParams(alias, getUniqueViewName(alias)), ctx={ 'url': url, 'webHandlers': webHandlers, 'returnAlias': VIEW_ALIAS.LOBBY_HANGAR, 'onServerSettingsChange': self.__serverSettingsChangeBrowserHandler }), EVENT_BUS_SCOPE.LOBBY) def __serverSettingsChangeBrowserHandler(self, browser, diff): if not diff.get(Configs.EPIC_CONFIG.value, {}).get('isEnabled'): browser.onCloseView() @property def __metaSettings(self): return self.__lobbyContext.getServerSettings().epicMetaGame def __onTokensUpdate(self, diff): if any((key.startswith(EPIC_CHOICE_REWARD_OFFER_GIFT_TOKENS) for key in diff.keys())): pass
class ExternalLinksHandler(IExternalLinksController): def __init__(self): super(ExternalLinksHandler, self).__init__() self.__urlMacros = None return def init(self): self.__urlMacros = URLMacros() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMacros is not None: self.__urlMacros.clear() self.__urlMacros = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(ExternalLinksHandler, self).fini() return def open(self, url): if not url: LOG_ERROR('URL is empty', url) return try: BigWorld.wg_openWebBrowser(url) except Exception: LOG_ERROR('There is error while opening web browser at page:', url) LOG_CURRENT_EXCEPTION() @async @process def getURL(self, name, params=None, callback=lambda *args: None): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMacros.parse(str(urlSettings), params) else: url = yield lambda callback: callback('') callback(url) def _handleSpecifiedURL(self, event): self.open(event.url) @process def __openParsedUrl(self, urlName, params=None): parsedUrl = yield self.getURL(urlName, params) self.open(parsedUrl) def _handleParsedURL(self, event): self.__openParsedUrl(event.url) def _handleOpenRegistrationURL(self, _): self.__openParsedUrl('registrationURL') def _handleOpenRecoveryPasswordURL(self, _): self.__openParsedUrl('recoveryPswdURL') def _handleOpenPaymentURL(self, _): self.__openParsedUrl('paymentURL') def _handleSecuritySettingsURL(self, _): self.__openParsedUrl('securitySettingsURL') def _handleSupportURL(self, _): self.__openParsedUrl('supportURL') def _handleMigrationURL(self): self.__openParsedUrl('migrationURL') def _handleFortDescription(self, _): self.__openParsedUrl('fortDescription') def _handleClanSearch(self, _): self.__openParsedUrl('clanSearch') def _handleClanCreate(self, _): self.__openParsedUrl('clanCreate') def _handleInvitesManagementURL(self, _): self.__openParsedUrl('invitesManagementURL') def _handleGmSummaryURL(self, _): self.__openParsedUrl('globalMapSummary') def _handleGmPromoSummaryURL(self, _): self.__openParsedUrl('globalMapPromoSummary') def _handleGmCapURL(self, _): self.__openParsedUrl('globalMapCap') def _handleGmPromoURL(self, _): self.__openParsedUrl('globalMapPromo') def _handleOpenPremShopURL(self, _): self.__openParsedUrl('premShopURL') def _handleFrontlineChangesURL(self, _): self.__openParsedUrl('frontlineChangesURL') def _handleTokenShopURL(self, event): self.__openParsedUrl('tokenShopURL', event.params) def _handleTechTreeNewsURL(self, event): self.__openParsedUrl('techTreeUpdateNewsURL', event.params)
class PromoController(IPromoController): __browserCtrl = dependency.descriptor(IBrowserController) __notificationsCtrl = dependency.descriptor(IEventsNotificationsController) __webController = dependency.descriptor(IWebController) __settingsCore = dependency.descriptor(ISettingsCore) __lobbyContext = dependency.descriptor(ILobbyContext) __logger = dependency.descriptor(IPromoLogger) __bootcamp = dependency.descriptor(IBootcampController) def __init__(self): super(PromoController, self).__init__() self.__urlMacros = URLMacros() self.__externalCloseCallback = None self.__isLobbyInited = False self.__pendingPromo = None self.__promoCount = 0 self.__lastUpdateTimeMark = 0 self.__promoData = None self.__waitingForWebBridgeData = False self.__battlesFromLastTeaser = 0 self.__wasInBattle = False self.__hasPendingTeaser = False self.__isPromoOpen = False self.__browserCreationCallbacks = {} self.__browserWatchers = {} self.__isInHangar = False self.__isTeaserOpen = False self.__checkIntervalInBattles = GUI_SETTINGS.checkPromoFrequencyInBattles self.__em = EventManager() self.onNewTeaserReceived = Event(self.__em) self.onPromoCountChanged = Event(self.__em) self.onTeaserShown = Event(self.__em) self.onTeaserClosed = Event(self.__em) return @sf_lobby def app(self): pass def fini(self): self.__stop() self.__pendingPromo = None self.__urlMacros.clear() self.__urlMacros = None self.__externalCloseCallback = None self.__em.clear() g_eventBus.removeListener(BrowserEvent.BROWSER_CREATED, self.__handleBrowserCreated) self.__browserCreationCallbacks = {} self.__browserWatchers = {} super(PromoController, self).fini() return def onLobbyInited(self, event): if not isPlayerAccount(): return g_eventBus.addListener(BrowserEvent.BROWSER_CREATED, self.__handleBrowserCreated) self.__isLobbyInited = True if self.__needToGetTeasersInfo(): self.__updateWebBrgData() elif self.__hasPendingTeaser: self.__tryToShowTeaser() self.__notificationsCtrl.onEventNotificationsChanged += self.__onEventNotification if not isPopupsWindowsOpenDisabled(): self.__processPromo( self.__notificationsCtrl.getEventsNotifications()) self.app.loaderManager.onViewLoaded += self.__onViewLoaded @property def checkIntervalInBattles(self): return self.__checkIntervalInBattles def setNewTeaserData(self, teaserData): timestamp = teaserData['timestamp'] if self.__lastUpdateTimeMark < timestamp and not self.__isPromoOpen and not self.__isTeaserOpen: self.__updateTeaserData(teaserData) def showFieldPost(self): url = GUI_SETTINGS.promoscreens loadingCallback = self.__logger.getLoggingFuture( action=PromoLogActions.OPEN_FROM_MENU, type=PromoLogSubjectType.INDEX, url=url) self.__showBrowserView(url, loadingCallback, soundSpaceID='field_post') @process def showLastTeaserPromo(self): rowUrl = self.__promoData.get('url', '') loadingCallback = self.__logger.getLoggingFuture( self.__promoData, action=PromoLogActions.OPEN_FROM_TEASER, type=PromoLogSubjectType.PROMO_SCREEN, url=rowUrl) url = yield self.__addAuthParams(rowUrl) self.__showBrowserView(url, loadingCallback) def setUnreadPromoCount(self, count): self.__updatePromoCount(count) def isTeaserOpen(self): return self.__isTeaserOpen def onAvatarBecomePlayer(self): if self.__isLobbyInited: self.__battlesFromLastTeaser += 1 self.__stop() def onDisconnected(self): self.__stop() def isActive(self): return self.__lobbyContext.getServerSettings().isFieldPostEnabled( ) and not self.__bootcamp.isInBootcamp() def getPromoCount(self): return self.__promoCount def showPromo(self, url, closeCallback=None, source=None): if self.__isLobbyInited: if not self.__isPromoOpen and not self.__waitingForWebBridgeData: self.__registerAndShowPromoBrowser( url, closeCallback, self.__logger.getLoggingFuture( action=PromoLogActions.OPEN_IN_OLD, type=PromoLogSubjectType.PROMO_SCREEN, source=source, url=url)) else: self.__pendingPromo = _PromoData(url, closeCallback, source) def __needToGetTeasersInfo(self): return True if self.__battlesFromLastTeaser == 0 else self.__checkIntervalInBattles > 0 and self.__battlesFromLastTeaser % self.__checkIntervalInBattles == 0 def __onTeaserClosed(self, byUser=False): self.__isTeaserOpen = False self.onTeaserClosed() if byUser: self.__showBubbleTooltip() def __showBubbleTooltip(self): storageData = self.__settingsCore.serverSettings.getUIStorage() if not storageData.get(UI_STORAGE_KEYS.FIELD_POST_HINT_IS_SHOWN): showBubbleTooltip(i18n.makeString(TOOLTIPS.HEADER_VERSIONINFOHINT)) self.__settingsCore.serverSettings.saveInUIStorage( {UI_STORAGE_KEYS.FIELD_POST_HINT_IS_SHOWN: True}) @process def __updateWebBrgData(self): ctx = PromoGetTeaserRequestCtx() if self.__battlesFromLastTeaser == 0: sourceType = PromoLogSourceType.FIRST_LOGIN else: sourceType = PromoLogSourceType.AFTER_BATTLE answerCallback = self.__logger.getLoggingFuture( action=PromoLogActions.GET_MOST_IMPORTANT, source=sourceType) self.__waitingForWebBridgeData = True response = yield self.__webController.sendRequest(ctx=ctx) self.__waitingForWebBridgeData = False if response.isSuccess(): self.__updateTeaserData(ctx.getDataObj(response.getData())) elif self.__hasPendingTeaser: self.__tryToShowTeaser() if answerCallback: answerCallback(success=response.extraCode) def __onPromoClosed(self, **kwargs): self.__isPromoOpen = False self.__showBubbleTooltip() if self.__externalCloseCallback: self.__externalCloseCallback() self.__requestPromoCount() actionType = PromoLogActions.CLOSED_BY_USER if kwargs.get( 'byUser') else PromoLogActions.KILLED_BY_SYSTEM self.__logger.logAction(action=actionType, type=PromoLogSubjectType.PROMO_SCREEN_OR_INDEX, url=kwargs.get('url')) @process def __requestPromoCount(self): if not self.isActive(): _logger.warning( 'Trying to request unread promos count when promo functionality is disabled' ) return ctx = PromoGetUnreadCountRequestCtx() response = yield self.__webController.sendRequest(ctx=ctx) if response.isSuccess(): self.__updatePromoCount(ctx.getCount(response)) def __updatePromoCount(self, count): countChanged = count != self.__promoCount self.__promoCount = count if countChanged: self.onPromoCountChanged() def __updateTeaserData(self, teaserData): self.__lastUpdateTimeMark = teaserData['timestamp'] self.__promoData = teaserData['lastPromo'] self.__updatePromoCount(teaserData['count']) if self.__promoData.get('url'): self.__tryToShowTeaser() def __showTeaser(self): if self.isActive(): self.__battlesFromLastTeaser = 0 self.__hasPendingTeaser = False self.onNewTeaserReceived(self.__promoData, self.__onTeaserShown, self.__onTeaserClosed) else: _logger.warning( 'Impossible to show teaser, functionality is disabled') @process def __onTeaserShown(self, promoID): self.__isTeaserOpen = True self.onTeaserShown() yield self.__webController.sendRequest( PromoSendTeaserShownRequestCtx(promoID)) def __tryToShowTeaser(self): if self.__isLobbyInited and self.__isInHangar and not self.__waitingForWebBridgeData: self.__showTeaser() else: self.__hasPendingTeaser = True def __stop(self): if self.app and self.app.loaderManager: self.app.loaderManager.onViewLoaded -= self.__onViewLoaded self.__isLobbyInited = False self.__isInHangar = False self.__isPromoOpen = False self.__externalCloseCallback = None self.__isTeaserOpen = False self.__notificationsCtrl.onEventNotificationsChanged -= self.__onEventNotification g_eventBus.removeListener(BrowserEvent.BROWSER_CREATED, self.__handleBrowserCreated) self.__browserCreationCallbacks = {} watcherKeys = self.__browserWatchers.keys() for browserID in watcherKeys: self.__clearWatcher(browserID) return def __processPromo(self, promos): if not self.__isPromoOpen and not self.__waitingForWebBridgeData: logData = { 'action': PromoLogActions.OPEN_IN_OLD, 'type': PromoLogSubjectType.PROMO_SCREEN } if self.__pendingPromo is not None: promoData = self.__pendingPromo logData.update({ 'source': promoData.source, 'url': promoData.url }) loadingCallback = self.__logger.getLoggingFuture(**logData) self.__registerAndShowPromoBrowser(promoData.url, promoData.closeCallback, loadingCallback) self.__pendingPromo = None return promo = findFirst( lambda item: item.eventType.startswith( gc_constants.PROMO.TEMPLATE.ACTION), promos) if promo: logData.update({ 'source': PromoLogSourceType.SSE, 'url': promo.data }) self.__showBrowserView( promo.data, self.__logger.getLoggingFuture(**logData)) return def __onEventNotification(self, added, _): self.__processPromo(added) def __registerAndShowPromoBrowser(self, url, closeCallback, loadingCallback): self.__externalCloseCallback = closeCallback self.__showBrowserView(url, loadingCallback) @process def __showBrowserView(self, url, loadingCallback=None, soundSpaceID=None): promoUrl = yield self.__urlMacros.parse(url) self.__registerLoadingCallback(promoUrl, loadingCallback) _showBrowserView(promoUrl, self.__onPromoClosed, soundSpaceID=soundSpaceID) self.__isPromoOpen = True def __registerLoadingCallback(self, url, callback): if callback is not None: self.__browserCreationCallbacks[url] = callback return def __handleBrowserCreated(self, event): url = event.ctx.get('url') if url in self.__browserCreationCallbacks: callback = self.__browserCreationCallbacks.pop(url) browserID = event.ctx.get('browserID') browser = self.__browserCtrl.getBrowser(browserID) if browser is None: return def callbackWrapper(clbUrl, _, statusCode): if clbUrl == url: callback(url=url, success=statusCode) self.__clearWatcher(browserID) browser.onLoadEnd += callbackWrapper self.__browserWatchers[browserID] = callbackWrapper return def __clearWatcher(self, browserID): if browserID in self.__browserWatchers: watcher = self.__browserWatchers.pop(browserID) browser = self.__browserCtrl.getBrowser(browserID) if browser is not None: browser.onLoadEnd -= watcher return @async @process def __addAuthParams(self, url, callback): if not url or not self.__webController: callback(url) accessTokenData = yield self.__webController.getAccessTokenData( force=True) params = { 'access_token': str(accessTokenData.accessToken), 'spa_id': BigWorld.player().databaseID } callback(url_formatters.addParamsToUrlQuery(url, params)) def __onViewLoaded(self, pyView, _): if self.__isLobbyInited: if pyView.alias == VIEW_ALIAS.LOBBY_HANGAR: self.__isInHangar = True if self.__hasPendingTeaser: self.__tryToShowTeaser() elif pyView.viewType == ViewTypes.LOBBY_SUB: self.__isInHangar = False
class ExternalLinksHandler(IExternalLinksController): __loginManager = dependency.descriptor(ILoginManager) def __init__(self): super(ExternalLinksHandler, self).__init__() self.__urlMacros = None self.__linksHandlers = None return def init(self): self.__urlMacros = URLMacros() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: _logger.error('Handler is not found %s %s', eventType, handlerName) continue if not callable(handler): _logger.error('Handler is invalid %s %s %r', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMacros is not None: self.__urlMacros.clear() self.__urlMacros = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(ExternalLinksHandler, self).fini() return def open(self, url): if not url: _logger.error('URL is empty %r', url) return handled = False for handler in self._getHandlers(): handled = handler.handle(url) if handled: break if not handled: _logger.error('Cant handle external link: %s', url) @async @process def getURL(self, name, params=None, callback=lambda *args: None): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMacros.parse(str(urlSettings), params) else: url = yield lambda callback: callback('') callback(url) def externalAllowed(self, url): for handler in self._getHandlers(): result = handler.checkHandle(url) if result.handled: return result.externalAllowed return False def _handleSpecifiedURL(self, event): self.open(event.url) @process def __openParsedUrl(self, urlName, params=None): parsedUrl = yield self.getURL(urlName, params) self.open(parsedUrl) def _handleParsedURL(self, event): self.__openParsedUrl(event.url) def _handleOpenRegistrationURL(self, _): self.__openParsedUrl('registrationURL') def _handleOpenRecoveryPasswordURL(self, _): self.__openParsedUrl('recoveryPswdURL') def _handleOpenPaymentURL(self, _): self.__openParsedUrl('paymentURL') def _handleSecuritySettingsURL(self, _): self.__openParsedUrl('securitySettingsURL') def _handleClanRulesURL(self, _): self.__openParsedUrl('clanRulesURL') def _handleSupportURL(self, _): self.__openParsedUrl('supportURL') def _handleMigrationURL(self): self.__openParsedUrl('migrationURL') def _handleFortDescription(self, _): self.__openParsedUrl('fortDescription') def _handleClanSearch(self, _): self.__openParsedUrl('clanSearch') def _handleClanCreate(self, _): self.__openParsedUrl('clanCreate') def _handleInvitesManagementURL(self, _): self.__openParsedUrl('invitesManagementURL') def _handleGmSummaryURL(self, _): self.__openParsedUrl('globalMapSummary') def _handleGmPromoSummaryURL(self, _): self.__openParsedUrl('globalMapPromoSummary') def _handleGmCapURL(self, _): self.__openParsedUrl('globalMapCap') def _handleGmPromoURL(self, _): self.__openParsedUrl('globalMapPromo') def _handleOpenPremShopURL(self, _): self.__openParsedUrl('premShopURL') def _handleFrontlineChangesURL(self, _): self.__openParsedUrl('frontlineChangesURL') def _handleTokenShopURL(self, event): self.__openParsedUrl('tokenShopURL', event.params) def _getHandlers(self): if not self.__linksHandlers: self.__linksHandlers = [] if self.__loginManager.isWgcSteam: self.__linksHandlers.append(external.PremShopLinksHandler()) self.__linksHandlers.append( external.AddPlatformTagLinksHandler()) self.__linksHandlers.append( external.PremShopLinksForArgsUrlHandler()) self.__linksHandlers.append( external.AddPlatformTagLinksToArgsUrlHandler()) self.__linksHandlers.append(external.OpenBrowserHandler()) return self.__linksHandlers
class PersonalMissionFirstEntryView(LobbySubView, PersonalMissionFirstEntryViewMeta): _COMMON_SOUND_SPACE = PERSONAL_MISSIONS_SOUND_SPACE __settingsCore = dependency.descriptor(ISettingsCore) __CARDS = (3, 3, 4, 4) __R_PERSONAL_MISSION_FIRST_ENTRY_VIEW = R.strings.personal_missions.PersonalMissionFirstEntryView def __init__(self, ctx): super(PersonalMissionFirstEntryView, self).__init__(ctx) self.__urlMacros = URLMacros() self.__settings = GUI_SETTINGS.personalMissions.get('welcomeVideo', {}) self.__cardsLen = len(self.__CARDS) def playVideo(self): if self.__settings.get('isEnabled', False): self.__showVideo() def backBtnClicked(self): self.fireEvent(events.LoadViewEvent( SFViewLoadParams(VIEW_ALIAS.LOBBY_PERSONAL_MISSIONS)), scope=EVENT_BUS_SCOPE.LOBBY) def onViewClose(self, isAcceptBtnClick=False): if isAcceptBtnClick: self.__settingsCore.serverSettings.saveInUIStorage( {PM_TUTOR_FIELDS.GREETING_SCREEN_SHOWN: True}) self.fireEvent(events.LoadViewEvent( SFViewLoadParams(VIEW_ALIAS.LOBBY_PERSONAL_MISSIONS)), scope=EVENT_BUS_SCOPE.LOBBY) else: self.fireEvent(events.LoadViewEvent( SFViewLoadParams(VIEW_ALIAS.LOBBY_HANGAR)), scope=EVENT_BUS_SCOPE.LOBBY) def onCardClick(self, cardIndex): self.__updateDetailedData(cardIndex) def onNextCardClick(self, cardIndex): self.__updateDetailedData(cardIndex + 1) def onPrevCardClick(self, cardIndex): self.__updateDetailedData(cardIndex - 1) def _populate(self): super(PersonalMissionFirstEntryView, self)._populate() infoBlocks = [ self.__makeTileData(cardIndex) for cardIndex in xrange(0, self.__cardsLen) ] firstEntry = not self.__settingsCore.serverSettings.getUIStorage().get( PM_TUTOR_FIELDS.GREETING_SCREEN_SHOWN) self.as_setInitDataS({ 'titleLabel': PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_TITLE, 'bigBtnLabel': PERSONAL_MISSIONS.PERSONALMISSIONFIRSTENTRYVIEW_ACKNOWLEDGEBTN, 'playVideoBtnLabel': text_styles.concatStylesToSingleLine( icons.makeImageTag( RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_PLAYICON, width=14, height=15, vSpace=-2), i18n.makeString(PERSONAL_MISSIONS. PERSONALMISSIONFIRSTENTRYVIEW_VIDEOBTNLABEL)), 'playVideoBtnVisible': self.__settings.get('isEnabled', False), 'bgSource': RES_ICONS.MAPS_ICONS_PERSONALMISSIONS_INFOSCREENBG, 'infoBlocks': infoBlocks, 'backBtnLabel': PERSONAL_MISSIONS.HEADER_BACKBTN_LABEL, 'isFirstEntry': firstEntry }) self.soundManager.setRTPC(SOUNDS.RTCP_OVERLAY, SOUNDS.MAX_MISSIONS_ZOOM) def _dispose(self): self.soundManager.setRTPC(SOUNDS.RTCP_OVERLAY, SOUNDS.MIN_MISSIONS_ZOOM) super(PersonalMissionFirstEntryView, self)._dispose() def __updateDetailedData(self, cardIndex): cardIndex = self.__normalizeSlotIndex(cardIndex) blocksLen = self.__CARDS[cardIndex] blocks = [] for blockIndex in xrange(0, blocksLen): blocks.append({ 'title': PERSONAL_MISSIONS.getBlockTitle(cardIndex, blockIndex), 'description': PERSONAL_MISSIONS.getBlockDescription(cardIndex, blockIndex), 'image': RES_ICONS.getBlockImageByStep(cardIndex, blockIndex) }) item = self.__R_PERSONAL_MISSION_FIRST_ENTRY_VIEW.dyn( 'item{}'.format(cardIndex)) data = { 'index': cardIndex, 'icon': RES_ICONS.getInfoIcon(cardIndex), 'title': PERSONAL_MISSIONS.getCardHeader(cardIndex), 'description': PERSONAL_MISSIONS.getCardInnerDescription(cardIndex), 'blocks': blocks, 'notificationIcon': RES_ICONS.MAPS_ICONS_LIBRARY_WARNINGICON_1, 'notificationLabel': backport.text(item.warning()) if item and 'warning' in item.keys() else '' } self.as_setDetailedCardDataS(data) @process def __showVideo(self): url = yield self.__urlMacros.parse(self.__settings.get('url')) webHandlers = webApiCollection(ui_web_api.CloseViewWebApi, sound_web_api.SoundWebApi, sound_web_api.HangarSoundWebApi) ctx = { 'url': url, 'webHandlers': webHandlers, 'returnAlias': self.alias } showPersonalMissionBrowserView(ctx) @staticmethod def __makeTileData(cardIndex): return { 'index': cardIndex, 'iconSource': RES_ICONS.getInfoIcon(cardIndex), 'titleLabel': PERSONAL_MISSIONS.getCardHeader(cardIndex), 'descriptionLabel': PERSONAL_MISSIONS.getCardDescription(cardIndex) } def __normalizeSlotIndex(self, slotIndex): if slotIndex >= self.__cardsLen: return 0 return self.__cardsLen - 1 if slotIndex < 0 else slotIndex
class BattleRoyaleController(Notifiable, SeasonProvider, IBattleRoyaleController, IGlobalListener): __lobbyContext = dependency.descriptor(ILobbyContext) __eventsCache = dependency.descriptor(IEventsCache) __itemsCache = dependency.descriptor(IItemsCache) __hangarsSpace = dependency.descriptor(IHangarSpace) __settingsCore = dependency.descriptor(ISettingsCore) __hangarSpacesSwitcher = dependency.descriptor(IHangarSpacesSwitcher) __hangarSpaceReloader = dependency.descriptor(IHangarSpaceReloader) __notificationsCtrl = dependency.descriptor(IEventsNotificationsController) __sessionProvider = dependency.descriptor(IBattleSessionProvider) __c11nService = dependency.descriptor(ICustomizationService) __connectionMgr = dependency.descriptor(IConnectionManager) __battleRoyaleTournamentController = dependency.descriptor( IBattleRoyaleTournamentController) __bootcamp = dependency.descriptor(IBootcampController) TOKEN_QUEST_ID = 'token:br:title:' MAX_STORED_ARENAS_RESULTS = 20 def __init__(self): super(BattleRoyaleController, self).__init__() self.onUpdated = Event.Event() self.onPrimeTimeStatusUpdated = Event.Event() self.onSpaceUpdated = Event.Event() self.__clientValuesInited = False self.__clientShields = {} self.__performanceGroup = None self.__serverSettings = None self.__battleRoyaleSettings = None self.__wasInLobby = False self.__equipmentCount = {} self.__equipmentSlots = tuple() self.__voControl = None self.__defaultHangars = {} self.__c11nVisible = False self.__urlMacros = None self.__isNeedToUpdateHeroTank = False return def init(self): super(BattleRoyaleController, self).init() self.__voControl = BRVoiceOverController() self.__voControl.init() self.__urlMacros = URLMacros() self.addNotificator(SimpleNotifier(self.getTimer, self.__timerUpdate)) def fini(self): self.__voControl.fini() self.__voControl = None self.__equipmentCount = None self.__defaultHangars = None self.__urlMacros = None self.onUpdated.clear() self.onPrimeTimeStatusUpdated.clear() self.clearNotification() super(BattleRoyaleController, self).fini() return def wasInLobby(self): return self.__wasInLobby def onLobbyInited(self, event): super(BattleRoyaleController, self).onLobbyInited(event) if not self.__clientValuesInited: self.__clientValuesInited = True g_clientUpdateManager.addCallbacks( {'battleRoyale': self.__updateRoyale}) self.startNotification() self.startGlobalListening() self.__hangarsSpace.onSpaceChangedByAction += self.__onSpaceChanged self.__hangarsSpace.onSpaceChanged += self.__onSpaceChanged self.__hangarsSpace.onVehicleChanged += self.__onVehicleChanged self.__c11nService.onVisibilityChanged += self.__onC11nVisibilityChanged self.__notificationsCtrl.onEventNotificationsChanged += self.__onEventNotification self.__onEventNotification( self.__notificationsCtrl.getEventsNotifications()) self.__battleRoyaleTournamentController.onSelectBattleRoyaleTournament += self.__selectBattleRoyaleTournament self.__updateMode() self.__wasInLobby = True if not self.__hangarsSpace.spaceInited or self.__hangarsSpace.spaceLoading( ): self.__hangarsSpace.onSpaceCreate += self.__onSpaceCreate else: self.__updateSpace() nextTick(self.__eventAvailabilityUpdate)() def __onEventNotification(self, added, removed=()): for evNotification in removed: if evNotification.eventType in (SERVER_CMD_CHANGE_HANGAR, SERVER_CMD_CHANGE_HANGAR_PREM): self.__defaultHangars[evNotification.eventType == SERVER_CMD_CHANGE_HANGAR_PREM] = None for evNotification in added: if evNotification.eventType in (SERVER_CMD_CHANGE_HANGAR, SERVER_CMD_CHANGE_HANGAR_PREM): try: data = json.loads(evNotification.data) path = data['hangar'] except Exception: path = evNotification.data self.__defaultHangars[evNotification.eventType == SERVER_CMD_CHANGE_HANGAR_PREM] = path return def onDisconnected(self): self.__wasInLobby = False self.__clearClientValues() self.__clear() super(BattleRoyaleController, self).onDisconnected() def onAccountBecomePlayer(self): self.__onServerSettingsChanged(self.__lobbyContext.getServerSettings()) super(BattleRoyaleController, self).onAccountBecomePlayer() def onAvatarBecomePlayer(self): self.__clear() if self.__sessionProvider.arenaVisitor.getArenaBonusType( ) in ARENA_BONUS_TYPE.BATTLE_ROYALE_RANGE: self.__voControl.activate() else: self.__voControl.deactivate() self.__voControl.onAvatarBecomePlayer() super(BattleRoyaleController, self).onAvatarBecomePlayer() def getModeSettings(self): return self.__lobbyContext.getServerSettings().battleRoyale def isEnabled(self): return self.getModeSettings().isEnabled def getEndTime(self): return self.getCurrentSeason().getCycleEndDate() def getPerformanceGroup(self): if not self.__performanceGroup: self.__analyzeClientSystem() _logger.debug('Current performance group %s', self.__performanceGroup) return self.__performanceGroup def getDefaultAmmoCount(self, itemKey, intCD=None, vehicleName=None): if itemKey in AmmoTypes.SHELLS or itemKey in AmmoTypes.CHARGES: return self.__equipmentCount.get(itemKey, 0) else: if itemKey == AmmoTypes.ITEM: if intCD is None: _logger.error( 'Cannot get count of equipment. Equipment id not specified' ) return 0 if vehicleName is None: _logger.error( "Cannot get count of '%r' equipment. Vehicle not specified", intCD) return 0 vehiclesSlotsConfig = self.getModeSettings( ).vehiclesSlotsConfig if vehicleName not in vehiclesSlotsConfig: _logger.error( "Cannot get count of '%r' equipment. Vehicle '%r' not found", intCD, vehicleName) return 0 for chargeId, equipmentId in vehiclesSlotsConfig[ vehicleName].iteritems(): if equipmentId == intCD: return self.getDefaultAmmoCount(chargeId) else: _logger.warning( "Can't get default ammo count. Unknown item key: '%r'.", itemKey) return 0 def getVehicleSlots(self): return self.__equipmentSlots def getBrVehicleEquipmentIds(self, vehicleName): vehiclesSlotsConfig = self.getModeSettings().vehiclesSlotsConfig if vehicleName not in vehiclesSlotsConfig: _logger.error( "Get equipment for vehicle '%r' failed. Vehicle not found. Slots config %s", vehicleName, vehiclesSlotsConfig) return None else: vehiclesSlots = vehiclesSlotsConfig[vehicleName] result = [] for chargeName in sorted(vehiclesSlots.keys()): result.append(vehiclesSlots[chargeName]) return result @staticmethod def getBrCommanderSkills(): result = [] if g_currentVehicle.isPresent(): vehicle = g_currentVehicle.item for _, tankman in vehicle.crew: if tankman is not None: for skill in tankman.skills: result.append(skill) return result def isActive(self): _, isCycleActive = self.getCurrentCycleInfo() return self.isEnabled() and self.getCurrentSeason( ) is not None and isCycleActive def isBattleRoyaleMode(self): if self.prbDispatcher is None: return False else: state = self.prbDispatcher.getFunctionalState() return self.__isBattleRoyaleMode( state) or self.__isBattleRoyaleTournamentMode(state) def __isBattleRoyaleMode(self, state): return state.isInPreQueue( queueType=QUEUE_TYPE.BATTLE_ROYALE) or state.isInUnit( PREBATTLE_TYPE.BATTLE_ROYALE) def __isBattleRoyaleTournamentMode(self, state): return state.isInPreQueue( queueType=QUEUE_TYPE.BATTLE_ROYALE_TOURNAMENT) or state.isInUnit( PREBATTLE_TYPE.BATTLE_ROYALE_TOURNAMENT) def isBattlePassAvailable(self, bonusType): battlePassConfig = self.__lobbyContext.getServerSettings( ).getBattlePassConfig() return battlePassConfig.isEnabled( ) and battlePassConfig.isGameModeEnabled(bonusType) def isInBattleRoyaleSquad(self): dispatcher = self.prbDispatcher if dispatcher is not None: state = dispatcher.getFunctionalState() return state.isInUnit(PREBATTLE_TYPE.BATTLE_ROYALE) else: return False def onPrbEntitySwitched(self): self.__updateMode() self.__updateSpace() def selectRoyaleBattle(self): if not self.isEnabled(): return self.__selectRoyaleBattle() def setDefaultHangarEntryPoint(self): if self.__battleRoyaleTournamentController.isSelected(): self.__battleRoyaleTournamentController.leaveBattleRoyaleTournament( isChangingToBattleRoyaleHangar=True) def isGeneralHangarEntryPoint(self): return not self.__battleRoyaleTournamentController.isSelected() def selectRandomBattle(self): dispatcher = g_prbLoader.getDispatcher() if dispatcher is None: _logger.error('Prebattle dispatcher is not defined') return else: self.__doSelectRandomPrb(dispatcher) return def getPlayerLevelInfo(self): return self.__itemsCache.items.battleRoyale.accTitle def getStats(self): return self.__itemsCache.items.battleRoyale @process def openURL(self, url=None): requestUrl = url or self.__battleRoyaleSettings.url if requestUrl: parsedUrl = yield self.__urlMacros.parse(requestUrl) if parsedUrl: self.__showBrowserView(parsedUrl) def getQuests(self): _, isCycleActive = self.getCurrentCycleInfo() return { k: v for k, v in self.__eventsCache.getQuests().items() if v.getGroupID() == BATTLE_ROYALE_GROUPS_ID and self.__tokenIsValid(v) } if self.isGeneralHangarEntryPoint() and isCycleActive else {} def isDailyQuestsRefreshAvailable(self): if self.hasPrimeTimesLeftForCurrentCycle(): return True serversPeriodsMapping = self.getPrimeTimesForDay( time_utils.getCurrentLocalServerTimestamp()) periods = [] for _, dayPeriods in serversPeriodsMapping.items(): periods.append(max([periodEnd for _, periodEnd in dayPeriods])) if periods: periodTimeLeft = max( periods) - time_utils.getCurrentLocalServerTimestamp() return periodTimeLeft > time_utils.getDayTimeLeft() return False def __selectRoyaleBattle(self): dispatcher = g_prbLoader.getDispatcher() if dispatcher is None: _logger.error('Prebattle dispatcher is not defined') return else: self.__doSelectBattleRoyalePrb(dispatcher) return def __selectBattleRoyaleTournament(self): dispatcher = g_prbLoader.getDispatcher() if dispatcher is None: _logger.error('Prebattle dispatcher is not defined') return else: self.__doSelectBattleRoyaleTournamentPrb(dispatcher) return def __showBrowserView(self, url): webHandlers = createBattleRoyaleWebHanlders() alias = VIEW_ALIAS.BROWSER_VIEW g_eventBus.handleEvent( events.LoadViewEvent(SFViewLoadParams(alias, getUniqueViewName(alias)), ctx={ 'url': url, 'webHandlers': webHandlers, 'returnAlias': VIEW_ALIAS.LOBBY_HANGAR, 'onServerSettingsChange': self.__serverSettingsChangeBrowserHandler }), EVENT_BUS_SCOPE.LOBBY) def __serverSettingsChangeBrowserHandler(self, browser, diff): if not diff.get(Configs.BATTLE_ROYALE_CONFIG.value, {}).get('isEnabled'): browser.onCloseView() def _createSeason(self, cycleInfo, seasonData): return BattleRoyaleSeason(cycleInfo, seasonData) def __onSpaceChanged(self): switchItems = self.__hangarSpacesSwitcher.itemsToSwitch if self.isBattleRoyaleMode( ) and self.__hangarSpacesSwitcher.currentItem != switchItems.BATTLE_ROYALE: self.selectRandomBattle() def __eventAvailabilityUpdate(self, *_): if g_prbLoader.getDispatcher() is None: return elif self.__battleRoyaleTournamentController.isSelected(): return else: battleRoyaleEnabled = self.isEnabled() and self.getCurrentSeason( ) is not None isSelectRandom = not battleRoyaleEnabled and self.isBattleRoyaleMode( ) if battleRoyaleEnabled and not self.isActive(): currTime = time_utils.getCurrentLocalServerTimestamp() cycle = self.getCurrentSeason().getNextByTimeCycle(currTime) isSelectRandom = cycle is None if isSelectRandom: self.selectRandomBattle() return def __onSpaceCreate(self): nextTick(self.__updateSpace)() def __updateSpace(self): if not self.__c11nVisible and self.__hangarsSpace.spaceInited and not self.__hangarsSpace.spaceLoading( ): switchItems = self.__hangarSpacesSwitcher.itemsToSwitch isBrSpace = self.__hangarSpacesSwitcher.currentItem == switchItems.BATTLE_ROYALE isBrMode = self.isBattleRoyaleMode() if isBrMode and not isBrSpace: g_eventBus.handleEvent(events.HangarSpacesSwitcherEvent( events.HangarSpacesSwitcherEvent.SWITCH_TO_HANGAR_SPACE, ctx={'switchItemName': switchItems.BATTLE_ROYALE}), scope=EVENT_BUS_SCOPE.LOBBY) self.__isNeedToUpdateHeroTank = True elif not isBrMode and isBrSpace: defaultHangarPath = self.__defaultHangars.get( self.__hangarsSpace.isPremium) if defaultHangarPath is not None: self.__hangarSpaceReloader.changeHangarSpace( defaultHangarPath) else: g_eventBus.handleEvent(events.HangarSpacesSwitcherEvent( events.HangarSpacesSwitcherEvent. SWITCH_TO_HANGAR_SPACE, ctx={'switchItemName': switchItems.DEFAULT}), scope=EVENT_BUS_SCOPE.LOBBY) self.onSpaceUpdated() return def __updateMode(self): if self.isBattleRoyaleMode(): self.__enableRoyaleMode() elif not self.__bootcamp.isInBootcamp(): self.__disableRoyaleMode() def __enableRoyaleMode(self): royaleVehicleID = AccountSettings.getFavorites(ROYALE_VEHICLE) if not royaleVehicleID or self.__itemsCache.items.getVehicle( royaleVehicleID) is None: criteria = REQ_CRITERIA.VEHICLE.HAS_TAGS( [VEHICLE_TAGS.BATTLE_ROYALE]) | REQ_CRITERIA.INVENTORY vehicles = self.__itemsCache.items.getVehicles royaleVehicle = first( sorted(vehicles(criteria=criteria).values(), key=lambda item: item.intCD)) if royaleVehicle: royaleVehicleID = royaleVehicle.invID if self.__c11nVisible: pass elif royaleVehicleID: g_currentVehicle.selectVehicle(royaleVehicleID) else: g_currentVehicle.selectNoVehicle() self.__voControl.activate() return def __disableRoyaleMode(self): storedVehInvID = AccountSettings.getFavorites(CURRENT_VEHICLE) if not storedVehInvID: criteria = REQ_CRITERIA.INVENTORY | ~REQ_CRITERIA.VEHICLE.HAS_TAGS( [VEHICLE_TAGS.BATTLE_ROYALE]) vehicle = first( self.__itemsCache.items.getVehicles( criteria=criteria).values()) if vehicle: storedVehInvID = vehicle.invID if storedVehInvID: g_currentVehicle.selectVehicle(storedVehInvID) else: g_currentVehicle.selectNoVehicle() self.__voControl.deactivate() @process def __doSelectBattleRoyaleTournamentPrb(self, dispatcher): yield dispatcher.doSelectAction( PrbAction(PREBATTLE_ACTION_NAME.BATTLE_ROYALE_TOURNAMENT)) @process def __doSelectBattleRoyalePrb(self, dispatcher): yield dispatcher.doSelectAction( PrbAction(PREBATTLE_ACTION_NAME.BATTLE_ROYALE)) @process def __doSelectRandomPrb(self, dispatcher): yield dispatcher.doSelectAction(PrbAction( PREBATTLE_ACTION_NAME.RANDOM)) @process def fightClick(self): dispatcher = g_prbLoader.getDispatcher() if not dispatcher: return lobbyContext = dependency.instance(ILobbyContext) navigationPossible = yield lobbyContext.isHeaderNavigationPossible() fightButtonPressPossible = yield lobbyContext.isFightButtonPressPossible( ) if navigationPossible and fightButtonPressPossible: if dispatcher: dispatcher.doAction( PrbAction(PREBATTLE_ACTION_NAME.BATTLE_ROYALE)) else: _logger.error('Prebattle dispatcher is not defined') @process def _doLeaveBattleRoyalePrb(self, dispatcher): if dispatcher is None: return else: yield dispatcher.doLeaveAction(LeavePrbAction()) return def __getBattleRoyaleSettings(self): generalSettings = self.__serverSettings.battleRoyale cycleID = None now = time_utils.getCurrentLocalServerTimestamp() _, cycleInfo = season_common.getSeason(generalSettings.asDict(), now) if cycleInfo: _, _, _, cycleID = cycleInfo for season in generalSettings.seasons.values(): if cycleID in season.get('cycles', {}): return generalSettings.replace(season).replace( season['cycles'][cycleID]) return generalSettings def __getCachedSettings(self): return self.__battleRoyaleSettings def __timerUpdate(self): status, _, _ = self.getPrimeTimeStatus() self.onPrimeTimeStatusUpdated(status) self.__eventAvailabilityUpdate() def __resetTimer(self): self.startNotification() self.__timerUpdate() def __onServerSettingsChanged(self, serverSettings): if self.__serverSettings is not None: self.__serverSettings.onServerSettingsChange -= self.__updateRoyaleSettings self.__serverSettings = serverSettings self.__battleRoyaleSettings = self.__getBattleRoyaleSettings() self.__updateEquipmentCount() self.__serverSettings.onServerSettingsChange += self.__updateRoyaleSettings return def __updateRoyaleSettings(self, diff): if Configs.BATTLE_ROYALE_CONFIG.value not in diff: return else: self.__eventAvailabilityUpdate() self.__battleRoyaleSettings = self.__getBattleRoyaleSettings() self.__updateEquipmentCount() self.__divisions = None self.onUpdated() self.__resetTimer() return def __clear(self): self.stopNotification() self.stopGlobalListening() self.__hangarsSpace.onSpaceChangedByAction -= self.__onSpaceChanged self.__hangarsSpace.onSpaceChanged -= self.__onSpaceChanged self.__hangarsSpace.onSpaceCreate -= self.__onSpaceCreate self.__hangarsSpace.onVehicleChanged -= self.__onVehicleChanged self.__notificationsCtrl.onEventNotificationsChanged -= self.__onEventNotification self.__c11nService.onVisibilityChanged -= self.__onC11nVisibilityChanged self.__battleRoyaleTournamentController.onSelectBattleRoyaleTournament -= self.__selectBattleRoyaleTournament self.__defaultHangars = {} g_clientUpdateManager.removeObjectCallbacks(self) def __clearClientValues(self): if self.__serverSettings is not None: self.__serverSettings.onServerSettingsChange -= self.__updateRoyaleSettings self.__serverSettings = None self.__clientValuesInited = False return def __updateRoyale(self, _): self.onUpdated() self.__resetTimer() def __analyzeClientSystem(self): stats = BigWorld.wg_getClientStatistics() stats['graphicsEngine'] = self.__settingsCore.getSetting( GRAPHICS.RENDER_PIPELINE) self.__performanceGroup = BattleRoyalePerfProblems.LOW_RISK for groupName, conditions in PERFORMANCE_GROUP_LIMITS.iteritems(): for currentLimit in conditions: condValid = True systemStats = currentLimit.get( BATTLE_ROYALE_GAME_LIMIT_TYPE.SYSTEM_DATA, {}) for key, limit in systemStats.iteritems(): currValue = stats.get(key, None) if currValue is None or currValue != limit: condValid = False hardwareParams = currentLimit.get( BATTLE_ROYALE_GAME_LIMIT_TYPE.HARDWARE_PARAMS, {}) for key, limit in hardwareParams.iteritems(): currValue = BigWorld.getAutoDetectGraphicsSettingsScore( key) if currValue >= limit: condValid = False if condValid: self.__performanceGroup = groupName return return def __updateEquipmentCount(self): if self.__equipmentCount: self.__equipmentCount = None self.__equipmentCount = {} items = self.__battleRoyaleSettings.defaultAmmo for itemGroup in items: groupKey, groupItems = itemGroup self.__equipmentCount[groupKey] = groupItems[0] return def __onC11nVisibilityChanged(self, isVisible): self.__c11nVisible = isVisible self.__updateSpace() def __onVehicleChanged(self): if self.__isNeedToUpdateHeroTank: self.__hangarsSpace.onHeroTankReady() self.__isNeedToUpdateHeroTank = False def __tokenIsValid(self, quest): tokens = quest.accountReqs.getTokens() return False if tokens and not tokens[0].isAvailable() else True
class GameWindowController(IGameWindowController): eventsCache = dependency.descriptor(IEventsCache) lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): self.__urlMacros = URLMacros() self.__isLobbyInited = False super(GameWindowController, self).__init__() def fini(self): self.__urlMacros.clear() self.__urlMacros = None self.hideWindow() super(GameWindowController, self).fini() return def onLobbyInited(self, event): self.__isLobbyInited = True self._addListeners() def onAvatarBecomePlayer(self): self._removeListeners() if self.__isLobbyInited: self.hideWindow() self.__isLobbyInited = False super(GameWindowController, self).onAvatarBecomePlayer() def onDisconnected(self): self.__isLobbyInited = False self._removeListeners() self.hideWindow() super(GameWindowController, self).onDisconnected() def hideWindow(self): raise NotImplementedError def showWindow(self, url=None, invokedFrom=None): self.hideWindow() self._showWindow(url, invokedFrom) @async @process def getUrl(self, callback=lambda *args: None): url = yield self.__urlMacros.parse(self._getUrl()) callback(url) def _addListeners(self): self.eventsCache.onSyncCompleted += self._onSyncCompleted def _removeListeners(self): self.eventsCache.onSyncCompleted -= self._onSyncCompleted def _onSyncCompleted(self, *_): pass @process def _showWindow(self, url, invokedFrom=None): if url is None: url = yield self.getUrl() if not url: return self._openWindow(url, invokedFrom) return def _openWindow(self, url, invokedFrom=None): raise NotImplementedError
class ProgressiveItemsView(ViewImpl): __slots__ = ('__c11nView', '_itemsProgressData', '_possibleItems', '_vehicle', '__blur', '__layoutID', '__urlMacros', '__guiSettings') __lobbyContext = dependency.descriptor(ILobbyContext) __itemsCache = dependency.descriptor(IItemsCache) __customizationService = dependency.descriptor(ICustomizationService) __appLoader = dependency.descriptor(IAppLoader) __settingsCore = dependency.descriptor(ISettingsCore) def __init__(self, layoutID, c11nView, *args, **kwargs): settings = ViewSettings(layoutID) settings.args = args settings.kwargs = kwargs settings.flags = ViewFlags.LOBBY_TOP_SUB_VIEW settings.model = ProgressiveItemsViewModel() super(ProgressiveItemsView, self).__init__(settings) self._itemsProgressData = None self._possibleItems = None self._vehicle = None self.__blur = CachedBlur() self.__layoutID = layoutID self.__c11nView = c11nView self.__urlMacros = URLMacros() self.__guiSettings = GUI_SETTINGS.progressiveItems.get( 'tutorialVideo', {}) return def createToolTip(self, event): if event.contentID == R.views.common.tooltip_window.backport_tooltip_content.BackportTooltipContent( ): intCD = int(event.getArgument('id')) level = int(event.getArgument('level')) window = BackportTooltipWindow( self.__getTooltipData(intCD, event.getArgument('tooltip'), level), self.getParentWindow()) window.load() return window return super(ProgressiveItemsView, self).createToolTip(event) @property def viewModel(self): return super(ProgressiveItemsView, self).getViewModel() def _initialize(self, *args, **kwargs): super(ProgressiveItemsView, self)._initialize(*args, **kwargs) if self.__c11nView is not None: self.__c11nView.changeVisible(False) self.viewModel.onSelectItem += self._onSelectItem self.viewModel.tutorial.showVideo += self._showVideoPage return def _finalize(self): super(ProgressiveItemsView, self)._finalize() if self.__c11nView is not None: self.__c11nView.changeVisible(True) self.__c11nView = None self.__blur.fini() self.viewModel.onSelectItem -= self._onSelectItem self.viewModel.tutorial.showVideo -= self._showVideoPage return def _onLoading(self, *args, **kwargs): self._vehicle = g_currentVehicle.item self._possibleItems = self._getPossibleItemsForVehicle() self._itemsProgressData = self.__itemsCache.items.inventory.getC11nProgressionDataForVehicle( self._vehicle.intCD) itemIntCD = kwargs.get('itemIntCD') with self.getViewModel().transaction() as model: model.setTankName(self._vehicle.userName) model.setTankLevel(int2roman(self._vehicle.level)) model.setTankType(self._vehicle.typeBigIconResource()) self.__setItems(model) model.setIsRendererPipelineDeferred(isRendererPipelineDeferred()) model.setItemToScroll(0 if itemIntCD is None else itemIntCD) return def _onLoaded(self, *args, **kwargs): self.__blur.enable() self.__settingsCore.serverSettings.setOnceOnlyHintsSettings( {OnceOnlyHints.C11N_PROGRESSION_VIEW_HINT: HINT_SHOWN_STATUS}) def _onSelectItem(self, args=None): if args is not None: intCD = int(args['intCD']) level = int(args['level']) item = self.__customizationService.getItemByCD(intCD) ctx = self.__customizationService.getCtx() def changeTabAndGetItemToHand(): ctx.changeModeWithProgressionDecal(intCD) ctx.events.onGetItemBackToHand(item, level, scrollToItem=True) noveltyCount = self._vehicle.getC11nItemNoveltyCounter( proxy=self.__itemsCache.items, item=item) if noveltyCount: BigWorld.callback( 0.0, lambda: ctx.resetItemsNovelty([item.intCD])) BigWorld.callback(0.0, changeTabAndGetItemToHand) self.destroyWindow() return def _showVideoPage(self, args=None): self.__showVideo() @process def __showVideo(self): url = yield self.__urlMacros.parse(self.__guiSettings.get('url')) webHandlers = webApiCollection(ui_web_api.CloseViewWebApi, sound_web_api.SoundWebApi, sound_web_api.HangarSoundWebApi) ctx = {'url': url, 'webHandlers': webHandlers} showProgressiveItemsBrowserView(ctx) def _getPossibleItemsForVehicle(self): customizationCache = vehicles.g_cache.customization20() vehicleType = self._vehicle.descriptor.type sortedItems = sorted( customizationCache.customizationWithProgression.itervalues(), key=lambda i: i.id) return [ item.compactDescr for item in sortedItems if item.filter.matchVehicleType(vehicleType) ] def __setItems(self, model): for intCD in self._possibleItems: itemModel = ItemModel() item = self.__customizationService.getItemByCD(intCD) itemModel.setItemId(intCD) itemModel.setItemUserString(item.userName) itemModel.setMaxLevel(item.getMaxProgressionLevel()) itemModel.setScaleFactor(item.formfactor) latestOpenedLevel = item.getLatestOpenedProgressionLevel( self._vehicle) itemModel.setCurrentLevel(1 if latestOpenedLevel == -1 else latestOpenedLevel + 1) self.__setEachLevelInfo(itemModel, item) model.progressiveItems.addViewModel(itemModel) def __setEachLevelInfo(self, model, item): for level in xrange(1, model.getMaxLevel() + 1): levelInfo = ItemLevelInfoModel() levelInfo.setLevel(level) levelInfo.setLevelText(getProgressionItemStatusText(level)) levelInfo.setUnlocked(level < model.getCurrentLevel()) icon = item.iconUrlByProgressionLevel( level, _PREVIEW_ICON_SIZE, _PREVIEW_ICON_INNER_SIZE.get(item.formfactor)) levelInfo.setIcon(icon) if level == model.getCurrentLevel(): levelInfo.setInProgress(True) levelInfo.progressBlock.setUnlockCondition( _ms( item.progressionConditions.get(level, {})[0].get( 'description', ''))) currProgress = int( item.getCurrentProgressOnCurrentLevel(self._vehicle)) currProgress = currProgress if currProgress > 0 else 0 maxProgress = int( item.progressionConditions.get(level, {})[0].get('value', '1')) if maxProgress > 1: levelInfo.progressBlock.setProgressionVal(currProgress) levelInfo.progressBlock.setMaxProgressionVal(maxProgress) else: levelInfo.progressBlock.setHideProgressBarAndString(True) model.eachLevelInfo.addViewModel(levelInfo) @staticmethod def __getTooltipData(intCD, tooltip, level): return createTooltipData(isSpecial=True, specialAlias=tooltip, specialArgs=CustomizationTooltipContext( itemCD=intCD, level=level, showOnlyProgressBlock=True))
class MarathonEvent(IMarathonEvent, MarathonEventDataProvider): _eventsCache = dependency.descriptor(IEventsCache) _bootcamp = dependency.descriptor(IBootcampController) _lobbyContext = dependency.descriptor(ILobbyContext) def __init__(self): super(MarathonEvent, self).__init__() self.__isEnabled = False self.__isAvailable = False self.__rewardObtained = False self.__state = '' self.__suspendFlag = False self.__quest = None self.__group = None self.__urlMacros = URLMacros() return @async @process def getUrl(self, callback): url = yield self.__urlMacros.parse(self._getUrl()) callback(url) @async @process def getMarathonVehicleUrl(self, callback): url = yield self.__urlMacros.parse(self._getUrl(urlType=MarathonConfig.REWARD_VEHICLE_URL)) callback(url) def getFinishSaleTime(self): return self._lobbyContext.getServerSettings().getMarathonConfig()[MarathonConfig.FINISH_SALE_TIME] def doesShowMissionsTab(self): return self.isEnabled() def getHangarFlag(self, state=None): return backport.image(R.images.gui.maps.icons.library.hangarFlag.dyn(self.hangarFlags)()) @prbEntityProperty def prbEntity(self): return None def isEnabled(self): return self.__isEnabled and not self._bootcamp.isInBootcamp() def isAvailable(self): return self.__isAvailable def getQuestsData(self, prefix=None, postfix=None): return self.__getProgress('quests', prefix, postfix) def getTokensData(self, prefix=None, postfix=None): return self.__getProgress('tokens', prefix, postfix) def getMarathonProgress(self, byCompletedTokensCount=False): tokens = self.getTokensData(prefix=self.tokenPrefix, postfix=self.completedTokenPostfix) if byCompletedTokensCount: return (len(tokens), self.questsInChain) tokenPrefixLen = len(self.tokenPrefix) res = [] for tokenNames in tokens.keys(): name = str(tokenNames[tokenPrefixLen:]) res.append(int(filter(str.isdigit, name))) currentStep = sorted(res)[-1] if res else 0 return (currentStep, self.questsInChain) def getState(self): return self.__state def getTooltipHeader(self): if self.tooltipHeaderType == MARATHON_FLAG_TOOLTIP_HEADERS.PROGRESS: return self.getFormattedDaysStatus() if self.tooltipHeaderType == MARATHON_FLAG_TOOLTIP_HEADERS.COUNTDOWN: return self.getFormattedRemainingTime() return self.getFormattedStartFinishText() if self.tooltipHeaderType == MARATHON_FLAG_TOOLTIP_HEADERS.TEXT else ('', '') def getMarathonFlagState(self, vehicle): return {'flagHeaderIcon': self.__getHangarFlagHeaderIcon(), 'flagStateIcon': self.__getHangarFlagStateIcon(vehicle), 'flagMain': self.getHangarFlag(self.__state), 'tooltip': self.__getTooltip(), 'enable': self.isAvailable(), 'visible': self.isEnabled()} def checkForWarnings(self, vehicle): wrongBattleType = self.prbEntity.getEntityType() != constants.ARENA_GUI_TYPE.RANDOM if wrongBattleType: return MARATHON_WARNING.WRONG_BATTLE_TYPE wrongVehicleLevel = vehicle.level < self.minVehicleLevel return MARATHON_WARNING.WRONG_VEH_TYPE if wrongVehicleLevel else '' def isRewardObtained(self): return self.__rewardObtained def getMarathonQuests(self): return self._eventsCache.getHiddenQuests(self.__marathonFilterFunc) def getFormattedDaysStatus(self): icon = self.icons.iconFlag text = self.__getProgressInDays(self.__getTimeFromGroupStart()) return (icon, text) def getFormattedRemainingTime(self): firstQuestStartTimeLeft, firstQuestFinishTimeLeft = self.__getQuestTimeInterval() if self.__state == MARATHON_STATE.NOT_STARTED: icon = self.icons.timeIconGlow text = self.__getTillTimeStart(firstQuestStartTimeLeft) elif self.__state == MARATHON_STATE.IN_PROGRESS: text = self.__getTillTimeEnd(firstQuestFinishTimeLeft) if firstQuestFinishTimeLeft > ONE_DAY: icon = self.icons.iconFlag else: icon = self.icons.timeIconGlow else: icon = self.icons.iconFlag text = text_styles.main(backport.text(self.tooltips.stateComplete)) return (icon, text) def getFormattedStartFinishText(self): startDate, finishDate = self.__getGroupStartFinishTime() startDateStruct = getTimeStructInLocal(startDate) finishDateStruct = getTimeStructInLocal(finishDate) startDateText = text_styles.main(backport.text(TOOLTIPS.MARATHON_DATE, day=startDateStruct.tm_mday, month=i18n.makeString(MENU.datetime_months(startDateStruct.tm_mon)), hour=startDateStruct.tm_hour, minutes=i18n.makeString('%02d', startDateStruct.tm_min))) finishDateText = text_styles.main(backport.text(TOOLTIPS.MARATHON_DATE, day=finishDateStruct.tm_mday, month=i18n.makeString(MENU.datetime_months(finishDateStruct.tm_mon)), hour=finishDateStruct.tm_hour, minutes=i18n.makeString('%02d', finishDateStruct.tm_min))) text = text_styles.main(backport.text(TOOLTIPS.MARATHON_SUBTITLE, startDate=startDateText, finishDate=finishDateText)) return ('', text) def getExtraTimeToBuy(self, timeFormat=TIME_FORMAT_DAYS): if self.__state == MARATHON_STATE.FINISHED: _, groupFinishTimeLeft = self.__getGroupTimeInterval() timeUnit = TIME_FORMAT_TO_TIME_UNIT[timeFormat] if groupFinishTimeLeft < timeUnit: groupFinishTimeLeft += timeUnit if timeFormat == TIME_FORMAT_HOURS: templateKey = self.tooltips.hoursShort else: templateKey = self.tooltips.daysShort fmtText = text_styles.neutral(backport.text(templateKey, value=str(int(groupFinishTimeLeft // timeUnit)))) return fmtText def getMarathonDiscount(self): passQuests, allQuests = self.getMarathonProgress() return int(passQuests * 100) / allQuests if passQuests and self.questsInChain else 0 def setState(self): if not self.__group: self.__isEnabled = False self.__isAvailable = False self.__state = MARATHON_STATE.UNKNOWN return self.__state if self.__suspendFlag: self.__state = MARATHON_STATE.SUSPENDED self.__isEnabled = True self.__isAvailable = False return self.__state groupStartTimeLeft, groupFinishTimeLeft = self.__getGroupTimeInterval() zeroTime = ZERO_TIME if groupStartTimeLeft > zeroTime or groupFinishTimeLeft <= zeroTime: self.__isEnabled = False self.__isAvailable = False self.__state = MARATHON_STATE.DISABLED return self.__state if groupStartTimeLeft <= zeroTime < groupFinishTimeLeft: self.__isEnabled = True self.__isAvailable = True firstQuestStartTimeLeft, firstQuestFinishTimeLeft = self.__getQuestTimeInterval() if firstQuestStartTimeLeft > zeroTime: self.__state = MARATHON_STATE.NOT_STARTED elif firstQuestStartTimeLeft <= zeroTime < firstQuestFinishTimeLeft: self.__state = MARATHON_STATE.IN_PROGRESS elif firstQuestFinishTimeLeft <= zeroTime < groupFinishTimeLeft: self.__state = MARATHON_STATE.FINISHED return self.__state def updateQuestsData(self): self.__suspendFlag = False quests = self._eventsCache.getHiddenQuests(self.__marathonFilterFunc) if quests: sortedQuests = sorted(quests.itervalues(), key=self.__findEarliestQuest) for q in quests: if self.suspendPrefix in q: self.__suspendFlag = True break self.__quest = sortedQuests[0] else: self.__quest = None groups = self._eventsCache.getGroups(self.__marathonFilterFunc) if groups: sortedGroups = sorted(groups) self.__group = groups[sortedGroups[0]] else: self.__group = None tokens = self.getTokensData(prefix=self.tokenPrefix) rewardObtained = False for key in self.awardTokens: if key in tokens and tokens[key][_TOKEN_COUNT_INDEX] > 0: rewardObtained = True break self.__setRewardObtained(rewardObtained) return def getClosestStatusUpdateTime(self): if self.__state == MARATHON_STATE.NOT_STARTED: timeLeft, _ = self.__getQuestTimeInterval() return timeLeft + 1 if self.__state == MARATHON_STATE.IN_PROGRESS: _, timeLeft = self.__getQuestTimeInterval() return timeLeft + 1 if self.__state == MARATHON_STATE.FINISHED: _, timeLeft = self.__getGroupTimeInterval() return timeLeft def showRewardVideo(self): videoShownKey = self.__getRewardShownMarkKey(MARATHON_VIDEO_WAS_SHOWN_PREFIX) if self.isRewardObtained() and self.doesShowRewardVideo() and not AccountSettings.getUIFlag(videoShownKey): showMarathonReward(self.vehicleID, videoShownKey) def showRewardScreen(self): if not self.doesShowRewardScreen(): return if self.__state in MARATHON_STATE.DISABLED_STATE: return if self.isRewardObtained() and not AccountSettings.getUIFlag(self.__getRewardShownMarkKey(MARATHON_REWARD_WAS_SHOWN_PREFIX)): showBrowserOverlayView(self._getUrl() + self.marathonCompleteUrlAdd, alias=VIEW_ALIAS.BROWSER_OVERLAY, callbackOnLoad=partial(self.__setScreenWasShown, MARATHON_REWARD_WAS_SHOWN_PREFIX)) def createMarathonWebHandlers(self): from gui.marathon.web_handlers import createDefaultMarathonWebHandlers return createDefaultMarathonWebHandlers() def getVehiclePreviewTitleTooltip(self): finishSaleTime = self.__getDateTimeText(self.getFinishSaleTime()) questStartTime, _ = self.__getQuestStartFinishTime() questStartTimeText = self.__getDateTimeText(questStartTime) body = self.infoBody addInfo = self.bodyAddInfo if self.__state == MARATHON_STATE.NOT_STARTED: tooltipBody = body.announce() addInfo = backport.text(addInfo.announce(), addInfo=backport.text(self.tooltips.previewAnnounce, marathonStartDate=text_styles.neutral(questStartTimeText))) return self.__getPreviewInfoTooltip(tooltipBody, addInfo) if self.__state in (MARATHON_STATE.IN_PROGRESS, MARATHON_STATE.FINISHED): tooltipBody = body.progress.withDiscount() if self.getMarathonDiscount() else body.progress() endVehicleSellDate = text_styles.neutral(finishSaleTime) addInfo = backport.text(addInfo.progress(), endVehicleSellDate=endVehicleSellDate, addInfo=backport.text(self.tooltips.previewInProgress)) return self.__getPreviewInfoTooltip(tooltipBody, addInfo) return makeTooltip() def getPreviewBuyBtnData(self): buyImage = backport.image(R.images.gui.maps.icons.library.buyInWeb()) label = backport.text(_R_BUYING_PANEL.buyBtn.label.buy()) enabled = False questStartTime, _ = self.__getQuestStartFinishTime() questStartTimeText = self.__getDateTimeText(questStartTime) customOffer = None addInfo = backport.text(self.tooltips.previewAnnounce, marathonStartDate=text_styles.neutral(questStartTimeText)) tooltip = makeTooltip(header=backport.text(_R_BUYING_PANEL.buyBtn.tooltip.inactive.header()), body=backport.text(_R_BUYING_PANEL.buyBtn.tooltip.inactive.body(), addInfo=addInfo)) if self.__state == MARATHON_STATE.IN_PROGRESS or self.__state == MARATHON_STATE.FINISHED: enabled = True tooltip = makeTooltip(body=backport.text(_R_BUYING_PANEL.buyBtn.tooltip.active.body())) if self.getMarathonDiscount(): label = backport.text(_R_BUYING_PANEL.buyBtn.label.buyWithDiscount()) discountText = text_styles.stats(backport.text(_R_BUYING_PANEL.customOffer.discount())) discountValue = text_styles.promoTitle(' {}'.format(backport.text(R.strings.quests.action.discount.percent(), value=backport.getIntegralFormat(self.getMarathonDiscount())))) customOffer = ''.join((discountText, discountValue)) return {'enabled': enabled, 'label': label, 'btnIcon': buyImage, 'btnIconAlign': _BUYING_BUTTON_ICON_ALIGN, 'btnTooltip': tooltip, 'customOffer': customOffer} def _getUrl(self, urlType=MarathonConfig.URL): baseUrl = self._lobbyContext.getServerSettings().getMarathonConfig().get(urlType, MarathonConfig.EMPTY_PATH) if not baseUrl: _logger.warning('Marathon url from marathon_config.xml is absent or invalid: %s', baseUrl) return baseUrl def __getDateTimeText(self, dateTime): localDateTime = getTimeStructInLocal(dateTime) monthName = backport.text(R.strings.menu.dateTime.months.dyn('c_{}'.format(localDateTime.tm_mon))()) dateTimeText = backport.text(R.strings.marathon.vehiclePreview.tooltip.dateTime(), day=localDateTime.tm_mday, monthName=monthName, year=localDateTime.tm_year, hour=localDateTime.tm_hour, min='{min:02d}'.format(min=localDateTime.tm_min)) return self.__noWrapTextFormat(dateTimeText) def __getPreviewInfoTooltip(self, tooltipBody, addInfo): return makeTooltip(header=backport.text(R.strings.marathon.vehiclePreview.title.tooltip.header()), body=backport.text(tooltipBody, addInfo=addInfo)) def __getRewardShownMarkKey(self, key): return '_'.join([key, self.tokenPrefix]) def __setScreenWasShown(self, key): AccountSettings.setUIFlag(self.__getRewardShownMarkKey(key), True) def __setRewardObtained(self, obtained): self.__rewardObtained = obtained def __findEarliestQuest(self, quest): return quest.getStartTimeLeft() def __marathonFilterFunc(self, q): return q.getID().startswith(self.prefix) def __getProgress(self, progressType, prefix=None, postfix=None): progress = {} if progressType == 'quests': progress = self._eventsCache.questsProgress.getQuestsData() elif progressType == 'tokens': progress = self._eventsCache.questsProgress.getTokensData() if prefix: progress = {k:v for k, v in progress.iteritems() if k.startswith(prefix)} if postfix: progress = {k:v for k, v in progress.iteritems() if k.endswith(postfix)} return progress def __getHangarFlagHeaderIcon(self): for key, imgPath in self.icons.mapFlagHeaderIcon.iteritems(): if self.__state in key: return imgPath def __getHangarFlagStateIcon(self, vehicle): if self.__state not in MARATHON_STATE.ENABLED_STATE: return '' if self.isRewardObtained(): return self.icons.okIcon if self.__state == MARATHON_STATE.NOT_STARTED: return self.icons.timeIcon if self.__state == MARATHON_STATE.IN_PROGRESS: warning = self.checkForWarnings(vehicle) if warning: return self.icons.alertIcon _, firstQuestFinishTimeLeft = self.__getQuestTimeInterval() if firstQuestFinishTimeLeft > ONE_DAY: return self.icons.iconFlag if firstQuestFinishTimeLeft <= ONE_DAY: return self.icons.timeIcon return self.icons.saleIcon if self.__state == MARATHON_STATE.FINISHED else '' def __noWrapTextFormat(self, text): return text.replace(' ', ' ') def __getTillTimeEnd(self, value): return self.__getFormattedTillTimeString(value, self.tooltips.stateEnd) def __getTillTimeStart(self, value): return self.__getFormattedTillTimeString(value, self.tooltips.stateStart, extraFmt=True) def __getProgressInDays(self, value): return self.__getTextInDays(value, self.tooltips.stateProgress) def __getTextInDays(self, timeValue, keyNamespace): gmtime = time.gmtime(timeValue) text = text_styles.stats(backport.text(self.tooltips.daysShort, value=str(time.struct_time(gmtime).tm_yday))) return text_styles.main(backport.text(keyNamespace, value=text)) def __getFormattedTillTimeString(self, timeValue, keyNamespace, extraFmt=False): gmtime = time.gmtime(timeValue) if timeValue >= ONE_DAY: text = backport.text(self.tooltips.daysShort, value=str(gmtime.tm_yday)) elif timeValue >= ONE_HOUR: text = backport.text(self.tooltips.hoursShort, value=str(gmtime.tm_hour + 1)) else: text = backport.text(self.tooltips.minutesShort, value=str(gmtime.tm_min + 1)) return text_styles.main(backport.text(keyNamespace, value=text_styles.stats(text))) if extraFmt or timeValue >= ONE_DAY else text_styles.tutorial(backport.text(keyNamespace, value=text)) def __getTooltip(self): return self.flagTooltip if self.isAvailable() else self.disabledFlagTooltip def __getTimeFromGroupStart(self): return self.__group.getTimeFromStartTillNow() if self.__group else ZERO_TIME def __getGroupTimeInterval(self): return (self.__group.getStartTimeLeft(), self.__group.getFinishTimeLeft()) if self.__group else (ZERO_TIME, ZERO_TIME) def __getQuestTimeInterval(self): return (self.__quest.getStartTimeLeft(), self.__quest.getFinishTimeLeft()) if self.__quest else (ZERO_TIME, ZERO_TIME) def __getQuestStartFinishTime(self): return (self.__quest.getStartTimeRaw(), self.__quest.getFinishTimeRaw()) if self.__quest else (ZERO_TIME, ZERO_TIME) def __getGroupStartFinishTime(self): return (self.__group.getStartTimeRaw(), self.__group.getFinishTimeRaw()) if self.__group else (ZERO_TIME, ZERO_TIME)
def externalBrowser(self, cmd): linkCtrl = dependency.instance(IExternalLinksController) urlParser = URLMacros(allowedMacroses=['DB_ID']) url = yield urlParser.parse(url=cmd.url) linkCtrl.open(url)
class BrowserController(IBrowserController): def __init__(self): super(BrowserController, self).__init__() self.__browsers = {} self.__browsersCallbacks = {} self.__browserCreationCallbacks = {} self.__browserIDGenerator = SequenceIDGenerator() self.__eventMgr = Event.EventManager() self.onBrowserAdded = Event.Event(self.__eventMgr) self.onBrowserDeleted = Event.Event(self.__eventMgr) self.__urlMacros = URLMacros() self.__pendingBrowsers = {} self.__creatingBrowserID = None self.__filters = _getGlobalFilters() return def fini(self): self.__filters = None self.__eventMgr.clear() self.__eventMgr = None self.__urlMacros.clear() self.__urlMacros = None self.__browsersCallbacks.clear() self.__browsersCallbacks = None self.__browsers.clear() self.__browsers = None self.__pendingBrowsers.clear() self.__pendingBrowsers = None self.__browserIDGenerator = None super(BrowserController, self).fini() return def onAvatarBecomePlayer(self): self.__stop() BigWorld.destroyBrowser() def onDisconnected(self): self.__stop() BigWorld.destroyBrowser() def onLobbyStarted(self, ctx): BigWorld.createBrowser() def addFilterHandler(self, handler): self.__filters.add(handler) def removeFilterHandler(self, handler): self.__filters.discard(handler) @async @process def load(self, url=None, title=None, showActionBtn=True, showWaiting=True, browserID=None, isAsync=False, browserSize=None, isDefault=True, callback=None, showCloseBtn=False, useBrowserWindow=True, isModal=False, showCreateWaiting=False, handlers=None, showBrowserCallback=None, isSolidBorder=False): if showCreateWaiting: Waiting.show('browser/init') url = yield self.__urlMacros.parse(url or GUI_SETTINGS.browser.url) suffix = yield self.__urlMacros.parse(GUI_SETTINGS.browser.params) concatenator = '&' if '?' in url else '?' if suffix not in url: url = concatenator.join([url, suffix]) size = browserSize or BROWSER.SIZE webBrowserID = browserID if browserID is None: browserID = self.__browserIDGenerator.next() webBrowserID = browserID elif not isinstance(browserID, int): webBrowserID = self.__browserIDGenerator.next() ctx = { 'url': url, 'title': title, 'showActionBtn': showActionBtn, 'showWaiting': showWaiting, 'browserID': browserID, 'size': size, 'isAsync': isAsync, 'showCloseBtn': showCloseBtn, 'showWindow': useBrowserWindow, 'alias': VIEW_ALIAS.BROWSER_WINDOW_MODAL if isModal else VIEW_ALIAS.BROWSER_WINDOW, 'showCreateWaiting': showCreateWaiting, 'handlers': handlers, 'showBrowserCallback': showBrowserCallback, 'isSolidBorder': isSolidBorder } if browserID not in self.__browsers and browserID not in self.__pendingBrowsers: appLoader = dependency.instance(IAppLoader) app = appLoader.getApp() if app is None: raise SoftException('Application can not be None') browser = WebBrowser(webBrowserID, app, size, url, handlers=self.__filters) self.__browsers[browserID] = browser if self.__isCreatingBrowser(): _logger.info('CTRL: Queueing a browser creation: %r - %s', browserID, url) self.__pendingBrowsers[browserID] = ctx else: self.__createBrowser(ctx) elif browserID in self.__pendingBrowsers: _logger.info( 'CTRL: Re-queuing a browser creation, overriding: %r - %s', browserID, url) self.__pendingBrowsers[browserID] = ctx elif browserID in self.__browsers: _logger.info('CTRL: Re-navigating an existing browser: %r - %s', browserID, url) browser = self.__browsers[browserID] browser.navigate(url) browser.changeTitle(title) callback(browserID) return def getAllBrowsers(self): return self.__browsers def getBrowser(self, browserID): return self.__browsers.get(browserID) def delBrowser(self, browserID): if browserID in self.__browsers: _logger.info('CTRL: Deleting a browser: %s', browserID) browser = self.__browsers.pop(browserID) self.__clearCallbacks(browserID, browser, True) browser.destroy() if self.__creatingBrowserID == browserID: self.__creatingBrowserID = None self.__tryCreateNextPendingBrowser() if browserID in self.__pendingBrowsers: del self.__pendingBrowsers[browserID] self.onBrowserDeleted(browserID) return def __isCreatingBrowser(self): return self.__creatingBrowserID is not None def __createDone(self, ctx): _logger.info('CTRL: Finished creating a browser: %r', self.__creatingBrowserID) if ctx['showCreateWaiting']: Waiting.hide('browser/init') def __tryCreateNextPendingBrowser(self): self.__creatingBrowserID = None if self.__pendingBrowsers: nextCtx = self.__pendingBrowsers.popitem()[1] self.__createBrowser(nextCtx) return def __createBrowser(self, ctx): browserID = ctx['browserID'] _logger.info('CTRL: Creating a browser: %r - %s', browserID, ctx['url']) self.__creatingBrowserID = browserID browser = self.__browsers[browserID] if not browser.create(): _logger.info('CTRL: Failed the create step: %r', browserID) self.delBrowser(browserID) self.__tryCreateNextPendingBrowser() return else: self.onBrowserAdded(browserID) def createNextBrowser(): _logger.info( 'CTRL: Triggering create of next browser from: %r', browserID) creation = self.__browserCreationCallbacks.pop(browserID, None) if creation is not None: self.__browsers[ browserID].onCanCreateNewBrowser -= creation self.__tryCreateNextPendingBrowser() return def failedCreationCallback(url): _logger.info('CTRL: Failed a creation: %r - %s', browserID, url) self.__clearCallbacks(browserID, self.__browsers[browserID], False) self.delBrowser(browserID) def successfulCreationCallback(url, isLoaded, httpStatusCode=None): _logger.info('CTRL: Ready to show: %r isLoaded: %r %s', browserID, isLoaded, url) self.__clearCallbacks(browserID, self.__browsers[browserID], False) if isLoaded: self.__showBrowser(browserID, ctx) else: _logger.warning('Browser request url %s was not loaded!', url) g_eventBus.handleEvent( BrowserEvent(BrowserEvent.BROWSER_CREATED, ctx=ctx)) self.__createDone(ctx) def titleUpdateCallback(title): ctx['title'] = title browser.onCanCreateNewBrowser += createNextBrowser self.__browserCreationCallbacks[browserID] = createNextBrowser browser.onFailedCreation += failedCreationCallback browser.onTitleChange += titleUpdateCallback if ctx['isAsync']: self.__browsersCallbacks[browserID] = ( None, successfulCreationCallback, failedCreationCallback, titleUpdateCallback) browser.onLoadEnd += successfulCreationCallback else: self.__browsersCallbacks[browserID] = ( successfulCreationCallback, None, failedCreationCallback, titleUpdateCallback) browser.onReady += successfulCreationCallback return def __stop(self): while self.__browsers: browserID, browser = self.__browsers.popitem() self.__clearCallbacks(browserID, browser, True) browser.destroy() def __clearCallbacks(self, browserID, browser, incDelayedCreation): ready, loadEnd, failed, title = self.__browsersCallbacks.pop( browserID, (None, None, None, None)) if browser is not None: if failed is not None: browser.onFailedCreation -= failed if ready is not None: browser.onReady -= ready if loadEnd is not None: browser.onLoadEnd -= loadEnd if title is not None: browser.onTitleChange -= title if incDelayedCreation: creation = self.__browserCreationCallbacks.pop(browserID, None) if browser is not None and creation is not None: browser.onCanCreateNewBrowser -= creation return def __showBrowser(self, browserID, ctx): _logger.info('CTRL: Showing a browser: %r - %s', browserID, ctx['url']) if ctx.get('showWindow'): alias = ctx['alias'] g_eventBus.handleEvent( LoadViewEvent(SFViewLoadParams(alias, getViewName(alias, browserID)), ctx=ctx), EVENT_BUS_SCOPE.LOBBY) showBrowserCallback = ctx.get('showBrowserCallback') if showBrowserCallback: showBrowserCallback()
class EventProgressionController(IEventProgressionController): __lobbyContext = dependency.descriptor(ILobbyContext) __itemsCache = dependency.descriptor(IItemsCache) __eventsCache = dependency.descriptor(IEventsCache) __connectionMgr = dependency.descriptor(IConnectionManager) __questController = dependency.descriptor(IQuestsController) onUpdated = Event.Event() def __init__(self): self.__urlMacros = URLMacros() self.__isEnabled = False self.__isFrontLine = False self.__isSteelHunter = False self.__url = '' self.__actualRewardPoints = 0 self.__seasonRewardPoints = 0 self.__maxRewardPoints = 0 self.__rewardPointsTokenID = '' self.__seasonPointsTokenID = '' self.__rewardVehicles = [] self.__currentMode = None self.__questCardLevelTxtId = 0 self.__progressionNameCycleTxtId = 0 self.__progressionIconId = 0 self.__selectorLabelTxtId = 0 self.__selectorRibbonResId = 0 self.__allCyclesWasEndedResId = 0 self.__selectorData = 0 self.__selectorType = 0 self.__selectorQueueType = 0 self.__questPrefix = '' self.__activeQuestIDs = [] self.__primeTimeTitle = '' self.__primeTimeBg = '' return @property def isEnabled(self): return self.__isEnabled @property def isFrontLine(self): return self.__isEnabled and self.__isFrontLine @property def isSteelHunter(self): return self.__isEnabled and self.__isSteelHunter @property def url(self): return self.__url @property def questPrefix(self): return self.__questPrefix @property def actualRewardPoints(self): return self.__actualRewardPoints @property def seasonRewardPoints(self): dossier = self.__itemsCache.items.getAccountDossier() achievements = dossier.getDossierDescr().expand('epicSeasons') achievements = chain( achievements.items(), dossier.getDossierDescr().expand('battleRoyaleSeasons').items()) seasonRewardPoints = self.__seasonRewardPoints for (seasonID, cycleID), cycleAchievements in achievements: if not self.validateSeasonData(seasonID, cycleID): continue _, _, awardPoints, _ = cycleAchievements seasonRewardPoints += awardPoints return seasonRewardPoints @property def maxRewardPoints(self): return self.__maxRewardPoints @property def rewardPointsTokenID(self): return self.__rewardPointsTokenID @property def rewardVehicles(self): return self.__rewardVehicles @property def questCardLevelTxtId(self): return self.__questCardLevelTxtId @property def flagIconId(self): return self.__flagIconId @property def questTooltipHeaderIconId(self): return self.__questTooltipHeaderIconId @property def questTooltipHeaderTxtId(self): return self.__questTooltipHeaderTxtId @property def selectorLabelTxtId(self): return self.__selectorLabelTxtId @property def selectorRibbonResId(self): return self.__selectorRibbonResId @property def aboutEventProgressionResId(self): if self.__currentMode: if self.__currentMode.getCurrentSeason( ) or self.__currentMode.getNextSeason(): self.__allCyclesWasEndedResId = R.strings.event_progression.selectorTooltip.eventProgression.waitNext( ) else: self.__allCyclesWasEndedResId = R.strings.event_progression.selectorTooltip.eventProgression.ended( ) return self.__allCyclesWasEndedResId @property def selectorData(self): return self.__selectorData @property def selectorType(self): return self.__selectorType @property def selectorQueueType(self): return self.__selectorQueueType @process def openURL(self, url=None): requestUrl = url or self.__url if requestUrl: parsedUrl = yield self.__urlMacros.parse(requestUrl) if parsedUrl: _showBrowserView(parsedUrl) def getProgressionXPTokenID(self): return self.__currentController.PROGRESSION_XP_TOKEN if self.__currentController else '' def isAvailable(self): return self.isFrontLine or self.isSteelHunter def modeIsEnabled(self): return self.__currentController.getModeSettings( ).isEnabled if self.__currentController else False def modeIsAvailable(self): return self.isAvailable() and self.isInPrimeTime() and self.isActive() def isFrozen(self): if self.__currentController: for primeTime in self.getPrimeTimes().values(): if primeTime.hasAnyPeriods(): return False return True def isActive(self): return self.modeIsEnabled( ) and self.__currentController.getCurrentSeason( ) is not None and self.__currentController.getCurrentCycleInfo( )[1] if self.__currentController else False def isDailyQuestsRefreshAvailable(self): dayTimeLeft = time_utils.getDayTimeLeft() cycleTimeLeft = self.getCurrentCycleTimeLeft() currentPrimeTimeEnd = self.getCurrentPrimeTimeEnd() if currentPrimeTimeEnd is None: return False else: primeTimeTimeLeft = currentPrimeTimeEnd - time_utils.getCurrentLocalServerTimestamp( ) state1 = self.hasPrimeTimesLeft( ) or primeTimeTimeLeft > dayTimeLeft state2 = cycleTimeLeft > dayTimeLeft return state1 and state2 def getPlayerLevelInfo(self): if not (self.isSteelHunter or self.isFrontLine): return PlayerLevelInfo(None, None) else: levelInfo = self.__currentController.getPlayerLevelInfo() if self.isFrontLine: levelInfo = self.__currentController.getPlayerLevelInfo()[1:] return PlayerLevelInfo(*levelInfo) def getActiveQuestIDs(self): self.__activeQuestIDs = [ q.getID() for q in self.getActiveQuestsAsDict().values() ] return self.__activeQuestIDs def getActiveQuestsAsDict(self): if not (self.__isEnabled and self.modeIsEnabled()): return {} quests = { k: v for k, v in self.__eventsCache.getQuests().items() if self.__isActiveQuest(v) } return quests def getQuestForVehicle(self, vehicle, sortByPriority=False, questIDs=None): questIDs = questIDs if questIDs is not None else self.getActiveQuestIDs( ) quests = [ q for q in self.__questController.getQuestForVehicle(vehicle) if q.getID() in questIDs ] if sortByPriority: quests.sort(key=lambda _q: _q.getPriority(), reverse=True) return quests def isUnavailableQuestByID(self, questID): if questID not in self.__activeQuestIDs: return False if self.__isFrontLine: if not self.__isMaxLevel(): return True return False def getUnavailableQuestMessage(self, questID): if questID not in self.__activeQuestIDs: return '' if self.__isFrontLine: if not self.__isMaxLevel(): idMsg = R.strings.event_progression.questsTooltip.frontLine.notReachLevel( ) return backport.text( idMsg, level=self.__currentController.getMaxPlayerLevel()) def getRewardVehiclePrice(self, vehicleCD): return {intCD: price for intCD, price in self.__rewardVehicles}.get(vehicleCD, 0) def getAllLevelAwards(self): awardsData = dict() abilityPts = None if self.isFrontLine: abilityPts = self.__lobbyContext.getServerSettings( ).epicMetaGame.metaLevel['abilityPointsForLevel'] allQuests = self.__eventsCache.getAllQuests() for questKey, questData in allQuests.iteritems(): if self.__currentController.TOKEN_QUEST_ID in questKey: _, _, questNum = questKey.partition( self.__currentController.TOKEN_QUEST_ID) if questNum: questLvl = int(questNum) questBonuses = questData.getBonuses() awardsData[questLvl] = self.__packBonuses( questBonuses, questLvl, abilityPts) return awardsData def getLevelAwards(self, level): allAwards = self.getAllLevelAwards() return allAwards[level] if level in allAwards else [] def showCustomScreen(self, screen): if self.__url and EventProgressionScreens.hasValue(screen): self.openURL('/'.join( (self.__url.strip('/'), screen.value.strip('/')))) def getPrimeTimeTitle(self): return self.__primeTimeTitle def getPrimeTimeBg(self): return self.__primeTimeBg def onPrimeTimeStatusUpdatedAddEvent(self, event): if self.__currentController: self.__currentController.onPrimeTimeStatusUpdated += event def onPrimeTimeStatusUpdatedRemoveEvent(self, event): if self.__currentController: self.__currentController.onPrimeTimeStatusUpdated -= event def getTimer(self): return self.__currentController.getTimer() def isInPrimeTime(self): _, _, isNow = self.getPrimeTimeStatus() return isNow @classmethod def validateSeasonData(cls, seasonID, cycleID): seasonValidationData = { season.getSeasonID(): [cycle.ID for cycle in season.getAllCycles().values()] for season in cls.getMostRelevantSeasons().itervalues() } return seasonID in seasonValidationData and cycleID in seasonValidationData.get( seasonID, []) @classmethod def getMostRelevantSeasons(cls): epicMetaGameCtrl = dependency.instance(IEpicBattleMetaGameController) battleRoyaleCtrl = dependency.instance(IBattleRoyaleController) seasons = { key: value for key, value in zip(('frontline', 'battle_royale'), (first( filter(None, (mode.getCurrentSeason(), mode.getNextSeason(), mode.getPreviousSeason()))) for mode in ( epicMetaGameCtrl, battleRoyaleCtrl))) } return seasons @classmethod def getCalendarInfo(cls): calendarData = dict() for key, selectedSeason in cls.getMostRelevantSeasons().iteritems(): if selectedSeason is not None: calendarData[key] = {} calendarData[key]['season'] = { 'id': selectedSeason.getSeasonID(), 'start': selectedSeason.getStartDate(), 'end': selectedSeason.getEndDate() } calendarData[key]['cycles'] = [{ 'id': cycle.ID, 'start': cycle.startDate, 'end': cycle.endDate, 'announce_only': cycle.announceOnly } for cycle in selectedSeason.getAllCycles().values()] return calendarData def getCurrentSeason(self): return self.__currentController.getCurrentSeason( ) if self.__currentController else None def getNextSeason(self): return self.__currentController.getNextSeason( ) if self.__currentController else None def getPreviousSeason(self): return self.__currentController.getPreviousSeason( ) if self.__currentController else None def hasAnySeason(self): return self.__currentController.hasAnySeason( ) if self.__currentController else False def getCurrentOrNextActiveCycleNumber(self, season): return self.__currentController.getCurrentOrNextActiveCycleNumber( season) if self.__currentController else 0 def getMaxPlayerLevel(self): return self.__currentController.getMaxPlayerLevel() def isNeedAchieveMaxLevelForDailyQuest(self): level, _ = self.getPlayerLevelInfo() return True if self.isFrontLine and level < self.getMaxPlayerLevel( ) else False def getCurrentCycleInfo(self): return self.__currentController.getCurrentCycleInfo( ) if self.__currentController else (None, False) def getPrimeTimeStatus(self, peripheryID=None): return self.__currentController.getPrimeTimeStatus( peripheryID) if self.__currentController else ( PrimeTimeStatus.NOT_SET, 0, False) def hasAvailablePrimeTimeServers(self): if self.__connectionMgr.isStandalone(): allPeripheryIDs = {self.__connectionMgr.peripheryID} else: allPeripheryIDs = set([ host.peripheryID for host in g_preDefinedHosts.hostsWithRoaming() ]) for peripheryID in allPeripheryIDs: primeTimeStatus, _, _ = self.getPrimeTimeStatus(peripheryID) if primeTimeStatus == PrimeTimeStatus.AVAILABLE: return True return False def getPrimeTimesForDay(self, selectedTime, groupIdentical=False): return self.__currentController.getPrimeTimesForDay( selectedTime, groupIdentical) def getPrimeTimes(self): return self.__currentController.getPrimeTimes( ) if self.__currentController else (0, 0, False) def getPerformanceGroup(self): return self.__currentController.getPerformanceGroup( ) if self.__currentController else None def getCurrentCycleTimeLeft(self): currentCycleEndTime, isCycleActive = self.getCurrentCycleInfo() cycleTimeLeft = currentCycleEndTime - time_utils.getCurrentLocalServerTimestamp( ) if isCycleActive else None return cycleTimeLeft def getCurrentPrimeTimeEnd(self): primeTimes = self.getPrimeTimes() currentPrimeTimeEnd = None for primeTime in primeTimes.values(): periods = primeTime.getPeriodsActiveForTime( time_utils.getCurrentLocalServerTimestamp()) for period in periods: _, endTime = period currentPrimeTimeEnd = max(endTime, currentPrimeTimeEnd) return currentPrimeTimeEnd def hasPrimeTimesLeft(self): currentCycleEndTime, isCycleActive = self.getCurrentCycleInfo() if not isCycleActive: return False primeTimes = self.getPrimeTimes() return any([ primeTime.getNextPeriodStart( time_utils.getCurrentLocalServerTimestamp(), currentCycleEndTime) for primeTime in primeTimes.values() ]) def getStats(self): return self.__currentController.getStats() def getPointsProgressForLevel(self, level): return self.__currentController.getPointsProgressForLevel(level) def getEpicMetascreenData(self): if self.isFrontLine: metaGameStats = self.getStats() data = { 'average_xp': metaGameStats.averageXP, 'is_reserves_available_in_fl_menu': self.__currentController.isReservesAvailableInFLMenu() } return data elif self.isSteelHunter: metaGameStats = self.getStats() data = {'kill_count': metaGameStats.killCount} return data else: return None def onLobbyInited(self, ctx): self.__lobbyContext.getServerSettings( ).onServerSettingsChange += self.__onServerSettingsChange self.__itemsCache.onSyncCompleted += self.__updatePlayerData self.__updateSettings() self.__updatePlayerData() def isCurrentSeasonInPrimeTime(self): season = self.getCurrentSeason() if season is None or season.getCycleInfo() is None: return False else: isInPrime = not self.isInPrimeTime() isEnable = self.modeIsEnabled() isAvailable = self.modeIsAvailable() return isInPrime and isEnable and not isAvailable and season.getCycleInfo( ) def getHeaderTooltipPack(self): items = [self.__getTopBackgroundTooltipWithTextData()] bottom = -30 if not self.isCurrentSeasonInPrimeTime() and not self.modeIsAvailable( ): items.append(self.__getRewardVehiclesData()) bottom = 0 return formatters.packBuildUpBlockData( items, padding=formatters.packPadding(bottom=bottom)) def getSeasonInfoTooltipPack(self): season = self.getCurrentSeason() or self.getNextSeason() currentTime = time_utils.getCurrentLocalServerTimestamp() isPrimeTime = self.isCurrentSeasonInPrimeTime() if isPrimeTime or self.modeIsAvailable(): cycle = season.getCycleInfo() getDate = lambda c: c.endDate getTimeToStr = getTimeToLeftStr else: cycle = season.getNextByTimeCycle(currentTime) if season else None getDate = lambda c: c.startDate getTimeToStr = getTimeToStartStr if cycle is not None: cycleNumber = self.getCurrentOrNextActiveCycleNumber(season) if self.modeIsEnabled(): title = backport.text(self.__progressionNameCycleTxtId, season=int2roman(cycleNumber)) else: title = backport.text(self.__selectorLabelTxtId) description = getTimeToStr( getDate(cycle) - currentTime) if self.modeIsEnabled() else backport.text( R.strings.tooltips.eventProgression.disabled()) else: title = '' description = '' if self.isFrontLine: title = backport.text( R.strings.tooltips.eventProgression.allSeasonsAreOver()) description = backport.text( R.strings.tooltips.eventProgression.allSeasonsAreOver()) elif self.isSteelHunter: title = backport.text(self.__allCyclesWasEndedResId) return formatters.packBuildUpBlockData([ formatters.packImageTextBlockData( title=text_styles.middleTitle(title), txtPadding=formatters.packPadding(top=8, left=94), desc=text_styles.main(description), descPadding=formatters.packPadding(top=8, left=94), txtOffset=1, txtGap=-1, img=backport.image(self.__progressionIconId), imgPadding=formatters.packPadding(top=1, left=18)) ]) def getCurrentModeAlias(self): return self.__currentController.MODE_ALIAS def getCycleStatusTooltipPack(self): items = [] season = self.__currentController.getCurrentSeason( ) or self.__currentController.getNextSeason() levelInfo = self.getPlayerLevelInfo() cycleNumber = self.getCurrentOrNextActiveCycleNumber(season) seasonStr = backport.text(self.__progressionNameCycleTxtId, season=int2roman(cycleNumber)) seasonDescr = text_styles.middleTitle(seasonStr) items.append( formatters.packTextBlockData(text=seasonDescr, useHtml=True, padding=formatters.packPadding( left=20, right=20))) currentCycle = season.getCycleInfo() tDiff = currentCycle.endDate - time_utils.getCurrentLocalServerTimestamp( ) if currentCycle is not None else 0 timeLeft = text_styles.main(getTimeToLeftStr(tDiff)) items.append( formatters.packTextBlockData(text=timeLeft, useHtml=True, padding=formatters.packPadding( left=20, right=20))) linkage = BLOCKS_TOOLTIP_TYPES.TOOLTIP_BATTLE_ROYALE_META_LEVEL_BLOCK_LINKAGE if self.isSteelHunter else BLOCKS_TOOLTIP_TYPES.TOOLTIP_EPIC_BATTLE_META_LEVEL_BLOCK_LINKAGE items.append( formatters.packBuildUpBlockData( blocks=[ formatters.packBlockDataItem( linkage=linkage, data=getProgressionIconVODict( cycleNumber=cycleNumber, playerLevel=levelInfo.currentLevel)) ], layout=BLOCKS_TOOLTIP_TYPES.LAYOUT_HORIZONTAL, align=BLOCKS_TOOLTIP_TYPES.ALIGN_CENTER)) items.append(getLevelData(levelInfo.currentLevel)) if levelInfo.currentLevel < self.getMaxPlayerLevel(): items.append( self.__getCurrentMaxProgress( playerLevel=levelInfo.currentLevel, playerFamePts=levelInfo.levelProgress)) items.append( self.__getPlayerProgressToLevelBlock( playerLevel=levelInfo.currentLevel, playerFamePts=levelInfo.levelProgress)) else: unlockedStr = backport.text( R.strings.tooltips.eventProgression.unlockedDailyMissions()) items.append( formatters.packTextBlockData( text=text_styles.main(unlockedStr), useHtml=True, padding=formatters.packPadding(left=20, right=20, top=-7))) return formatters.packBuildUpBlockData(items) def getExchangeInfo(self): exchange = self.__lobbyContext.getServerSettings( ).eventProgression.exchange return { 'expireTimestamp': exchange['expireTimestamp'], 'exchangeRate': exchange['exchangeRate'], 'loginDeadlineTimestamp': exchange['loginDeadlineTimestamp'] } @property def __currentController(self): if self.__currentMode is None: self.__updateSettings() return self.__currentMode def __isMaxLevel(self): modeCtrl = self.__currentController levelInfo = self.getPlayerLevelInfo() maxLevel = modeCtrl.getMaxPlayerLevel() return levelInfo.currentLevel >= maxLevel def __isActiveQuest(self, q): if self.__questPrefix not in q.getID(): return False if self.__isFrontLine: return True if self.__isSteelHunter: validationResult = q.isAvailable() isReqsAvailable = q.accountReqs.isAvailable() return (validationResult.isValid or validationResult.reason == 'dailyComplete') and isReqsAvailable return False def __packBonuses(self, bonuses, level, abilityPts): result = [{ 'id': 0, 'type': ItemPackType.CUSTOM_SUPPLY_POINT, 'value': abilityPts[level - 1], 'icon': { AWARDS_SIZES.SMALL: getRelativeUrl( backport.image(R.images.gui.maps.icons.epicBattles.awards. c_48x48.abilityToken())), AWARDS_SIZES.BIG: getRelativeUrl( backport.image(R.images.gui.maps.icons.epicBattles.awards. c_80x80.abilityToken())) } }] if abilityPts else [] for bonus in bonuses: bonusList = bonus.getWrappedEpicBonusList() for bonusEntry in bonusList: bonusEntry['icon'] = { size: getRelativeUrl(path) for size, path in bonusEntry['icon'].iteritems() } result.extend(bonusList) return result def __getPlayerProgressToLevelBlock(self, playerLevel, playerFamePts): famePtsToProgress = self.getPointsProgressForLevel(playerLevel) data = EpicBattlesWidgetTooltipVO(progressBarData={ 'value': playerFamePts, 'maxValue': famePtsToProgress })._asdict() res = formatters.packBlockDataItem( linkage=BLOCKS_TOOLTIP_TYPES. TOOLTIP_META_LEVEL_PROGRESS_BLOCK_LINKAGE, data=data, padding=formatters.packPadding(left=20)) return res def __getCurrentMaxProgress(self, playerLevel, playerFamePts): items = [] famePtsToProgress = self.getPointsProgressForLevel(playerLevel) currentPoint = text_styles.stats(str(playerFamePts)) fameTo = text_styles.main(str(famePtsToProgress)) currentPointMaxPoint = text_styles.concatStylesWithSpace( currentPoint, text_styles.main('/'), fameTo) text = text_styles.main(currentPointMaxPoint) marginTop = 7 icon = None if self.isFrontLine: marginTop = 0 iconSrc = backport.image( R.images.gui.maps.icons.epicBattles.fame_point_tiny()) icon = icons.makeImageTag(source=iconSrc, width=24, height=24) elif self.isSteelHunter: marginTop = 6 iconSrc = backport.image( R.images.gui.maps.icons.battleRoyale.progression_point()) icon = icons.makeImageTag(source=iconSrc, width=16, height=16) if icon is not None: text = text_styles.concatStylesWithSpace(text, icon) items.append( formatters.packAlignedTextBlockData( text=text, align=BLOCKS_TOOLTIP_TYPES.ALIGN_RIGHT, padding=formatters.packPadding(left=20, right=20, top=-35))) return formatters.packBuildUpBlockData( items, padding=formatters.packPadding(top=marginTop)) def __getRewardVehiclesData(self): getRewards = self.__getRewardVehicles rewardVehiclesNames = [ text_styles.stats(v.shortUserName) for v in getRewards() ] promo = R.strings.event_progression.selectorTooltip.eventProgression.promo text = backport.text( promo.multi() if len(rewardVehiclesNames) > 1 else promo.single(), vehicles=', '.join(rewardVehiclesNames[:-1]), vehicle=rewardVehiclesNames[-1]) return formatters.packTextBlockData(text_styles.main(text), padding=formatters.packPadding( top=-10, left=20, right=25)) def __getTopBackgroundTooltipWithTextData(self): header = text_styles.bonusLocalText( backport.text(R.strings.tooltips.eventProgression.header())) iconSrc = backport.image( R.images.gui.maps.icons.epicBattles.rewardPoints.c_16x16()) iconCurrency = icons.makeImageTag(source=iconSrc, width=16, height=16, vSpace=-3) currency = text_styles.concatStylesWithSpace( self.__getCurrencyCurrentStr(), iconCurrency) background = R.images.gui.maps.icons.epicBattles.backgrounds.widget_tooltip_background( ) return formatters.packImageTextBlockData( title=header, txtPadding=formatters.packPadding(top=16, left=20), desc=currency, descPadding=formatters.packPadding(top=6, left=20), txtOffset=1, txtGap=-1, img=backport.image(background)) def __getCurrencyCurrentStr(self): res = text_styles.main( backport.text(R.strings.tooltips.eventProgression.currency()) + ' ') + text_styles.stats(int(self.actualRewardPoints)) return res def __getRewardVehicles(self): rewardVehiclesIds = [intCD for intCD, _ in self.rewardVehicles] rewardVehicles = self.__itemsCache.items.getVehicles( REQ_CRITERIA.IN_CD_LIST(rewardVehiclesIds)) return [rewardVehicles[intCD] for intCD in rewardVehiclesIds] def __clear(self): self.__itemsCache.onSyncCompleted -= self.__updatePlayerData self.__lobbyContext.getServerSettings( ).onServerSettingsChange -= self.__onServerSettingsChange def __onServerSettingsChange(self, diff): if Configs.EVENT_PROGRESSION_CONFIG.value in diff: self.__updateSettings() self.onUpdated(diff) def __onSyncCompleted(self, *args, **kwargs): self.__updatePlayerData() self.onUpdated(args, kwargs) def __updateSettings(self): s = self.__lobbyContext.getServerSettings().eventProgression self.__isEnabled = s.isEnabled self.__isFrontLine = s.isFrontLine self.__isSteelHunter = s.isSteelHunter self.__url = s.url self.__maxRewardPoints = s.maxRewardPoints self.__rewardPointsTokenID = s.rewardPointsTokenID self.__seasonPointsTokenID = s.seasonPointsTokenID self.__rewardVehicles = s.rewardVehicles self.__questPrefix = s.questPrefix if self.isSteelHunter is True: self.__updateSteelHunterData() elif self.isFrontLine is True: self.__updateFrontLineData() else: self.__currentMode = None return def __updateFrontLineData(self): self.__currentMode = dependency.instance(IEpicBattleMetaGameController) self.__flagIconId = R.images.gui.maps.icons.library.hangarFlag.flag_epic( ) self.__questTooltipHeaderIconId = R.images.gui.maps.icons.quests.epic_quests_infotip( ) self.__questTooltipHeaderTxtId = R.strings.epic_battle.questsTooltip.epicBattle.header( ) self.__questCardLevelTxtId = R.strings.event_progression.questsCard.frontLine.getLevel( ) self.__progressionNameCycleTxtId = R.strings.tooltips.eventProgression.season( ) self.__progressionIconId = R.images.gui.maps.icons.battleTypes.c_64x64.frontline( ) self.__selectorLabelTxtId = R.strings.menu.headerButtons.battle.types.epic( ) self.__selectorRibbonResId = R.images.gui.maps.icons.epicBattles.ribbon_small( ) self.__selectorData = PREBATTLE_ACTION_NAME.EPIC self.__selectorType = SELECTOR_BATTLE_TYPES.EVENT_PROGRESSION self.__selectorQueueType = QUEUE_TYPE.EPIC self.__primeTimeTitle = R.strings.epic_battle.primeTime.title() self.__primeTimeBg = R.images.gui.maps.icons.epicBattles.primeTime.prime_time_back_default( ) self.__allCyclesWasEndedResId = R.strings.event_progression.selectorTooltip.eventProgression.waitNext( ) def __updateSteelHunterData(self): self.__currentMode = dependency.instance(IBattleRoyaleController) self.__flagIconId = R.images.gui.maps.icons.library.hangarFlag.flag_epic_steelhunter( ) self.__questTooltipHeaderIconId = R.images.gui.maps.icons.quests.epic_steelhunter_quests_infotip( ) self.__questTooltipHeaderTxtId = R.strings.epic_battle.questsTooltip.epicBattle.steelhunter.header( ) self.__questCardLevelTxtId = R.strings.event_progression.questsCard.steelHunter.getLevel( ) self.__progressionNameCycleTxtId = R.strings.tooltips.eventProgression.steelHunter.season( ) self.__progressionIconId = R.images.gui.maps.icons.battleTypes.c_64x64.steelhunt( ) self.__selectorLabelTxtId = R.strings.menu.headerButtons.battle.types.battleRoyale( ) self.__selectorRibbonResId = R.images.gui.maps.icons.battleRoyale.ribbon_small( ) self.__selectorData = PREBATTLE_ACTION_NAME.BATTLE_ROYALE self.__selectorType = SELECTOR_BATTLE_TYPES.BATTLE_ROYALE self.__selectorQueueType = QUEUE_TYPE.BATTLE_ROYALE self.__primeTimeTitle = R.strings.epic_battle.primeTime.steelhunter.title( ) self.__primeTimeBg = R.images.gui.maps.icons.battleRoyale.primeTime.prime_time_back_default( ) self.__allCyclesWasEndedResId = R.strings.event_progression.selectorTooltip.eventProgression.ended( ) def __updatePlayerData(self, *_): t = self.__itemsCache.items.tokens.getTokens() self.__actualRewardPoints = t.get(self.__rewardPointsTokenID, (0, 0))[1] self.__seasonRewardPoints = t.get(self.__seasonPointsTokenID, (0, 0))[1]
class RssNewsFeed(RssNewsFeedMeta): UPDATE_INTERVAL = 60 DESCRIPTION_MAX_LENGTH = 250 DESCRIPTION_TAIL = '...' DESCRIPTION_CUT_LENGTH = DESCRIPTION_MAX_LENGTH - len(DESCRIPTION_TAIL) SHOW_NEWS_COUNT = 3 externalBrowser = dependency.descriptor(IExternalLinksController) internalBrowser = dependency.descriptor(IBrowserController) def __init__(self): super(RssNewsFeed, self).__init__() self.__requestCbID = None self.__feed = [] self.__urlMacros = URLMacros() return def getFeed(self): return self.__feed def openBrowser(self, linkToOpen): if linkToOpen: openBrowser = self.externalBrowser.open if GUI_SETTINGS.loginRssFeed.internalBrowser: browser = self.internalBrowser if browser is not None: openBrowser = browser.load else: _logger.error( 'Attempting to open internal browser, but browseris not exist. External browser will be opened: %r', linkToOpen) _logger.debug('Open browser: %r', linkToOpen) openBrowser(linkToOpen) return def _populate(self): super(RssNewsFeed, self)._populate() self.__updateCallback() def _dispose(self): self.__urlMacros.clear() self.__urlMacros = None self.__feed = [] self.__clearCallback() super(RssNewsFeed, self)._dispose() return @process def __requestFeed(self): yield lambda callback: callback(True) if GUI_SETTINGS.loginRssFeed.show: requestUrl = yield self.__getRssUrl() from helpers.RSSDownloader import g_downloader as g_rss if g_rss is not None: g_rss.download(self.__onRssFeedReceived, url=requestUrl) _logger.debug('Requesting login RSS news: %s', requestUrl) return def __onRssFeedReceived(self, data): if self.isDisposed(): return else: self.__feed = [] for entry in reversed(data.get('entries', [])): data = self.__prepareData(entry) if data is not None: self.__feed.append(data) _logger.debug('RSS feed received, entries count %d', len(self.__feed)) self.as_updateFeedS(self.__feed[:self.SHOW_NEWS_COUNT]) return def __clearCallback(self): if self.__requestCbID is not None: BigWorld.cancelCallback(self.__requestCbID) self.__requestCbID = None return def __updateCallback(self): self.__requestFeed() self.__clearCallback() self.__requestCbID = BigWorld.callback(self.UPDATE_INTERVAL, self.__updateCallback) @async @process def __getRssUrl(self, callback): url = yield self.__urlMacros.parse(str(GUI_SETTINGS.loginRssFeed.url)) callback(url) def __prepareData(self, entryData): description = entryData.get('description') if description is not None: try: section = ResMgr.DataSection() section.createSectionFromString(encodeUtf8(description)) _, section = findFirst(lambda (name, _): name == 'div', section.items()) description, _ = unicode_from_utf8(section.asString) if len(description) > self.DESCRIPTION_MAX_LENGTH: description = description[:self. DESCRIPTION_CUT_LENGTH] + self.DESCRIPTION_TAIL except Exception: _logger.exception('Invalid RSS entry description: %r, %r', entryData, description) return return { 'id': entryData.get('id', str(uuid.uuid4())), 'link': entryData.get('link'), 'description': encodeUtf8(description) }
class VehiclePreviewBuyingPanel(VehiclePreviewBuyingPanelMeta): appLoader = dependency.descriptor(IAppLoader) _itemsCache = dependency.descriptor(IItemsCache) _goodiesCache = dependency.descriptor(IGoodiesCache) _comparisonBasket = dependency.descriptor(IVehicleComparisonBasket) _tradeIn = dependency.descriptor(ITradeInController) _restores = dependency.descriptor(IRestoreController) _heroTanks = dependency.descriptor(IHeroTankController) _lobbyContext = dependency.descriptor(ILobbyContext) _marathonsCtrl = dependency.descriptor(IMarathonEventsController) __calendarController = dependency.descriptor(ICalendarController) __linksCtrl = dependency.descriptor(IExternalLinksController) def __init__(self, skipConfirm=False): super(VehiclePreviewBuyingPanel, self).__init__() heroTankCD = self._heroTanks.getCurrentTankCD() self._vehicleCD = g_currentPreviewVehicle.item.intCD self._vehicleLevel = g_currentPreviewVehicle.item.level self._actionType = None self._skipConfirm = skipConfirm self._disableBuyButton = False self._marathonEvent = None self.__previewDP = DefaultVehPreviewDataProvider() self.__isHeroTank = heroTankCD and heroTankCD == self._vehicleCD self.__price = None self.__title = None self.__description = None self.__items = None self.__offers = None self.__currentOffer = None self.__styleByGroup = {} self.__vehicleByGroup = {} self.__endTime = None self.__oldPrice = MONEY_UNDEFINED self.__buyParams = None self.__backAlias = None self.__backCallback = None self.__timeCallbackID = None self.__timeLeftIcon = icons.makeImageTag( RES_ICONS.MAPS_ICONS_LIBRARY_TIME_ICON, 16, 16) self.__cachedVehiclesVOs = None self.__cachedItemsVOs = None self.__cachedCollapsedItemsVOs = None self.__couponInfo = None self.__hasSSEDiscount = False self.__urlMacros = URLMacros() g_techTreeDP.load() return def onBuyOrResearchClick(self): vehicle = g_currentPreviewVehicle.item shopPackage = self.__items is not None and self.__couponInfo is None frontlineCouponPackage = self.__couponInfo is not None and self.__couponInfo.selected if self._marathonEvent: self.__purchaseMarathonPackage() elif shopPackage or frontlineCouponPackage: self.__purchasePackage() elif self.__offers is not None: self.__purchaseOffer() elif self.__isHeroTank: self.__purchaseHeroTank() elif canBuyGoldForVehicleThroughWeb(vehicle): self.__purchaseSingleVehicle(vehicle) else: self.__research() return def onCouponSelected(self, isActive): if self.__couponInfo: self.__couponInfo.selected = isActive if isActive: self.__title = backport.text( R.strings.vehicle_preview.buyingPanel.frontlinePack. titleLabel.active()) elif self.__hasSSEDiscount: self.__title = backport.text( R.strings.vehicle_preview.buyingPanel.frontlinePack. titleLabel.inactive_add_discount()) else: self.__title = backport.text( R.strings.vehicle_preview.buyingPanel.frontlinePack. titleLabel.inactive()) self.__update() def setMarathonEvent(self, prefix): self._marathonEvent = self._marathonsCtrl.getMarathon(prefix) def setTimerData(self, endTime): if self.__couponInfo is not None: return else: if endTime is not None: self.__endTime = endTime self.__onLeftTimeUpdated() self.__updateBtnState() return def setInfoTooltip(self): tooltip = self._marathonEvent.getVehiclePreviewTitleTooltip() self.as_setSetTitleTooltipS(tooltip) def setBuyParams(self, buyParams): self.__buyParams = buyParams def setBackAlias(self, backAlias): self.__backAlias = backAlias def setBackCallback(self, backCallback): self.__backCallback = backCallback def setIsHeroTank(self, isHero): self.__isHeroTank = isHero def setPackItems(self, packItems, price, oldPrice, title): self.__title = title if title is not None else '' self.__price = price self.__hasSSEDiscount = oldPrice != MONEY_UNDEFINED self.__oldPrice = oldPrice self.__items = packItems self.__styleByGroup.clear() self.__vehicleByGroup.clear() vehiclesItems, items = self.__previewDP.separateItemsPack(self.__items) for item in items: if item.type in ItemPackTypeGroup.STYLE and item.groupID not in self.__styleByGroup: self.__styleByGroup[item.groupID] = item.id if item.type in ItemPackTypeGroup.DISCOUNT: self.__title = backport.text( R.strings.vehicle_preview.buyingPanel.frontlinePack. titleLabel.active()) self.__couponInfo = _CouponData(item=item, selected=True) self.as_setCouponS( self.__previewDP.packCouponData( self.__items, self.__price.get(Currency.GOLD))) if not self.__oldPrice: self.__oldPrice = self.__price for vehicleItem in vehiclesItems: self.__vehicleByGroup[vehicleItem.id] = vehicleItem.groupID vehiclesVOs, itemsVOs, collapseItemsVOs = self.__previewDP.getItemsPackData( g_currentPreviewVehicle.item, items, vehiclesItems) self.__cachedVehiclesVOs = vehiclesVOs self.__cachedItemsVOs = itemsVOs self.__cachedCollapsedItemsVOs = collapseItemsVOs self.__update() return def onCarouselVehicleSelected(self, intCD): self._vehicleCD = intCD g_currentPreviewVehicle.selectVehicle(intCD) def setOffers(self, offers, title, description): self.__offers = offers self.__title = title self.__description = description selectedID = getActiveOffer(self.__offers).id offersData = self.__previewDP.getOffersData( self.__offers, selectedID) if len(self.__offers) > 1 else [] self.as_setOffersDataS(offersData) self.onOfferSelected(selectedID) def onOfferSelected(self, offerID): self.__currentOffer = findFirst(lambda o: o.id == offerID, self.__offers) if self.__currentOffer: vehicle = g_currentPreviewVehicle.item crew = self.__currentOffer.crew g_eventBus.handleEvent( HasCtxEvent(ctx={ 'vehicleItems': [ItemPackEntry(id=vehicle.intCD, groupID=crew.groupID)], 'crewItems': [crew], 'offer': self.__currentOffer }, eventType=OFFER_CHANGED_EVENT)) self.__buyParams = self.__currentOffer.buyParams self.__price = self.__currentOffer.buyPrice self.as_setBuyDataS( self.__previewDP.getOffersBuyingPanelData(self.__getBtnData())) description = self.__description or self.__getCurrentOfferDescription( ) or {} self.as_setSetTitleTooltipS(makeTooltip(**description)) def showTooltip(self, intCD, itemType): toolTipMgr = self.appLoader.getApp().getToolTipMgr() if itemType == BOX_TYPE: toolTipMgr.onCreateComplexTooltip( makeTooltip(TOOLTIPS.VEHICLEPREVIEW_BOXTOOLTIP_HEADER, TOOLTIPS.VEHICLEPREVIEW_BOXTOOLTIP_BODY), 'INFO') return try: try: itemId = int(intCD) except ValueError: itemId = intCD rawItem = [ item for item in self.__items if item.id == itemId and item.type == itemType ][0] item = lookupItem(rawItem, self._itemsCache, self._goodiesCache) showItemTooltip(toolTipMgr, rawItem, item) except IndexError: return def updateData(self, useCompactData): self.__update(collapseItems=False) def _populate(self): super(VehiclePreviewBuyingPanel, self)._populate() g_clientUpdateManager.addMoneyCallback(self.__updateBtnState) g_clientUpdateManager.addCallbacks({ 'stats.freeXP': self.__updateBtnState, 'inventory': self.__updateBtnState, 'serverSettings.blueprints_config': self.__onBlueprintsModeChanged }) g_currentPreviewVehicle.onVehicleUnlocked += self.__updateBtnState g_currentPreviewVehicle.onChanged += self.__onVehicleChanged self._heroTanks.onUpdated += self.__updateBtnState self._restores.onRestoreChangeNotify += self.__onRestoreChanged self._lobbyContext.getServerSettings( ).onServerSettingsChange += self.__onServerSettingsChanged self.addListener(CameraRelatedEvents.VEHICLE_LOADING, self.__onVehicleLoading) def _dispose(self): g_clientUpdateManager.removeObjectCallbacks(self) g_currentPreviewVehicle.onVehicleUnlocked -= self.__updateBtnState g_currentPreviewVehicle.onChanged -= self.__onVehicleChanged self._heroTanks.onUpdated -= self.__updateBtnState self._restores.onRestoreChangeNotify -= self.__onRestoreChanged self._lobbyContext.getServerSettings( ).onServerSettingsChange -= self.__onServerSettingsChanged self.removeListener(CameraRelatedEvents.VEHICLE_LOADING, self.__onVehicleLoading) self.__stopTimer() self.__styleByGroup.clear() self.__vehicleByGroup.clear() self.__urlMacros.clear() self.__urlMacros = None super(VehiclePreviewBuyingPanel, self)._dispose() return def __update(self, collapseItems=False): if self.__cachedVehiclesVOs: g_currentPreviewVehicle.selectVehicle( self.__cachedVehiclesVOs[0]['intCD']) self.as_setSetVehiclesDataS({'vehicles': self.__cachedVehiclesVOs}) if self.__couponInfo: self.__updateEnabledState(self.__cachedCollapsedItemsVOs, self.__couponInfo.selected) self.__updateEnabledState(self.__cachedItemsVOs, self.__couponInfo.selected) if collapseItems and self.__cachedCollapsedItemsVOs: self.as_setSetItemsDataS({'items': self.__cachedCollapsedItemsVOs}) elif self.__cachedItemsVOs: self.as_setSetItemsDataS({'items': self.__cachedItemsVOs}) self.__updateBtnState() def __getOfferByID(self, offerID): return findFirst(lambda o: o.buy_params['transactionID'] == offerID, self.__offers) def __isReferralWindow(self): return self.__backAlias == VIEW_ALIAS.REFERRAL_PROGRAM_WINDOW def __getConfirmationDialogKey(self): key = 'buyConfirmation' if self.__isReferralWindow(): key = 'referralReward' return key def __buyRequestConfirmation(self, key='buyConfirmation'): product = self.__title if self.__couponInfo is None else g_currentPreviewVehicle.item.shortUserName return DialogsInterface.showDialog(meta=I18nConfirmDialogMeta( key=key, messageCtx={ 'product': product, 'price': formatPrice(self.__getPackPrice(), reverse=True, useIcon=True) }, focusedID=DIALOG_BUTTON_ID.SUBMIT)) def __onVehicleLoading(self, ctxEvent): vehicle = g_currentPreviewVehicle.item if vehicle is None: return else: groupID = self.__vehicleByGroup.get(vehicle.intCD) if not ctxEvent.ctx.get( 'started') and groupID in self.__styleByGroup: customizationStyle = self.__styleByGroup[groupID] style = self._itemsCache.items.getItemByCD(customizationStyle) if style is not None and not style.isRentable: g_currentPreviewVehicle.previewStyle(style) return @process def __updateBtnState(self, *_): item = g_currentPreviewVehicle.item if item is None: return else: btnData = self.__getBtnData() self._actionType = self.__previewDP.getBuyType(item) if self.__items: buyingPanelData = self.__previewDP.getItemPackBuyingPanelData( btnData, self.__items, self.__couponInfo.selected if self.__couponInfo else False, self.__price.get(Currency.GOLD)) elif self.__offers: buyingPanelData = self.__previewDP.getOffersBuyingPanelData( btnData) else: buyingPanelData = self.__previewDP.getBuyingPanelData( item, btnData, self.__isHeroTank) buyingPanelData.update( {'isReferralEnabled': self.__isReferralWindow()}) hasExternalLink = yield self.__hasExternalLink() if hasExternalLink: btnIcon = backport.image( R.images.gui.maps.icons.library.buyInWeb()) buyingPanelData.update({ 'buyButtonIcon': btnIcon, 'buyButtonIconAlign': 'right' }) self.as_setBuyDataS(buyingPanelData) return def __onVehicleChanged(self, *_): if g_currentPreviewVehicle.isPresent(): self._vehicleCD = g_currentPreviewVehicle.item.intCD if not self.__price: self.__updateBtnState() def __onRestoreChanged(self, vehicles): if g_currentPreviewVehicle.isPresent(): if self._vehicleCD in vehicles: self.__updateBtnState() def __onServerSettingsChanged(self, diff): if self._lobbyContext.getServerSettings().isShopDataChangedInDiff( diff, 'isEnabled') or CollectorVehicleConsts.CONFIG_NAME in diff: self.__updateBtnState() def __onBlueprintsModeChanged(self, _): self.__updateBtnState() def __getBtnData(self): if self.__price is not None: return self.__getBtnDataPack() else: vehicle = g_currentPreviewVehicle.item if vehicle.isCollectible: return self.__getBtnDataCollectibleVehicle(vehicle) return self.__getBtnDataUnlockedVehicle( vehicle ) if vehicle.isUnlocked else self.__getBtnDataLockedVehicle( vehicle) def __getBtnDataPack(self): buyButtonTooltip = '' actionTooltip = None customOffer = None price = self.__getPackPrice() currency = price.getCurrency() walletAvailable = self.__walletAvailableForCurrency(currency) enabled = False if not walletAvailable: buyButtonTooltip = _buildBuyButtonTooltip('walletUnavailable') elif self._disableBuyButton: buyButtonTooltip = _buildBuyButtonTooltip('endTime') elif self.__price.isSet(currency): enabled = currency == Currency.GOLD or mayObtainForMoney( price) or mayObtainWithMoneyExchange(price) else: enabled = True if self.__currentOffer and self.__currentOffer.bestOffer and self.__currentOffer.eventType: actionTooltip = self.__getBestOfferTooltipData( self.__currentOffer.eventType) buttonIcon = None buttonIconAlign = None itemPrices = ItemPrice(price=price, defPrice=self.__oldPrice) specialData = getHeroTankPreviewParams() if self.__isHeroTank else None if specialData is not None and specialData.buyButtonLabel: buttonLabel = backport.text(specialData.buyButtonLabel) elif self.__isReferralWindow(): buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.obtain()) elif self._marathonEvent is not None: itemPrices = ITEM_PRICE_EMPTY buttonData = self._marathonEvent.getPreviewBuyBtnData() buttonLabel = buttonData['label'] enabled = buttonData['enabled'] buttonIcon = buttonData['btnIcon'] buttonIconAlign = buttonData['btnIconAlign'] buyButtonTooltip = buttonData['btnTooltip'] customOffer = buttonData['customOffer'] elif self.__items and self.__couponInfo is None: buttonLabel = backport.text(R.strings.vehicle_preview.buyingPanel. buyBtn.label.buyItemPack()) elif self.__offers and self.__currentOffer: buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.rent()) self.__title = self.__getCurrentOfferTitle() else: buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.buy()) isAction = self.__oldPrice.isDefined( ) and self.__oldPrice != self.__price or actionTooltip is not None or self.__couponInfo and self.__couponInfo.selected return _ButtonState(enabled=enabled, itemPrice=getItemPricesVO(itemPrices), label=buttonLabel, icon=buttonIcon, iconAlign=buttonIconAlign, isAction=isAction, actionTooltip=actionTooltip, tooltip=buyButtonTooltip, title=self.__title, isMoneyEnough=True, isUnlock=False, isPrevItemsUnlock=True, customOffer=customOffer, isShowSpecial=False) def __getPackPrice(self): if self.__couponInfo and self.__couponInfo.selected: discount = self.__couponInfo.discount currency = self.__price.getCurrency() if currency == Currency.GOLD: discountPrice = self.__price - discount return discountPrice.toNonNegative() return self.__price def __getBtnDataUnlockedVehicle(self, vehicle): money = self._itemsCache.items.stats.money money = self._tradeIn.addTradeInPriceIfNeeded(vehicle, money) buyButtonTooltip = '' actionTooltip = getActionPriceData(vehicle) exchangeRate = self._itemsCache.items.shop.exchangeRate priceType, price = getPriceTypeAndValue(vehicle, money, exchangeRate) itemPrice = chooseItemPriceVO(priceType, price) currency = price.getCurrency(byWeight=True) walletAvailable = self.__walletAvailableForCurrency(currency) buttonLabel = self.__getUnlockedVehicleBtnLabel(priceType) buttonIcon = None buttonIconAlign = None isAction = False minRentPricePackage = vehicle.getRentPackage() if minRentPricePackage: isAction = minRentPricePackage['rentPrice'] != minRentPricePackage[ 'defaultRentPrice'] elif not vehicle.isRestoreAvailable(): isAction = vehicle.buyPrices.getSum().isActionPrice() mayObtain = self.__isHeroTank or walletAvailable and vehicle.mayObtainWithMoneyExchange( money, exchangeRate) isBuyingAvailable = not vehicle.isHidden or vehicle.isRentable or vehicle.isRestorePossible( ) isMoneyEnough = True if not walletAvailable: buyButtonTooltip = _buildBuyButtonTooltip('walletUnavailable') elif not mayObtain and isBuyingAvailable: if currency == Currency.GOLD: mayObtain = True else: buyButtonTooltip = _buildBuyButtonTooltip('notEnoughCredits') isMoneyEnough = False if self._disableBuyButton or self.__isHeroTank and self._vehicleCD != self._heroTanks.getCurrentTankCD( ): mayObtain = False isMoneyEnough = False return _ButtonState(enabled=mayObtain, itemPrice=itemPrice, label=buttonLabel, icon=buttonIcon, iconAlign=buttonIconAlign, isAction=isAction, actionTooltip=actionTooltip, tooltip=buyButtonTooltip, title=self.__title, isMoneyEnough=isMoneyEnough, isUnlock=False, isPrevItemsUnlock=True, customOffer=None, isShowSpecial=False) def __getBtnDataCollectibleVehicle(self, vehicle): isVehicleCollectorEnabled = self._lobbyContext.getServerSettings( ).isCollectorVehicleEnabled() isNationUnlocked = vehicle_collector_helper.isAvailableForPurchase( vehicle) resultVO = self.__getBtnDataUnlockedVehicle(vehicle) if isVehicleCollectorEnabled and isNationUnlocked: return resultVO if not isVehicleCollectorEnabled: tooltip = TOOLTIPS_CONSTANTS.VEHICLE_COLLECTOR_DISABLED isSpecialTooltip = True else: key = 'notUnlockedNation' tooltip = makeTooltip( header=TOOLTIPS.vehiclepreview_buybutton_all(key, 'header'), body=_getCollectibleWarningStr( TOOLTIPS.vehiclepreview_buybutton_all(key, 'body'), vehicle)) if resultVO.isMoneyEnough else resultVO.tooltip isSpecialTooltip = False resultVO = resultVO._replace(enabled=False, tooltip=tooltip, isShowSpecial=isSpecialTooltip) return resultVO def __getBtnDataLockedVehicle(self, vehicle): stats = self._itemsCache.items.stats tooltip = '' buttonIcon = None buttonIconAlign = None nodeCD = vehicle.intCD _, isXpEnough = g_techTreeDP.isVehicleAvailableToUnlock( nodeCD, self._vehicleLevel) unlocks = self._itemsCache.items.stats.unlocks isNext2Unlock, unlockProps = g_techTreeDP.isNext2Unlock( nodeCD, unlocked=set(unlocks), xps=stats.vehiclesXPs, freeXP=stats.freeXP, level=self._vehicleLevel) isAvailableToUnlock = isXpEnough and isNext2Unlock if not isAvailableToUnlock: if not isXpEnough: tooltip = _buildBuyButtonTooltip('notEnoughXp') elif any((bool(cd in unlocks) for cd in g_techTreeDP.getTopLevel(nodeCD))): tooltip = _buildBuyButtonTooltip('parentModuleIsLocked') else: tooltip = _buildBuyButtonTooltip('parentVehicleIsLocked') specialData = getHeroTankPreviewParams() if self.__isHeroTank else None if specialData is not None and specialData.buyButtonLabel: buyLabel = backport.text(specialData.buyButtonLabel) else: buyLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.research()) return _ButtonState(enabled=isAvailableToUnlock, itemPrice=getItemUnlockPricesVO(unlockProps), label=buyLabel, icon=buttonIcon, iconAlign=buttonIconAlign, isAction=unlockProps.discount > 0, actionTooltip=None, tooltip=tooltip, title=self.__title, isMoneyEnough=isXpEnough, isUnlock=True, isPrevItemsUnlock=isNext2Unlock, customOffer=None, isShowSpecial=False) @staticmethod def __getBestOfferTooltipData(eventType=None): return VEHICLE_PREVIEW.BUYINGPANEL_OFFER_RENT_FRONTLINE_TOOLTIP_BEST_OFFER if eventType == 'frontline' else None def __getCurrentOfferTitle(self): if self.__offers and self.__currentOffer: if self.__currentOffer.eventType == 'frontline': firstRent = first(self.__currentOffer.rent) if len(self.__offers) > 1 or firstRent and firstRent.get( 'season') is not None: return _ms( backport.text(R.strings.vehicle_preview.buyingPanel. offer.rent.title.frontline.ordinal())) return _ms( backport.text(R.strings.vehicle_preview.buyingPanel.offer. rent.title.frontline.single_cycle()), cycles=self.__currentOffer.name) return self.__title def __getCurrentOfferDescription(self): return { 'header': backport.text(R.strings.vehicle_preview.buyingPanel.offer.rent. frontline.description.header()), 'body': backport.text(R.strings.vehicle_preview.buyingPanel.offer.rent. frontline.description.body.credits()) } if self.__currentOffer and self.__currentOffer.eventType == 'frontline' else None def __startTimer(self, interval): self.__stopTimer() self.__timeCallbackID = BigWorld.callback(interval, self.__onLeftTimeUpdated) def __stopTimer(self): if self.__timeCallbackID is not None: BigWorld.cancelCallback(self.__timeCallbackID) self.__timeCallbackID = None return def __setUsageLeftTime(self, leftTime): self.as_updateLeftTimeS(formattedTime='{} {}'.format( self.__timeLeftIcon, text_styles.tutorial( time_utils.getTillTimeString(leftTime, MENU.VEHICLEPREVIEW_TIMELEFT))), hasHoursAndMinutes=True) def __setShortLeftTime(self, leftTime): self.as_updateLeftTimeS(formattedTime='{} {}'.format( self.__timeLeftIcon, text_styles.tutorial( time_utils.getTillTimeString( leftTime, MENU.VEHICLEPREVIEW_TIMELEFTSHORT))), hasHoursAndMinutes=True) def __setDateLeftTime(self): tm = time_utils.getTimeStructInLocal(self.__endTime) monthName = backport.text( R.strings.menu.dateTime.months.num(tm.tm_mon)()) fmtValues = backport.text(R.strings.menu.dateTime.order(), day=tm.tm_mday, month=monthName, year=tm.tm_year) tooltip = makeTooltip( header=backport.text(R.strings.tooltips.vehiclePreview.shopPack. dateTimeTooltip.header()), body=backport.text(R.strings.tooltips.vehiclePreview.shopPack. dateTimeTooltip.body(), namePack=text_styles.neutral(self.__title), date=fmtValues)) self.as_setSetTitleTooltipS(tooltip) self.as_updateLeftTimeS(formattedTime='') def __timeOver(self): self.__endTime = None self._disableBuyButton = True formattedTime = '{} {}'.format( icons.makeImageTag(RES_ICONS.MAPS_ICONS_LIBRARY_ALERTICON2, vSpace=-2), text_styles.alert(MENU.VEHICLEPREVIEW_ENDTIME)) self.as_updateLeftTimeS(formattedTime=formattedTime) self.__updateBtnState() return def __onLeftTimeUpdated(self): leftTime = self.__endTime - time_utils.getServerUTCTime() self.__timeCallbackID = None if leftTime < 0: self.__timeOver() elif leftTime > time_utils.ONE_DAY: self.__setDateLeftTime() self.__startTimer(leftTime - time_utils.ONE_DAY) else: gmTime = time.gmtime(leftTime) if gmTime.tm_min == 0: self.__setShortLeftTime(leftTime) else: self.__setUsageLeftTime(leftTime) self.__startTimer(gmTime.tm_sec + 1) return @process def __purchasePackage(self): if self.__items is not None: product = self.__title if self.__couponInfo is None else g_currentPreviewVehicle.item.shortUserName price = self.__getPackPrice() if not mayObtainForMoney(price) and mayObtainWithMoneyExchange( price): isOk, _ = yield DialogsInterface.showDialog( ExchangeCreditsWebProductMeta(name=product, count=1, price=price.get( Currency.CREDITS))) if isOk: self.__purchasePackage() return return requestConfirmed = yield self.__buyRequestConfirmation( self.__getConfirmationDialogKey()) if requestConfirmed: if self.__isReferralWindow(): inventoryVehicle = self._itemsCache.items.getItemByCD( g_currentPreviewVehicle.item.intCD) showGetVehiclePage(inventoryVehicle, self.__buyParams) return if mayObtainForMoney(price): showBuyVehicleOverlay(self.__buyParams) elif price.get(Currency.GOLD, 0) > self._itemsCache.items.stats.gold: showBuyGoldForBundle(price.get(Currency.GOLD, 0), self.__buyParams) return def __purchaseOffer(self): rent = self.__currentOffer.rent cycles = [r['cycle'] for r in rent if r.get('cycle')] seasons = [r['season'] for r in rent if r.get('season')] showVehicleRentDialog( g_currentPreviewVehicle.item.intCD, RentType.SEASON_CYCLE_RENT if cycles else RentType.SEASON_RENT, cycles if cycles else seasons, GameSeasonType.EPIC if self.__currentOffer.eventType == 'frontline' else None, self.__currentOffer.buyPrice, self.__currentOffer.buyParams) return def __purchaseSingleVehicle(self, vehicle): event_dispatcher.showVehicleBuyDialog( vehicle, returnAlias=self.__backAlias, returnCallback=self.__backCallback) @process def __purchaseHeroTank(self): if self._heroTanks.isAdventHero(): self.__calendarController.showWindow( invokedFrom=CalendarInvokeOrigin.HANGAR) return shopUrl = self._heroTanks.getCurrentShopUrl() if shopUrl: event_dispatcher.showShop(shopUrl) else: url = yield self.__urlMacros.parse( self._heroTanks.getCurrentRelatedURL()) self.fireEvent( events.OpenLinkEvent(events.OpenLinkEvent.SPECIFIED, url=url)) @async @process def __hasExternalLink(self, callback=None): url = '' if self._marathonEvent: url = yield self._marathonEvent.getMarathonVehicleUrl() elif self.__isHeroTank: if not self._heroTanks.isAdventHero( ) and not self._heroTanks.getCurrentShopUrl(): url = self._heroTanks.getCurrentRelatedURL() callback(self.__linksCtrl.externalAllowed(url) if url else False) @process def __purchaseMarathonPackage(self): if self._marathonEvent.hasIgbLink(): url = yield self._marathonEvent.getMarathonVehicleUrlIgb() event_dispatcher.showShop(url) else: url = yield self._marathonEvent.getMarathonVehicleUrl() self.fireEvent( events.OpenLinkEvent(events.OpenLinkEvent.SPECIFIED, url=url)) def __research(self): if self._actionType == factory.UNLOCK_ITEM: unlockProps = g_techTreeDP.getUnlockProps(self._vehicleCD, self._vehicleLevel) factory.doAction(factory.UNLOCK_ITEM, self._vehicleCD, unlockProps, skipConfirm=self._skipConfirm) else: factory.doAction(factory.BUY_VEHICLE, self._vehicleCD, False, None, VIEW_ALIAS.VEHICLE_PREVIEW, self.__backAlias, self.__backCallback, skipConfirm=self._skipConfirm) return def __walletAvailableForCurrency(self, currency): return self._itemsCache.items.stats.currencyStatuses.get( currency) == WalletController.STATUS.AVAILABLE def __getUnlockedVehicleBtnLabel(self, priceType): specialData = getHeroTankPreviewParams() if self.__isHeroTank else None if specialData is not None and specialData.buyButtonLabel: buttonLabel = backport.text(specialData.buyButtonLabel) elif priceType == ActualPrice.RESTORE_PRICE: buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.restore()) elif priceType == ActualPrice.RENT_PRICE: buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.rent()) elif self.__isHeroTank and self._heroTanks.isAdventHero(): buttonLabel = backport.text(R.strings.vehicle_preview.buyingPanel. buyBtn.label.showAdventCalendar()) else: buttonLabel = backport.text( R.strings.vehicle_preview.buyingPanel.buyBtn.label.buy()) return buttonLabel @staticmethod def __updateEnabledState(collection, enabled): if collection is None: return else: for item in collection: if 'isEnabled' in item: item['isEnabled'] = enabled return
class InternalLinksHandler(IInternalLinksController): browserCtrl = dependency.descriptor(IBrowserController) def __init__(self): super(InternalLinksHandler, self).__init__() self.__urlMacros = None self._browserID = None return def init(self): self.__urlMacros = URLMacros() addListener = g_eventBus.addListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if not handler: LOG_ERROR('Handler is not found', eventType, handlerName) continue if not callable(handler): LOG_ERROR('Handler is invalid', eventType, handlerName, handler) continue addListener(eventType, handler) return def fini(self): if self.__urlMacros is not None: self.__urlMacros.clear() self.__urlMacros = None self._browserID = None removeListener = g_eventBus.removeListener for eventType, handlerName in _LISTENERS.iteritems(): handler = getattr(self, handlerName, None) if handler: removeListener(eventType, handler) super(InternalLinksHandler, self).fini() return @async @process def getURL(self, name, callback): urlSettings = GUI_SETTINGS.lookup(name) if urlSettings: url = yield self.__urlMacros.parse(str(urlSettings)) else: url = yield lambda callback: callback('') callback(url) @process def __openInternalBrowse(self, urlName, title='', browserSize=None, showActionBtn=True, showCloseBtn=False): parsedUrl = yield self.getURL(urlName) if parsedUrl: self._browserID = yield self.browserCtrl.load( parsedUrl, browserID=self._browserID, title=title, browserSize=browserSize, showActionBtn=showActionBtn, showCloseBtn=showCloseBtn)