Пример #1
0
 def goToLobby(self):
     databaseID = account_helpers.getAccountDatabaseID()
     raise databaseID or AssertionError('Acoount database ID is not defined')
     isFirstStart = databaseID not in self.__loggedDBIDs
     self.__loggedDBIDs.add(databaseID)
     state = {'isFirstStart': isFirstStart,
      'isAfterBattle': self.__afterBattle}
     self.__setDispatcher(_LOBBY_DISPATCHER)
     self.__restoreID = _SETTINGS.QUESTS.id
     self.__doAutoRun((_SETTINGS.OFFBATTLE, _SETTINGS.QUESTS), state)
     self.__hintsManager = HintsManager()
     self.__hintsManager.start()
Пример #2
0
 def goToLobby(self):
     databaseID = account_helpers.getAccountDatabaseID()
     if not databaseID:
         raise SoftException('Acoount database ID is not defined')
     isFirstStart = databaseID not in self.__loggedDBIDs
     self.__loggedDBIDs.add(databaseID)
     state = {'isFirstStart': isFirstStart,
      'isAfterBattle': self.__afterBattle}
     self.__setDispatcher(_LOBBY_DISPATCHER)
     self.__restoreID = _SETTINGS.QUESTS.id
     bootcampController = dependency.instance(IBootcampController)
     isInBootcampAccount = bootcampController.isInBootcampAccount()
     if isInBootcampAccount:
         selectedSettings = self.__doAutoRun((_SETTINGS.OFFBATTLE, _SETTINGS.QUESTS, _SETTINGS.BOOTCAMP_LOBBY), state)
     else:
         selectedSettings = None
     if selectedSettings is None or selectedSettings.hintsEnabled:
         self.__hintsManager = HintsManager()
         self.__hintsManager.start()
     return
Пример #3
0
 def goToLobby(self):
     databaseID = account_helpers.getAccountDatabaseID()
     raise databaseID or AssertionError('Acoount database ID is not defined')
     isFirstStart = databaseID not in self.__loggedDBIDs
     self.__loggedDBIDs.add(databaseID)
     state = {'isFirstStart': isFirstStart,
      'isAfterBattle': self.__afterBattle}
     self.__setDispatcher(_LOBBY_DISPATCHER)
     self.__restoreID = _SETTINGS.QUESTS.id
     self.__doAutoRun((_SETTINGS.OFFBATTLE, _SETTINGS.QUESTS), state)
     self.__hintsManager = HintsManager()
     self.__hintsManager.start()
Пример #4
0
 def __pe_onGuiCacheSyncCompleted(self, ctx):
     if 'databaseID' in ctx:
         databaseID = ctx['databaseID']
         isFirstStart = databaseID not in self.__loggedDBIDs
         self.__loggedDBIDs.add(databaseID)
     else:
         isFirstStart = False
     cache = _cache.TutorialCache(BigWorld.player().name)
     cache.read()
     runCtx = RunCtx(cache, isFirstStart=isFirstStart, isAfterBattle=self.__afterBattle, **ctx)
     self.__setDispatcher(_LOBBY_DISPATCHER)
     self.__restoreID = _SETTINGS.QUESTS.id
     self.__doAutoRun((_SETTINGS.OFFBATTLE, _SETTINGS.QUESTS), runCtx)
     self.__hintsManager = HintsManager()
     self.__hintsManager.start()
