%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/vacivi36/moodledata/filedir/ea/97/
Upload File :
Create Path :
Current File : /home/vacivi36/moodledata/filedir/ea/97/ea975b2ecb712bdca1d9f74e00ea0c97eba6e0e2

/**
 * Defines the H5P.ArithmeticQuiz.GamePage class
 */
H5P.ArithmeticQuiz.GamePage = (function ($, UI, QuizType) {

  /**
   * Creates a new GamePage instance
   *
   * @class
   * @augments H5P.EventDispatcher
   * @namespace H5P
   * @param  {quizType} quizType
   * @param  {Object} t Object containing all options
   * @param {number} id Unique id to identify this quiz
   * @fires H5P.XAPIEvent
   */
  function GamePage(quizType, options, id) {
    H5P.EventDispatcher.call(this);
    var self = this;
    self.quizType = quizType;
    self.id = id;
    self.translations = options.UI;
    self.arithmeticType = options.arithmeticType;
    self.equationType = options.equationType;
    self.useFractions = options.useFractions;
    self.maxQuestions = options.maxQuestions;
    self.sliding = false;

    self.$gamepage = $('<div>', {
      'class': 'h5p-baq-game counting-down'
    });

    if (self.quizType === H5P.ArithmeticQuiz.QuizType.ARITHMETIC) {
      self.questionsGenerator = new H5P.ArithmeticQuiz.ArithmeticGenerator(self.arithmeticType, self.maxQuestions);
    } else {
      self.questionsGenerator = new H5P.ArithmeticQuiz.EquationsGenerator(self.arithmeticType, self.equationType, self.maxQuestions, self.useFractions);
    }
    self.score = 0;
    self.scoreWidget = new ScoreWidget(self.translations);
    self.scoreWidget.appendTo(self.$gamepage);

    self.timer = new H5P.ArithmeticQuiz.TimerWidget(self.translations);
    self.timer.appendTo(self.$gamepage);

    self.slider = UI.createSlider();

    self.countdownWidget = new H5P.ArithmeticQuiz.CountdownWidget(4, self.translations);
    self.slider.addSlide(self.countdownWidget.create());
    self.countdownWidget.on('ignition', function () {
      self.$gamepage.removeClass('counting-down');
      self.progressbar.setProgress(0);
      self.slider.next();
      self.timer.start();
      self.trigger('started-quiz');
    });

    // Shuffle quizzes:
    self.quizzes = self.questionsGenerator.get();

    var numQuestions = self.quizzes.length;
    for (var i = 0; i < numQuestions; i++) {
      self.slider.addSlide(self.createSlide(self.quizzes[i], i));
    }

    // Create progressbar
    self.progressbar = UI.createProgressbar(numQuestions, {
      progressText: self.translations.slideOfTotal
    });
    self.progressbar.appendTo(self.$gamepage);

    // Add result page:
    self.resultPage = new H5P.ArithmeticQuiz.ResultPage(numQuestions, self.translations);
    self.slider.addSlide(self.resultPage.create());

    self.resultPage.on('retry', function () {
      self.reset();
      self.slider.first();
    });

    self.slider.on('last-slide', function () {
      self.resultPage.update(self.score, self.timer.pause());
      self.$gamepage.addClass('result-page');
      self.trigger('last-slide', {
        score: self.score,
        numQuestions: numQuestions
      });
    });

    self.slider.on('first-slide', function () {
      self.$gamepage.removeClass('result-page');
    });

    self.slider.on('move', function () {
      self.progressbar.next();
    });

    self.slider.on('moved', function () {
      self.sliding = false;
      // Set focus
      var $button = self.$gamepage.find('.current .h5p-joubelui-button')[0];
      if ($button) {
        $button.focus();
      }
    });

    self.slider.attach(self.$gamepage);
  }
  GamePage.prototype = Object.create(H5P.EventDispatcher.prototype);
  GamePage.prototype.constructor = GamePage;

  /**
   * Starts the countdown
   */
  GamePage.prototype.startCountdown = function () {
    this.countdownWidget.start();
  };

  /**
   * Calculate maximum height
   * @method getMaxHeight
   * @return {number}
   */
  GamePage.prototype.getMaxHeight = function () {
    var $slide = $('.question-page', this.$gamepage).first();
    $slide.css({
      display: 'block',
      width: $('.h5p-container').width() + 'px'
    });
    var height = $slide.height();
    $slide.css({
      display: '',
      width: '100%'
    });

    return height;
  };

  /**
   * Resets quiz
   */
  GamePage.prototype.reset = function () {
    this.score = 0;
    this.scoreWidget.update(0);
    this.timer.reset();
    this.$gamepage.find('.reveal-wrong').removeClass('reveal-wrong');
    this.$gamepage.find('.reveal-correct').removeClass('reveal-correct');
    this.$gamepage.find('.h5p-baq-alternatives .h5p-joubelui-button')
      .attr('aria-checked', 'false');
    this.$gamepage.addClass('counting-down');
    this.countdownWidget.restart();
    this.$gamepage.find('.h5p-joubelui-button:first-child, .h5p-joubelui-button:last-child').attr('tabindex', 0);
  };

  GamePage.prototype.makeSignsReadable = function (questionTextual) {
    var self = this;
    questionTextual = String(questionTextual);
    return questionTextual
        .replaceAll('\\+', self.translations.plusOperator)
        .replaceAll('−', self.translations.minusOperator)
        .replaceAll('-', self.translations.minusOperator)
        .replaceAll('×', self.translations.multiplicationOperator)
        .replaceAll('/', ' ' + self.translations.divisionOperator + ' ')
        .replaceAll('÷', self.translations.divisionOperator)
        .replaceAll('=', self.translations.equalitySign);
  };

  /**
   * Creates a question slide
   *
   * @param  {Object} question
   * @param  {string} question.q The question
   * @param  {number} question.correct The correct answer
   * @param  {number} i Index of question
   * @return {H5P.jQuery} The jquery dom element generated
   */
  GamePage.prototype.createSlide = function (question, i) {
    var self = this;
    var readableSigns = undefined;
    var readableQuestion = undefined;
    var readableText = undefined;
    var $slide = $('<div>', {
      'class': 'question-page'
    });

    // Make equations readable, e.g. plus signs are not read by ChromeVox.
    readableSigns = self.makeSignsReadable(question.textual);
    readableQuestion = self.questionsGenerator.readableQuestion(self.translations, readableSigns, question);
    readableText = self.questionsGenerator.readableText(question);

    var questionId = 'arithmetic-quiz-' + self.id + '-question-' + i;

    $('<div>', {
      'class': 'question',
      'text': readableText,
      'aria-label': readableQuestion,
      'id': questionId
    }).appendTo($slide);

    if (question.expression !== undefined) {
      var readableVariable = self.translations.humanizedVariable
          .replace(':item', question.variable);
      $('<div>', {
        'class': 'question',
        'text': question.variable + ' = ?',
        'aria-label': readableVariable,
        'id': questionId
      }).appendTo($slide);
    }

    var $alternatives = $('<ul>', {
      'class': 'h5p-baq-alternatives',
      'role': 'radiogroup',
      'aria-labelledby': questionId
    });

    // Index of the currently focused option.
    var focusedOption;

    /**
     * Handles focusing one of the options, making the rest non-tabbable.
     * @private
     */
    var handleFocus = function () {
      // Go through all alternatives
      for (var i = 0; i < alternatives.length; i++) {
        if (alternatives[i] === this) {
          // Keep track of currently focused option
          focusedOption = i;
          alternatives[i].tabbable();
        }
        else {
          // Remove from tab
          alternatives[i].notTabbable();
        }
      }
    };

    /**
     * Handles moving the focus from the current option to the previous option.
     * @private
     */
    var handlePreviousOption = function () {
      if (focusedOption !== 0) {
        alternatives[focusedOption - 1].focus();
      }
    };

    /**
     * Handles moving the focus from the current option to the next option.
     * @private
     */
    var handleNextOption = function () {
      if (focusedOption !== alternatives.length - 1) {
        alternatives[focusedOption + 1].focus();
      }
    };

    var alternatives = [];
    var readableAlternative = undefined;
    for (var k = 0; k < question.alternatives.length; k++) {
      readableAlternative = self.makeSignsReadable(question.alternatives[k]);
      alternatives.push(new Alternative(question.alternatives[k], readableAlternative, question.alternatives[k]===question.correct, self.translations));
    }

    alternatives.forEach(function (alternative, index) {
      if (index === 0 || index === alternatives.length - 1) {
        alternative.tabbable();
      }
      alternative.on('focus', handleFocus);
      alternative.on('previousOption', handlePreviousOption);
      alternative.on('nextOption', handleNextOption);
      alternative.appendTo($alternatives);
      alternative.on('answered', function () {

        // Ignore clicks if in the middle of something else:
        if (self.sliding) {
          return;
        }
        self.sliding = true;

        self.trigger('alternative-chosen');

        // Can't play it after the transition end is received, since this is not
        // accepted on iPad. Therefore we are playing it here with a delay instead
        H5P.ArithmeticQuiz.SoundEffects.play(alternative.correct ? 'positive-short' : 'negative-short', 300);

        if (alternative.correct) {
          self.score++;
          self.scoreWidget.update(self.score);
        }

        alternatives.forEach(function (alt) {
          if (alt.correct && alternative !== alt) {
            alternative.announce(self.translations.incorrectText.replace(':num', alt.readableResult));
          }
          alt.reveal();
        });

        setTimeout(function(){
          self.slider.next();
        }, 3500);
      });
    });

    $alternatives.appendTo($slide);
    return $slide;
  };


  /**
   * Append game page to container
   *
   * @param  {H5P.jQuery} $container
   */
  GamePage.prototype.appendTo = function ($container) {
    this.$gamepage.appendTo($container);
  };

  String.prototype.replaceAll = function(target, replacement) {
      //var target = this;
      return this.split(target).join(replacement);
      //return target.replace(new RegExp(search, 'g'), replacement);
  };

  /**
   * Creates a ScoreWidget instance
   *
   * @class
   * @private
   * @param  {Object} t Translation object
   */
  function ScoreWidget(t) {
    var self = this;

    var $score = $('<span>', {
      'class': 'h5p-baq-score-widget-number',
      html: 0
    });

    this.$scoreWidget = $('<div>', {
      'class': 'h5p-baq-score-widget',
      'aria-live': 'polite',
      'aria-atomic': true,
      html: t.score + ' '
    }).append($score);

    this.scoreElement = $score.get(0);

    this.appendTo = function ($container) {
      this.$scoreWidget.appendTo($container);

      new Odometer({
        el: this.scoreElement
      });
    };

    this.update = function (score) {
      // Need this aria-busy to make sure readspeaker is not reading
      // both old and new score
      this.$scoreWidget.attr('aria-busy', true);
      this.scoreElement.innerHTML = score;
      // timeout has to be long enough that odometer has time to transition
      setTimeout(function () {
        self.$scoreWidget.attr('aria-busy', false);
      }, 500);
    };
  }


  /**
   * Creates an Alternative button instance
   *
   * @class
   * @private
   * @augments H5P.EventDispatcher
   * @fires H5P.Event
   * @param {number} number Number on button
   * @param {boolean} correct Correct or not
   * @param {Object} t Translations
   */
  function Alternative(number, readableResult, correct, t) {
    H5P.EventDispatcher.call(this);
    var self = this;

    self.number = number;
    self.readableResult = readableResult;
    self.correct = correct;

    var answer = function (event) {
      if (self.correct) {
        self.announce(t.correctText);
      }
      self.$button.attr('aria-checked', 'true');
      self.trigger('answered');
      setTimeout(self.dropLive, 500);
      event.preventDefault();
    };

    // Create radio button and set up event listeners
    this.$button = $('<li>', {
      'class': 'h5p-joubelui-button',
      'role': 'radio',
      'tabindex': -1,
      'text': number,
      'aria-checked': 'false',
      'on': {
        'keydown': function (event) {
          if (self.$button.is('.reveal-correct, .reveal-wrong')) {
            return;
          }
          switch (event.which) {
            case 13: // Enter
            case 32: // Space
              // Answer question
              answer(event);
              break;

            case 37: // Left Arrow
            case 38: // Up Arrow
              // Go to previous Option
              self.trigger('previousOption');
              event.preventDefault();
              break;

            case 39: // Right Arrow
            case 40: // Down Arrow
              // Go to next Option
              self.trigger('nextOption');
              event.preventDefault();
              break;
          }
        },
        'focus': function () {
          if (self.$button.is('.reveal-correct, reveal-wrong')) {
            return;
          }
          self.trigger('focus');
        },
        'click': function (event) {
          if (self.$button.is('.reveal-correct, reveal-wrong')) {
            return;
          }
          // Answer question
          answer(event);
        }
      }
    });

    /**
     * Move focus to this option.
     */
    self.focus = function () {
      self.$button.focus();
    };

    /**
     * Makes it possible to tab your way to this option.
     */
    self.tabbable = function () {
      self.$button.attr('tabindex', 0);
    };

    /**
     * Make sure it's NOT possible to tab your way to this option.
     */
    self.notTabbable = function () {
      self.$button.attr('tabindex', -1);
    };

    this.dropLive = function() {
      if (self.$liveRegion) {
        var node = self.$liveRegion[0];
        if (node.parentNode) {
          node.parentNode.removeChild(node);
        }
      }
    };

    this.announce = function (text) {
      self.$liveRegion = $('<div>', {
        'class': 'h5p-baq-live-feedback',
        'aria-live': 'assertive',
        'width': '1px',
        'height': '1px',
      }).appendTo(document.body.lastChild);

      // Readspeaker needs a small delay after creating the aria live field
      // in order to pick up the change
      setTimeout(function () {
        self.$liveRegion.text(text);
      }, 100);
    };


    this.reveal = function () {
      this.$button.addClass(this.correct ? 'reveal-correct' : 'reveal-wrong')
          .attr('tabindex', -1);
    };

    this.appendTo = function ($container) {
      this.$button.appendTo($container);
      return this;
    };
  }
  Alternative.prototype = Object.create(H5P.EventDispatcher.prototype);
  Alternative.prototype.constructor = Alternative;

  return GamePage;
})(H5P.jQuery, H5P.JoubelUI, H5P.ArithmeticQuiz.QuizType);

Zerion Mini Shell 1.0