%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /opt/bitnami/apps/moodle/moodledata/filedir/40/be/
Upload File :
Create Path :
Current File : /opt/bitnami/apps/moodle/moodledata/filedir/40/be/40be75a9ac1c43624aee194a738d8f11feb7da2d

H5P = H5P || {};

H5P.BranchingScenario = function (params, contentId) {
  const self = this;

  H5P.EventDispatcher.call(self);
  self.contentId = contentId;
  self.startScreen = {};
  self.libraryScreen = {};
  self.endScreens = {};
  self.navigating;
  self.currentHeight;
  self.currentId = -1;
  self.xAPIDataCollector = [];

  /**
   * Extend an array just like JQuery's extend.
   * @param {...Object} arguments - Objects to be merged.
   * @return {Object} Merged objects.
   */
  const extend = function () {
    for (var i = 1; i < arguments.length; i++) {
      for (var key in arguments[i]) {
        if (arguments[i].hasOwnProperty(key)) {
          if (typeof arguments[0][key] === 'object' &&
          typeof arguments[i][key] === 'object') {
            extend(arguments[0][key], arguments[i][key]);
          }
          else {
            arguments[0][key] = arguments[i][key];
          }
        }
      }
    }
    return arguments[0];
  };

  params = extend({
    content: [],
    startScreen: {
      startScreenTitle: "",
      startScreenSubtitle: ""
    },
    endScreens: [
      {
        endScreenTitle: "",
        endScreenSubtitle: "",
        contentId: -1
      }
    ],
    scoringOption: 'no-score',
    l10n: {}
  }, params.branchingScenario); // Account for the wrapper!

  // Set default localization
  params.l10n = extend({
    startScreenButtonText: "Start the course",
    endScreenButtonText: "Restart the course",
    proceedButtonText: "Proceed",
    scoreText: "Your score:"
  }, params.l10n);

  // Sanitize the (next)ContentIds that the editor didn't set
  params.content.forEach((item, index) => {
    item.contentId = index;
    if (item.nextContentId === undefined) {
      item.nextContentId = -1;
    }
  });

  self.params = params;
  self.scoring = new H5P.BranchingScenario.Scoring(params);

  /**
   * Create a start screen object
   *
   * @param  {Object} startscreendata Object containing data needed to build a start screen
   * @param  {string} startscreendata.startScreenTitle Title
   * @param  {string} startscreendata.startScreenSubtitle Subtitle
   * @param  {Object} startscreendata.startScreenImage Object containing image metadata
   * @param  {boolean} isCurrentScreen When Branching Scenario is first initialized
   * @return {H5P.BranchingScenario.GenericScreen} Generic Screen object
   */
  const createStartScreen = function ({startScreenTitle, startScreenSubtitle, startScreenImage}, isCurrentScreen) {
    const startScreen = new H5P.BranchingScenario.GenericScreen(self, {
      isStartScreen: true,
      titleText: startScreenTitle,
      subtitleText: startScreenSubtitle,
      image: startScreenImage,
      buttonText: params.l10n.startScreenButtonText,
      isCurrentScreen
    });

    startScreen.on('toggleFullScreen', () => {
      self.toggleFullScreen();
    });

    return startScreen;
  };

  /**
   * Create an end screen object
   *
   * @param  {Object} endScreenData Object containing data needed to build an end screen
   * @param  {string} endScreenData.endScreenTitle Title
   * @param  {string} endScreenData.endScreenSubtitle Subtitle
   * @param  {Object} endScreenData.endScreenImage Object containing image metadata
   * @param  {Object} endScreenData.endScreenScore Score
   * @param  {Object} endScreenData.showScore Determines if score is shown
   * @return {H5P.BranchingScenario.GenericScreen} Generic Screen object
   */
  const createEndScreen = function (endScreenData) {
    const endScreen = new H5P.BranchingScenario.GenericScreen(self, {
      isStartScreen: false,
      titleText: endScreenData.endScreenTitle,
      subtitleText: endScreenData.endScreenSubtitle,
      image: endScreenData.endScreenImage,
      buttonText: params.l10n.endScreenButtonText,
      isCurrentScreen: false,
      scoreText: params.l10n.scoreText,
      score: self.scoring.getScore(endScreenData.endScreenScore),
      maxScore: self.scoring.getMaxScore(),
      showScore: self.scoring.shouldShowScore(),
    });

    endScreen.on('toggleFullScreen', () => {
      self.toggleFullScreen();
    });

    return endScreen;
  };

  /**
   * Get library data by id from branching scenario parameters
   *
   * @param  {number} id Id of the content type
   * @return {Object | boolean} Data required to create a library
   */
  self.getLibrary = function (id) {
    return (params.content[id] !== undefined ? params.content[id] : false);
  };

  /**
   * Handle the start of the branching scenario
   */
  self.on('started', function () {
    const startNode = this.params.content[0];
    if (startNode && startNode.type && startNode.type.library && startNode.type.library.split(' ')[0] === 'H5P.BranchingQuestion') {
      // First node is Branching Question, no sliding, just trigger BQ overlay
      self.trigger('navigated', {
        nextContentId: 0
      });
    }
    else {
      // First node is info content
      self.startScreen.hide();
      self.libraryScreen.show();
      self.triggerXAPI('progressed');
    }
    self.currentId = 0;
  });

  /**
   * Handle progression
   */
  self.on('navigated', function (e) {
    const id = parseInt(e.data.nextContentId);
    const nextLibrary = self.getLibrary(id);
    let resizeScreen = true;

    if (!self.libraryScreen) {
      self.libraryScreen = new H5P.BranchingScenario.LibraryScreen(
        self,
        params.startScreen.startScreenTitle,
        nextLibrary
      );

      self.libraryScreen.on('toggleFullScreen', () => {
        self.toggleFullScreen();
      });

      self.$container.append(self.libraryScreen.getElement());
      self.currentId = id;
    }
    else {
      // Try to collect xAPIData for last screen
      const xAPIData = self.libraryScreen.getXAPIData(self.currentId);
      if (xAPIData) {
        self.xAPIDataCollector.push(xAPIData);
      }
    }


    // Re-display library screen if it has been hidden by an ending screen
    if (self.currentEndScreen && self.currentEndScreen.isShowing) {
      if (nextLibrary) {
        if (!H5P.BranchingScenario.LibraryScreen.isBranching(nextLibrary)) {
          self.currentEndScreen.hide();
          self.currentEndScreen = null;
          self.libraryScreen.show();
        }
      }
      else {
        // Showing two end screens after each other
        self.libraryScreen.hideFeedbackDialogs();
        self.currentEndScreen.hide();
        self.currentEndScreen = null;
      }
    }
    else if (self.startScreen && self.startScreen.isShowing && nextLibrary) {
      if (!H5P.BranchingScenario.LibraryScreen.isBranching(nextLibrary)) {
        self.startScreen.hide();
        self.libraryScreen.show();
        resizeScreen = false;
      }
    }
    else {
      // Remove any feedback dialogs
      self.libraryScreen.hideFeedbackDialogs();
    }

    if (resizeScreen) {
      self.trigger('resize');
    }
    if (self.currentId !== -1) {
      self.triggerXAPI('progressed');
      self.scoring.addLibraryScore(
        this.currentId,
        this.libraryScreen.currentLibraryId,
        e.data.chosenAlternative
      );
    }

    if (nextLibrary === false) {
      //  Show the relevant end screen if there is no next library
      self.currentEndScreen = self.endScreens[id];
      // Custom end screen
      if (e.data.feedback) {
        const endScreen = createEndScreen({
          endScreenTitle: e.data.feedback.title || '',
          endScreenSubtitle: e.data.feedback.subtitle || '',
          endScreenImage: e.data.feedback.image,
          endScreenScore: e.data.feedback.endScreenScore
        });
        self.$container.append(endScreen.getElement());
        self.currentEndScreen = endScreen;
      }
      else if (self.scoring.isDynamicScoring()) {
        self.currentEndScreen.setScore(self.getScore());
      }

      self.startScreen.hide();
      self.libraryScreen.hide(true);
      self.currentEndScreen.show();

      self.triggerXAPICompleted(self.scoring.getScore(self.currentEndScreen.getScore()), self.scoring.getMaxScore());
    }
    else {
      self.libraryScreen.showNextLibrary(nextLibrary);
      self.currentId = id;
    }

    // First node was BQ, so sliding from start screen to library screen is needed now
    if (e.data.nextContentId !== 0 && document.querySelector('.h5p-start-screen').classList.contains('h5p-current-screen')) {
      // Remove translation of info content which would tamper with timing of sliding
      const wrapper = self.libraryScreen.wrapper.querySelector('.h5p-slide-in');
      if (wrapper) {
        wrapper.classList.remove('h5p-next');
        self.startScreen.hide();
        self.libraryScreen.show();
      }
    }
  });

  /**
   * Handle restarting
   */
  self.on('restarted', function () {
    if (self.currentEndScreen) {
      self.currentEndScreen.hide();
      self.currentEndScreen = null;
    }
    self.scoring.restart();
    self.xAPIDataCollector = [];
    self.startScreen.screenWrapper.classList.remove('h5p-slide-out');
    self.startScreen.show();
    self.currentId = -1;

    // Reset the library screen
    if (self.libraryScreen) {
      self.libraryScreen.remove();
    }
    // Note: the first library must always have an id of 0
    self.libraryScreen = new H5P.BranchingScenario.LibraryScreen(self, params.startScreen.startScreenTitle, self.getLibrary(0));

    self.libraryScreen.on('toggleFullScreen', () => {
      self.toggleFullScreen();
    });

    self.$container.append(self.libraryScreen.getElement());
  });

  /**
   * Handle resizing, resizes child library
   */
  self.on('resize', function (event) {
    if (self.bubblingUpwards) {
      return; // Prevent sending the event back down
    }
    if (
      self.libraryScreen
      && typeof self.libraryScreen === 'object'
      && Object.keys(self.libraryScreen).length !== 0
    ) {
      self.libraryScreen.resize(event);
    }
    self.changeLayoutToFitWidth();

    // Add classname for phone size adjustments
    const rect = self.$container[0].getBoundingClientRect();
    if (rect.width <= 480) {
      self.$container.addClass('h5p-phone-size');
    }
    else {
      self.$container.removeClass('h5p-phone-size');
    }
    if (rect.width < 768) {
      self.$container.addClass('h5p-medium-tablet-size');
    }
    else {
      self.$container.removeClass('h5p-medium-tablet-size');
    }
  });

  /**
   * Toggle full screen
   */
  self.toggleFullScreen = function () {
    if (self.isFullScreen()) {
      // Exit fullscreen
      if (H5P.exitFullScreen) {
        H5P.exitFullScreen();
      }
    }
    else {
      H5P.fullScreen(self.$container, this);
    }

  };

  /**
   * Returns true if we're in full screen or semi full screen.
   *
   * @returns {boolean}
   */
  self.isFullScreen = function () {
    return H5P.isFullscreen
      || (self.$container
        && self.$container[0].classList.contains('h5p-fullscreen'))
      ||(self.$container
        && self.$container[0].classList.contains('h5p-semi-fullscreen'));
  };

  /**
   * Get accumulative score for all attempted scenarios
   *
   * @returns {number} Current score for Brnaching Scenario
   */
  self.getScore = function () {
    return self.scoring.getScore();
  };

  /**
   * Get max score
   *
   * @returns {number} Max score for branching scenario
   */
  self.getMaxScore = function () {
    return self.scoring.getMaxScore();
  };

  /**
   * Change the width of the branching question depending on the container changeLayoutToFitWidth
   * @return {undefined} undefined
   */
  self.changeLayoutToFitWidth = function () {
    const fontSize = parseInt(window.getComputedStyle(document.getElementsByTagName('body')[0]).fontSize, 10);
    // Wide screen
    if (this.$container.width() / fontSize > 43) {
      self.$container[0].classList.add('h5p-wide-screen');
    }
    else {
      self.$container[0].classList.add('h5p-mobile-screen');
    }
  };

  /**
   * Attach Branching Scenario to the H5P container
   *
   * @param  {HTMLElement} $container Container for the content type
   * @return {undefined} undefined
   */
  self.attach = function ($container) {
    if (this.isRoot !== undefined && this.isRoot()) {
      this.setActivityStarted();
    }

    self.$container = $container;
    $container.addClass('h5p-branching-scenario').html('');

    if (!params.content || params.content.length === 0) {
      const contentMessage = document.createElement('div');
      contentMessage.innerHTML = 'No content';
      self.$container.append(contentMessage);
      return;
    }

    self.startScreen = createStartScreen(params.startScreen, true);
    self.$container.append(self.startScreen.getElement());
    self.currentId = -1;

    // Note: the first library must always have an id of 0
    self.libraryScreen = new H5P.BranchingScenario.LibraryScreen(self, params.startScreen.startScreenTitle, self.getLibrary(0));
    self.libraryScreen.on('toggleFullScreen', () => {
      self.toggleFullScreen();
    });
    self.$container.append(self.libraryScreen.getElement());

    params.endScreens.forEach(endScreen => {
      self.endScreens[endScreen.contentId] = createEndScreen(endScreen);
      self.$container.append(self.endScreens[endScreen.contentId].getElement());
    });
  };

  /**
   * Get xAPI data.
   * Contract used by report rendering engine.
   *
   * @see contract at {@link https://h5p.org/documentation/developers/contracts#guides-header-6}
   */
  self.getXAPIData = function () {
    if (!self.currentEndScreen) {
      console.error('Called getXAPIData before finished.')
      return;
    }

    const xAPIEvent = self.createXAPIEventTemplate('answered');

    // Extend definition
    const definition = xAPIEvent.getVerifiedStatementValue(['object', 'definition']);
    H5P.jQuery.extend(definition, {
      interactionType: 'compound',
      type: 'http://adlnet.gov/expapi/activities/cmi.interaction'
    });
    definition.extensions = {
      'https://h5p.org/x-api/no-question-score': 1
    };

    const score = self.scoring.getScore(self.currentEndScreen.getScore());
    const maxScore = self.scoring.getMaxScore();
    xAPIEvent.setScoredResult(score, maxScore, this, true, score === maxScore);

    return {
      statement: xAPIEvent.data.statement,
      children: self.xAPIDataCollector
    };
  };
};

H5P.BranchingScenario.prototype = Object.create(H5P.EventDispatcher.prototype);
H5P.BranchingScenario.prototype.constructor = H5P.BranchingScenario;

Zerion Mini Shell 1.0