Пример #5
0
class TutorialLoader(object):

    def __init__(self):
        super(TutorialLoader, self).__init__()
        self.__loggedDBIDs = set()
        self.__afterBattle = False
        self.__tutorial = None
        self.__dispatcher = None
        self.__restoreID = None
        self.__settings = _settings.createSettingsCollection()
        self.__hintsManager = None
        return

    def init(self):
        g_playerEvents.onGuiCacheSyncCompleted += self.__pe_onGuiCacheSyncCompleted
        g_playerEvents.onAvatarBecomePlayer += self.__pe_onAvatarBecomePlayer
        connectionManager.onDisconnected += self.__cm_onDisconnected

    def fini(self):
        g_playerEvents.onGuiCacheSyncCompleted -= self.__pe_onGuiCacheSyncCompleted
        g_playerEvents.onAvatarBecomePlayer -= self.__pe_onAvatarBecomePlayer
        connectionManager.onDisconnected -= self.__cm_onDisconnected
        if self.__hintsManager is not None:
            self.__hintsManager.stop()
        if self.__tutorial is not None:
            self.__dispatcher.stop()
            self.__tutorial.onStopped -= self.__onTutorialStopped
            self.__tutorial.stop()
        self.__loggedDBIDs.clear()
        self.__settings.clear()
        return

    def clear(self):
        if self.__tutorial is not None:
            self.__tutorial.onStopped -= self.__onTutorialStopped
        self.__tutorial = None
        return

    @property
    def tutorial(self):
        return self.__tutorial

    @property
    def tutorialID(self):
        result = 0
        if self.__tutorial is not None:
            result = not self.__tutorial.getID()
        return result

    @property
    def isRunning(self):
        result = False
        if self.__tutorial is not None:
            result = not self.__tutorial.isStopped()
        return result

    def isTutorialStopped(self):
        result = True
        if self.__tutorial is not None:
            result = self.__tutorial.isStopped()
        return result

    def run(self, settingsID, state = None):
        """
        Try to run tutorial.
        
        :param settingsID: string containing settings ID of required tutorial.
        :param state: dict(
                        reloadIfRun : bool - just reload tutorial if it's running,
                        afterBattle : bool - tutorial should load scenario that is played
                                when player left battle,
                        initialChapter : str - name of initial chapter,
                        restoreIfRun: bool - current tutorial will be started again
                                if required tutorial stop.
                        globalFlags : dict(GLOBAL_FLAG.* : bool,)
                )
        :return: True if tutorial has started, otherwise - False.
        """
        settings = self.__settings.getSettings(settingsID)
        if settings is None:
            LOG_ERROR('Can not find settings', settingsID)
            return False
        else:
            if state is None:
                state = {}
            reloadIfRun = state.pop('reloadIfRun', False)
            restoreIfRun = state.pop('restoreIfRun', False)
            isStopForced = state.pop('isStopForced', False)
            if self.__tutorial is not None and not self.__tutorial.isStopped():
                isCurrent = self.__tutorial.getID() == settings.id
                if reloadIfRun and isCurrent:
                    if isStopForced:
                        self.__doStop()
                    else:
                        GlobalStorage.setFlags(state.get('globalFlags', {}))
                        self.__tutorial.invalidateFlags()
                        return True
                elif restoreIfRun and not isCurrent:
                    self.__restoreID = self.__tutorial.getID()
                    self.__doStop()
                else:
                    LOG_ERROR('Tutorial already is running', self.__tutorial.getID())
                    return False
            if self.__dispatcher is None:
                self.__setDispatcher(settings.dispatcher)
            cache = _cache.TutorialCache(BigWorld.player().name)
            cache.read()
            state.setdefault('isAfterBattle', self.__afterBattle)
            state.setdefault('restart', True)
            result = self.__doRun(settings, RunCtx(cache, **state), byRequest=True)
            if not result:
                self.__restoreID = None
            return result

    def areSettingsEnabled(self, settingsID):
        settings = self.__settings.getSettings(settingsID)
        if settings is None:
            LOG_ERROR('Can not find settings', settingsID)
            return False
        else:
            return _settings.createTutorialElement(settings.reqs).isEnabled()

    def stop(self, restore = True):
        self.__doStop(reason=_STOP_REASON.PLAYER_ACTION)
        self.__doStopHints()
        if restore:
            self.__doRestore()
        else:
            self.__restoreID = None
        return

    def refuse(self):
        if self.__tutorial is not None:
            self.__tutorial.refuse()
        return

    def __doAutoRun(self, seq, runCtx):
        for settings in seq:
            if self.__doRun(settings, runCtx):
                return

    def __doRun(self, settings, runCtx, byRequest = False):
        if not settings.enabled:
            return False
        else:
            reqs = _settings.createTutorialElement(settings.reqs)
            if not reqs.isEnabled():
                return False
            descriptor = loadDescriptorData(settings, settings.exParsers)
            if descriptor is None:
                LOG_ERROR('Descriptor is not valid. Tutorial is not available', settings)
                return False
            runCtx.cache.setSpace(settings.space)
            if byRequest:
                runCtx.cache.setRefused(False)
            reqs.prepare(runCtx)
            if not reqs.process(descriptor, runCtx):
                return False
            self.clear()
            tutorial = Tutorial(settings, descriptor)
            result = tutorial.run(weakref.proxy(self.__dispatcher), runCtx)
            if result:
                self.__tutorial = tutorial
                self.__tutorial.onStopped += self.__onTutorialStopped
            return result

    def __doStop(self, reason = _STOP_REASON.DEFAULT):
        if self.__tutorial is not None:
            self.__tutorial.onStopped -= self.__onTutorialStopped
            self.__tutorial.stop(reason=reason)
            self.__tutorial = None
        return

    def __doStopHints(self):
        if self.__hintsManager is not None:
            self.__hintsManager.stop()
        return

    def __doClear(self, reason = _STOP_REASON.DEFAULT):
        self.__restoreID = None
        self.__doStop(reason=reason)
        self.__doStopHints()
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
            self.__dispatcher = None
        return

    def __doRestore(self):
        if self.__restoreID is not None:
            settingsID, self.__restoreID = self.__restoreID, None
            LOG_DEBUG('Restore tutorial', settingsID)
            self.run(settingsID)
        return

    def __setDispatcher(self, settings):
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
            self.__dispatcher = None
        self.__dispatcher = _settings.createTutorialElement(settings)
        self.__dispatcher.start(weakref.proxy(self))
        return

    def __pe_onGuiCacheSyncCompleted(self, ctx):
        if 'databaseID' in ctx:
            databaseID = ctx['databaseID']
            isFirstStart = databaseID not in self.__loggedDBIDs
            self.__loggedDBIDs.add(databaseID)
        else:
            isFirstStart = False
        cache = _cache.TutorialCache(BigWorld.player().name)
        cache.read()
        runCtx = RunCtx(cache, isFirstStart=isFirstStart, isAfterBattle=self.__afterBattle, **ctx)
        self.__setDispatcher(_LOBBY_DISPATCHER)
        self.__restoreID = _SETTINGS.QUESTS.id
        self.__doAutoRun((_SETTINGS.OFFBATTLE, _SETTINGS.QUESTS), runCtx)
        self.__hintsManager = HintsManager()
        self.__hintsManager.start()

    def __pe_onAvatarBecomePlayer(self):
        self.__afterBattle = True
        self.__doClear()

    def __cm_onDisconnected(self):
        self.__afterBattle = False
        self.__doClear(reason=_STOP_REASON.DISCONNECT)

    def __onTutorialStopped(self):
        self.__doRestore()
Пример #6
0
class TutorialLoader(object):

    def __init__(self):
        super(TutorialLoader, self).__init__()
        self.__loggedDBIDs = set()
        self.__afterBattle = False
        self.__tutorial = None
        self.__dispatcher = None
        self.__restoreID = None
        self.__settings = _settings.createSettingsCollection()
        self.__hintsManager = None
        self.__listener = None
        return

    def init(self):
        """
        Initialization of tutorial loader.
        """
        self.__listener = AppLoaderListener()
        self.__listener.start(weakref.proxy(self))

    def fini(self):
        """
        Tutorial loader finalizes work: stops training process, saving state,
        # if tutorial is running.
        """
        if self.__listener is not None:
            self.__listener.stop()
        if self.__hintsManager is not None:
            self.__hintsManager.stop()
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
        if self.__tutorial is not None:
            self.__tutorial.onStopped -= self.__onTutorialStopped
            self.__tutorial.stop()
        self.__loggedDBIDs.clear()
        self.__settings.clear()
        return

    def clear(self):
        if self.__tutorial is not None:
            self.__tutorial.onStopped -= self.__onTutorialStopped
        self.__tutorial = None
        return

    @property
    def tutorial(self):
        return self.__tutorial

    @property
    def tutorialID(self):
        result = ''
        if self.__tutorial is not None:
            result = self.__tutorial.getID()
        return result

    @property
    def isRunning(self):
        result = False
        if self.__tutorial is not None:
            result = not self.__tutorial.isStopped()
        return result

    def isTutorialStopped(self):
        result = True
        if self.__tutorial is not None:
            result = self.__tutorial.isStopped()
        return result

    def run(self, settingsID, state = None):
        """
        Try to run tutorial.
        
        :param settingsID: string containing settings ID of required tutorial.
        :param state: dict(
                reloadIfRun : bool - just reload tutorial if it's running,
                afterBattle : bool - tutorial should load scenario that is played
                    when player left battle,
                initialChapter : str - name of initial chapter,
                restoreIfRun: bool - current tutorial will be started again
                    if required tutorial stop.
                globalFlags : dict(GLOBAL_FLAG.* : bool,)
            )
        :return: True if tutorial has started, otherwise - False.
        """
        settings = self.__settings.getSettings(settingsID)
        if settings is None:
            LOG_ERROR('Can not find settings', settingsID)
            return False
        else:
            if state is None:
                state = {}
            reloadIfRun = state.pop('reloadIfRun', False)
            restoreIfRun = state.pop('restoreIfRun', False)
            isStopForced = state.pop('isStopForced', False)
            if self.__tutorial is not None and not self.__tutorial.isStopped():
                isCurrent = self.__tutorial.getID() == settings.id
                if reloadIfRun and isCurrent:
                    if isStopForced:
                        self.__doStop()
                    else:
                        GlobalStorage.setFlags(state.get('globalFlags', {}))
                        self.__tutorial.invalidateFlags()
                        return True
                elif restoreIfRun and not isCurrent:
                    self.__restoreID = self.__tutorial.getID()
                    self.__doStop()
                else:
                    LOG_ERROR('Tutorial already is running', self.__tutorial.getID())
                    return False
            state.setdefault('isAfterBattle', self.__afterBattle)
            state.setdefault('restart', True)
            state['byRequest'] = True
            result = self.__doRun(settings, state)
            if not result:
                self.__restoreID = None
            return result

    def stop(self, restore = True):
        self.__doStop()
        self.__doStopHints()
        if restore:
            self.__doRestore()
        else:
            self.__restoreID = None
        return

    def refuse(self):
        if self.__tutorial is not None:
            self.__tutorial.refuse()
        return

    def goToLobby(self):
        databaseID = account_helpers.getAccountDatabaseID()
        raise databaseID or AssertionError('Acoount database ID is not defined')
        isFirstStart = databaseID not in self.__loggedDBIDs
        self.__loggedDBIDs.add(databaseID)
        state = {'isFirstStart': isFirstStart,
         'isAfterBattle': self.__afterBattle}
        self.__setDispatcher(_LOBBY_DISPATCHER)
        self.__restoreID = _SETTINGS.QUESTS.id
        self.__doAutoRun((_SETTINGS.OFFBATTLE, _SETTINGS.QUESTS), state)
        self.__hintsManager = HintsManager()
        self.__hintsManager.start()

    def leaveLobby(self):
        self.stop(restore=False)

    def goToBattleLoading(self):
        self.__afterBattle = True
        self.__doClear()
        self.__doAutoRun((_SETTINGS.BATTLE_V2, _SETTINGS.BATTLE_QUESTS), {'canResolveChapterOnStart': False})

    def goToBattle(self):
        if self.__tutorial is not None:
            self.__tutorial.startBattle()
        return

    def leaveBattle(self):
        self.stop(restore=False)

    def goToLogin(self):
        self.__afterBattle = False
        self.__doClear()

    def __doAutoRun(self, seq, state):
        for settings in seq:
            if self.__doRun(settings, state):
                return

    def __doRun(self, settings, state):
        if not settings.enabled:
            return False
        else:
            reqs = _settings.createTutorialElement(settings.reqs)
            if not reqs.isEnabled():
                return False
            descriptor = loadDescriptorData(settings, settings.exParsers)
            if descriptor is None:
                LOG_ERROR('Descriptor is not valid. Tutorial is not available', settings)
                return False
            cache = _cache.TutorialCache(BigWorld.player().name)
            cache.read()
            cache.setSpace(settings.space)
            if state.get('byRequest', False):
                cache.setRefused(False)
            runCtx = RunCtx(cache, **state)
            reqs.prepare(runCtx)
            if not reqs.process(descriptor, runCtx):
                return False
            self.clear()
            if self.__dispatcher is None:
                self.__setDispatcher(settings.dispatcher)
            tutorial = Tutorial(settings, descriptor)
            result = tutorial.run(weakref.proxy(self.__dispatcher), runCtx)
            if result:
                self.__tutorial = tutorial
                self.__tutorial.onStopped += self.__onTutorialStopped
            return result

    def __doStop(self):
        if self.__tutorial is not None:
            self.__tutorial.onStopped -= self.__onTutorialStopped
            self.__tutorial.stop()
            self.__tutorial = None
        return

    def __doStopHints(self):
        if self.__hintsManager is not None:
            self.__hintsManager.stop()
        return

    def __doClear(self):
        self.__restoreID = None
        self.__doStop()
        self.__doStopHints()
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
            self.__dispatcher = None
        return

    def __doRestore(self):
        if self.__restoreID is not None:
            settingsID, self.__restoreID = self.__restoreID, None
            LOG_DEBUG('Restore tutorial', settingsID)
            self.run(settingsID)
        return

    def __setDispatcher(self, settings):
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
            self.__dispatcher = None
        self.__dispatcher = _settings.createTutorialElement(settings)
        self.__dispatcher.start(weakref.proxy(self))
        return

    def __onTutorialStopped(self):
        """
        Listener for event Tutorial.onStopped.
        """
        self.__doRestore()
Пример #7
0
class TutorialLoader(object):

    def __init__(self):
        super(TutorialLoader, self).__init__()
        self.__loggedDBIDs = set()
        self.__afterBattle = False
        self.__tutorial = None
        self.__dispatcher = None
        self.__restoreID = None
        self.__settings = _settings.createSettingsCollection()
        self.__hintsManager = None
        self.__listener = None
        return

    def init(self):
        """
        Initialization of tutorial loader.
        """
        self.__listener = AppLoaderListener()
        self.__listener.start(weakref.proxy(self))

    def fini(self):
        """
        Tutorial loader finalizes work: stops training process, saving state,
        # if tutorial is running.
        """
        if self.__listener is not None:
            self.__listener.stop()
        if self.__hintsManager is not None:
            self.__hintsManager.stop()
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
        if self.__tutorial is not None:
            self.__tutorial.onStopped -= self.__onTutorialStopped
            self.__tutorial.stop()
        self.__loggedDBIDs.clear()
        self.__settings.clear()
        return

    def clear(self):
        if self.__tutorial is not None:
            self.__tutorial.onStopped -= self.__onTutorialStopped
        self.__tutorial = None
        return

    @property
    def tutorial(self):
        return self.__tutorial

    @property
    def tutorialID(self):
        result = ''
        if self.__tutorial is not None:
            result = self.__tutorial.getID()
        return result

    @property
    def isRunning(self):
        result = False
        if self.__tutorial is not None:
            result = not self.__tutorial.isStopped()
        return result

    def isTutorialStopped(self):
        result = True
        if self.__tutorial is not None:
            result = self.__tutorial.isStopped()
        return result

    def run(self, settingsID, state = None):
        """
        Try to run tutorial.
        
        :param settingsID: string containing settings ID of required tutorial.
        :param state: dict(
                reloadIfRun : bool - just reload tutorial if it's running,
                afterBattle : bool - tutorial should load scenario that is played
                    when player left battle,
                initialChapter : str - name of initial chapter,
                restoreIfRun: bool - current tutorial will be started again
                    if required tutorial stop.
                globalFlags : dict(GLOBAL_FLAG.* : bool,)
            )
        :return: True if tutorial has started, otherwise - False.
        """
        settings = self.__settings.getSettings(settingsID)
        if settings is None:
            LOG_ERROR('Can not find settings', settingsID)
            return False
        else:
            if state is None:
                state = {}
            reloadIfRun = state.pop('reloadIfRun', False)
            restoreIfRun = state.pop('restoreIfRun', False)
            isStopForced = state.pop('isStopForced', False)
            if self.__tutorial is not None and not self.__tutorial.isStopped():
                isCurrent = self.__tutorial.getID() == settings.id
                if reloadIfRun and isCurrent:
                    if isStopForced:
                        self.__doStop()
                    else:
                        GlobalStorage.setFlags(state.get('globalFlags', {}))
                        self.__tutorial.invalidateFlags()
                        return True
                elif restoreIfRun and not isCurrent:
                    self.__restoreID = self.__tutorial.getID()
                    self.__doStop()
                else:
                    LOG_ERROR('Tutorial already is running', self.__tutorial.getID())
                    return False
            state.setdefault('isAfterBattle', self.__afterBattle)
            state.setdefault('restart', True)
            state['byRequest'] = True
            result = self.__doRun(settings, state)
            if not result:
                self.__restoreID = None
            return result

    def stop(self, restore = True):
        self.__doStop()
        self.__doStopHints()
        if restore:
            self.__doRestore()
        else:
            self.__restoreID = None
        return

    def refuse(self):
        if self.__tutorial is not None:
            self.__tutorial.refuse()
        return

    def goToLobby(self):
        databaseID = account_helpers.getAccountDatabaseID()
        raise databaseID or AssertionError('Acoount database ID is not defined')
        isFirstStart = databaseID not in self.__loggedDBIDs
        self.__loggedDBIDs.add(databaseID)
        state = {'isFirstStart': isFirstStart,
         'isAfterBattle': self.__afterBattle}
        self.__setDispatcher(_LOBBY_DISPATCHER)
        self.__restoreID = _SETTINGS.QUESTS.id
        self.__doAutoRun((_SETTINGS.OFFBATTLE, _SETTINGS.QUESTS), state)
        self.__hintsManager = HintsManager()
        self.__hintsManager.start()

    def leaveLobby(self):
        self.stop(restore=False)

    def goToBattle(self):
        self.__afterBattle = True
        self.__doClear()
        self.__doAutoRun((_SETTINGS.BATTLE, _SETTINGS.BATTLE_QUESTS), {})

    def leaveBattle(self):
        self.stop(restore=False)

    def goToLogin(self):
        self.__afterBattle = False
        self.__doClear()

    def __doAutoRun(self, seq, state):
        for settings in seq:
            if self.__doRun(settings, state):
                return

    def __doRun(self, settings, state):
        if not settings.enabled:
            return False
        else:
            reqs = _settings.createTutorialElement(settings.reqs)
            if not reqs.isEnabled():
                return False
            descriptor = loadDescriptorData(settings, settings.exParsers)
            if descriptor is None:
                LOG_ERROR('Descriptor is not valid. Tutorial is not available', settings)
                return False
            cache = _cache.TutorialCache(BigWorld.player().name)
            cache.read()
            cache.setSpace(settings.space)
            if state.get('byRequest', False):
                cache.setRefused(False)
            runCtx = RunCtx(cache, **state)
            reqs.prepare(runCtx)
            if not reqs.process(descriptor, runCtx):
                return False
            self.clear()
            if self.__dispatcher is None:
                self.__setDispatcher(settings.dispatcher)
            tutorial = Tutorial(settings, descriptor)
            result = tutorial.run(weakref.proxy(self.__dispatcher), runCtx)
            if result:
                self.__tutorial = tutorial
                self.__tutorial.onStopped += self.__onTutorialStopped
            return result

    def __doStop(self):
        if self.__tutorial is not None:
            self.__tutorial.onStopped -= self.__onTutorialStopped
            self.__tutorial.stop()
            self.__tutorial = None
        return

    def __doStopHints(self):
        if self.__hintsManager is not None:
            self.__hintsManager.stop()
        return

    def __doClear(self):
        self.__restoreID = None
        self.__doStop()
        self.__doStopHints()
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
            self.__dispatcher = None
        return

    def __doRestore(self):
        if self.__restoreID is not None:
            settingsID, self.__restoreID = self.__restoreID, None
            LOG_DEBUG('Restore tutorial', settingsID)
            self.run(settingsID)
        return

    def __setDispatcher(self, settings):
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
            self.__dispatcher = None
        self.__dispatcher = _settings.createTutorialElement(settings)
        self.__dispatcher.start(weakref.proxy(self))
        return

    def __onTutorialStopped(self):
        """
        Listener for event Tutorial.onStopped.
        """
        self.__doRestore()
Пример #8
0
class TutorialLoader(object):

    def __init__(self):
        super(TutorialLoader, self).__init__()
        self.__loggedDBIDs = set()
        self.__afterBattle = False
        self.__tutorial = None
        self.__dispatcher = None
        self.__restoreID = None
        self.__settings = _settings.createSettingsCollection()
        self.__hintsManager = None
        self.__listener = None
        return

    def init(self):
        self.__listener = AppLoaderListener()
        self.__listener.start(weakref.proxy(self))

    def fini(self):
        if self.__listener is not None:
            self.__listener.stop()
        if self.__hintsManager is not None:
            self.__hintsManager.stop()
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
        if self.__tutorial is not None:
            self.__tutorial.onStopped -= self.__onTutorialStopped
            self.__tutorial.stop()
        self.__loggedDBIDs.clear()
        self.__settings.clear()
        return

    @property
    def tutorial(self):
        return self.__tutorial

    @property
    def tutorialID(self):
        result = ''
        if self.__tutorial is not None:
            result = self.__tutorial.getID()
        return result

    @property
    def isRunning(self):
        result = False
        if self.__tutorial is not None:
            result = not self.__tutorial.isStopped()
        return result

    def isTutorialStopped(self):
        result = True
        if self.__tutorial is not None:
            result = self.__tutorial.isStopped()
        return result

    def run(self, settingsID, state=None):
        settings = self.__settings.getSettings(settingsID)
        if settings is None:
            _logger.error('Can not find settings: %r', settingsID)
            return False
        else:
            if state is None:
                state = {}
            reloadIfRun = state.pop('reloadIfRun', False)
            restoreIfRun = state.pop('restoreIfRun', False)
            isStopForced = state.pop('isStopForced', False)
            if self.__tutorial is not None and not self.__tutorial.isStopped():
                isCurrent = self.__tutorial.getID() == settings.id
                if reloadIfRun and isCurrent:
                    if isStopForced:
                        self.__doStop()
                    else:
                        GlobalStorage.setFlags(state.get('globalFlags', {}))
                        _logger.debug('invalidateFlags from TutorialLoader.run')
                        self.__tutorial.invalidateFlags()
                        return True
                elif restoreIfRun and not isCurrent:
                    self.__restoreID = self.__tutorial.getID()
                    self.__doStop()
                else:
                    _logger.error('Tutorial already is running: %r', self.__tutorial.getID())
                    return False
            state.setdefault('isAfterBattle', self.__afterBattle)
            state.setdefault('restart', True)
            state['byRequest'] = True
            result = self.__doRun(settings, state)
            if not result:
                self.__restoreID = None
            return result

    def stop(self, restore=True):
        self.__doStop()
        self.__doStopHints()
        if restore:
            self.__doRestore()
        else:
            self.__restoreID = None
        return

    def refuse(self):
        if self.__tutorial is not None:
            self.__tutorial.refuse()
        return

    def goToLobby(self):
        databaseID = account_helpers.getAccountDatabaseID()
        if not databaseID:
            raise SoftException('Acoount database ID is not defined')
        isFirstStart = databaseID not in self.__loggedDBIDs
        self.__loggedDBIDs.add(databaseID)
        state = {'isFirstStart': isFirstStart,
         'isAfterBattle': self.__afterBattle}
        self.__setDispatcher(_LOBBY_DISPATCHER)
        self.__restoreID = _SETTINGS.QUESTS.id
        bootcampController = dependency.instance(IBootcampController)
        isInBootcampAccount = bootcampController.isInBootcampAccount()
        if isInBootcampAccount:
            selectedSettings = self.__doAutoRun((_SETTINGS.OFFBATTLE, _SETTINGS.QUESTS, _SETTINGS.BOOTCAMP_LOBBY), state)
        else:
            selectedSettings = None
        if selectedSettings is None or selectedSettings.hintsEnabled:
            self.__hintsManager = HintsManager()
            self.__hintsManager.start()
        return

    def leaveLobby(self):
        self.stop(restore=False)

    def goToBattleLoading(self):
        self.__afterBattle = True
        self.__doClear()
        self.__doAutoRun((_SETTINGS.BATTLE_V2, _SETTINGS.BATTLE_QUESTS), {'canResolveChapterOnStart': False})

    def goToBattle(self):
        if self.__tutorial is not None:
            self.__tutorial.startBattle()
        return

    def leaveBattle(self):
        self.stop(restore=False)

    def goToLogin(self):
        self.__afterBattle = False
        self.__doClear()

    def __doAutoRun(self, seq, state):
        for settings in seq:
            if self.__doRun(settings, state):
                return settings

        return None

    def __doRun(self, settings, state):
        if not settings.enabled:
            return False
        else:
            reqs = _settings.createTutorialElement(settings.reqs)
            if not reqs.isEnabled():
                return False
            descriptor = loadDescriptorData(settings, settings.exParsers)
            if descriptor is None:
                _logger.error('Descriptor is not valid. Tutorial is not available: %r', settings)
                return False
            cache = _cache.TutorialCache(BigWorld.player().name)
            cache.read()
            cache.setSpace(settings.space, ioEnabled=settings.cacheEnabled)
            if state.get('byRequest', False):
                cache.setRefused(False)
            runCtx = RunCtx(cache, **state)
            reqs.prepare(runCtx)
            if not reqs.process(descriptor, runCtx):
                return False
            self.__doStop()
            if self.__dispatcher is None:
                self.__setDispatcher(settings.dispatcher)
            self.__tutorial = core.Tutorial(settings, descriptor)
            self.__tutorial.onStopped += self.__onTutorialStopped
            result = self.__tutorial.run(weakref.proxy(self.__dispatcher), runCtx)
            if not result:
                self.__tutorial.onStopped -= self.__onTutorialStopped
                self.__tutorial = None
            return result

    def __doStop(self):
        if self.__tutorial is not None:
            self.__tutorial.onStopped -= self.__onTutorialStopped
            self.__tutorial.stop()
            self.__tutorial = None
        return

    def __doStopHints(self):
        if self.__hintsManager is not None:
            self.__hintsManager.stop()
            self.__hintsManager = None
        return

    def __doClear(self):
        self.__restoreID = None
        self.__doStop()
        self.__doStopHints()
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
            self.__dispatcher = None
        return

    def __doRestore(self):
        if self.__restoreID is not None:
            settingsID, self.__restoreID = self.__restoreID, None
            _logger.debug('Restore tutorial: %r', settingsID)
            self.run(settingsID)
        return

    def __setDispatcher(self, settings):
        if self.__dispatcher is not None:
            self.__dispatcher.stop()
            self.__dispatcher = None
        self.__dispatcher = _settings.createTutorialElement(settings)
        self.__dispatcher.start(weakref.proxy(self))
        return

    def __onTutorialStopped(self):
        self.__doRestore()