Sindbad~EG File Manager

Current Path : /var/www/moodledata/mdata-uautomaq/filedir/8b/a6/
Upload File :
Current File : /var/www/moodledata/mdata-uautomaq/filedir/8b/a6/8ba63ec46391c43bd5a1bd69169c1df205946d23

var H5P = H5P || {};

(function ($, PersonalityQuiz) {
  /**
    A wheel of fortune animation.

    @param {Object} quiz
    @param {Object} personalities
    @param {number} width
    @param {number} height
    @param {PathFunction} _getPath
    @constructor
  */
  PersonalityQuiz.WheelAnimation = function (quiz, personalities, width, height, _getPath) {
    var self = this;

    // TODO (Emil): Some of these variables should probably be private.
    // NOTE (Emil): Choose the smallest if the dimensions vary, for simplicity.
    var side = Math.min(width, height);
    var min = 320;
    var max = 800;
    var hasImages = true;

    self.width = clamp(side, min, max);
    self.height = clamp(side, min, max);

    self.offscreen = document.createElement('canvas');

    self.offscreen.width = Math.max(self.width - 25, 500);
    self.offscreen.height = Math.max(self.height - 25, 500);
    self.offscreen.context = self.offscreen.getContext('2d');

    self.nubArrowSize = self.width * 0.1;
    self.nubRadius = self.width * 0.06;

    self.segmentAngle = (Math.PI * 2) / (personalities.length * 2);
    self.targetRotation = 6 * (Math.PI * 2) + ((3 * Math.PI) / 2) - (self.segmentAngle / 2);
    self.rotation = 0;
    self.rotationSpeed = Math.PI / 32;

    self.center = { x: self.width / 2, y: self.height / 2 };

    self.personalities = personalities;

    self.colors = {
      even: 'rgb(77, 93, 170)',
      odd:  'rgb(56, 183, 85)',
      text: 'rgb(233, 239, 247)',
      nub:  'rgb(233, 239, 247)',
      overlay: 'rgba(60, 62, 64, 0.5)',
      frame: 'rgb(60, 62, 64)'
    };

    self.images = [];

    self.personalities.forEach(function (personality) {
      hasImages = (hasImages && personality.image.file);
    });

    // NOTE (Emil): Prerender the wheel.
    if (hasImages) {
      load();
    }
    else {
      // NOTE (Emil): If there aren't any images we use a slightly different colors.
      self.colors = {
        even: 'rgb(233, 239, 247)',
        odd:  'rgb(203, 209, 217)',
        text: 'rgb(60, 62, 64)',
        nub:  'rgb(77, 93, 170)',
        overlay: 'rgba(60, 62, 64, 0.4)',
        frame: 'rgb(255, 255, 255)'
      };

      drawOffscreen(self.offscreen.context, self.personalities);
    }

    /**
      Clamp a value between low and high

      @param {number} value
      @param {number} low
      @param {number} high
      @return {number}
    */
    function clamp(value, low, high) {
      return Math.min(Math.max(low, value), high);
    }

    /**
      Zero out the current rotation and set the initial targetRotation.
    */
    function reset() {
      self.rotation = 0;
      self.targetRotation = 6 * (Math.PI * 2) + ((3 * Math.PI) / 2) - (self.segmentAngle / 2);
    }

    /**
      Returns the image pattern associated with the personality, if there is one,
      or it returns the background color for the segment.

      @param {Object} personality
      @param {number} index
      @return {Object|string}
    */
    function getPattern(personality, index) {
      if (personality.image.pattern) {
        return personality.image.pattern;
      }

      if (index % 2 === 0) {
        return self.colors.even;
      }
      else {
        return self.colors.odd;
      }
    }

    /**
      Load personality images and when all images are loaded draw the wheel.
    */
    function load() {
      self.loadingImages = [];

      self.personalities.forEach(function (personality) {
        var image = new Image();
        var deferred = $.Deferred();

        image.addEventListener('load', function () {
          personality.image.pattern = self.offscreen.context.createPattern(this, 'no-repeat');
          deferred.resolve();
        });

        image.src = _getPath(personality.image.file.path);
        self.images.push({ name: personality.name, data: image });
        self.loadingImages.push(deferred);
      });

      // NOTE(Emil): When all the images are loaded we can prerender the offscreen buffer.
      $.when.apply(null, self.loadingImages).done(function () {
        drawOffscreen(self.offscreen.context, self.personalities);
      });
    }

    /**
      Draw a single segment of the wheel. There are two segments per personality.

      @param {CanvasRenderingContext2D} context
      @param {Object} center
      @param {number} radius
      @param {number} fromAngle
      @param {number} toAngle
      @param {string|CanvasGradient|CanvasPattern} fillStyle
    */
    function drawSegment(context, center, radius, fromAngle, toAngle, fillStyle) {
      context.beginPath();

      context.fillStyle = fillStyle;

      context.moveTo(center.x, center.y);
      context.arc(center.x, center.y, radius, fromAngle, toAngle, false);
      context.lineTo(center.x, center.y);

      context.fill(); // Fill the segment with the background image.
      context.stroke(); // Draw the outline of the segment.

      context.closePath();
    }

    /**
      Draw the personality name if there is not image associated with the personality.

      @param {CanvasRenderingContext2D} context
      @param {string} text
      @param {number} x
      @param {number} y
      @param {number} maxWidth
    */
    function drawText(context, text, x, y, maxWidth) {
      context.fillStyle = self.colors.text;
      context.font = '24px Arial';

      context.fillText(text, x, y, maxWidth);
    }

    /**
      Draw the prerendered wheel, which is stored in the offscreen canvas.

      @param {CanvasRenderingContext2D} context
      @param {number} rotation
      @param {HTMLElement} canvas
    */
    function drawWheel(context, rotation, canvas) {
      var scale = 1;

      context.save();

      scale = {
        x: self.width / self.offscreen.width,
        y: self.width / self.offscreen.height
      };

      context.translate(self.center.x, self.center.y);
      context.rotate(rotation);
      context.scale(scale.x, scale.y);
      context.translate(-self.offscreen.width / 2, -self.offscreen.height / 2);

      context.drawImage(canvas, 0, 0);

      context.restore();
    }

    /**
      Draw the center arrow which will point to the result personality.

      @param {CanvasRenderingContext2D} context
      @param {Object} center
      @param {number} radius
      @param {string} color
    */
    function drawNub(context, center, radius, color) {
      context.fillStyle = color;

      context.beginPath();

      context.moveTo(self.center.x - radius, self.center.y);
      context.lineTo(self.center.x, self.center.y - self.nubArrowSize);
      context.lineTo(self.center.x + radius, self.center.y);
      context.arc(self.center.x, self.center.y, radius, 0, Math.PI * 2, false);

      context.fill();

      context.closePath();
    }

    /**
      Draw the wheel in the offscreen canvas and save it for later.

      @param {CanvasRenderingContext2D} context
      @param {Object[]} personalities - a list of personalities from H5P.PersonalityQuiz
    */
    function drawOffscreen(context, personalities) {
      var center = { x: self.offscreen.width / 2, y: self.offscreen.height / 2 };
      var radius = self.offscreen.width / 2 - 2;

      // NOTE (Emil): We draw two segments for each personality,
      // this way the number of segments is always even.
      var length = personalities.length * 2;
      var angle = (Math.PI * 2) / length;
      var halfAngle = angle / 2;

      var i, personality, pattern, open, offset;

      context.textBaseline = 'middle';
      context.strokeStyle = self.colors.frame;

      for (i = 0; i < length; i++) {
        personality = personalities[i % personalities.length];
        pattern = getPattern(personality, i);

        open = i * angle;
        offset = { x: 0, y: 0 };

        if (personality.image.file) {
          offset.x = personality.image.file.width / 2;
          offset.y = (personality.image.file.height - radius) / 2;
        }

        // NOTE (Emil): Assumes that the center of the image is the most interesting.
        context.save();

        // NOTE (Emil): Center the circle segment over the center of the background image.
        context.translate(center.x, center.y);
        context.rotate(open + halfAngle - (Math.PI / 2));
        context.translate(-offset.x, -offset.y);

        drawSegment(
          context,
          {x: offset.x, y: offset.y},
          radius,
          (Math.PI / 2) - halfAngle,
          (Math.PI / 2) + halfAngle,
          pattern
        );

        context.restore();

        // NOTE (Emil): Draw the personality name if there are no images.
        if (self.images.length < self.personalities.length) {
          context.save();

          context.translate(center.x, center.y);
          context.rotate(open + halfAngle);
          context.translate(-center.x, -center.y);

          drawText(
            context,
            personality.name,
            center.x + (self.nubRadius * 2),
            center.y,
            radius - (self.nubRadius * 2.5)
          );

          context.restore();
        }
      }
    }

    /**
        Attach the wheel animation to the provided canvas element.

        @param {HTMLElement} canvasElement
    */
    self.attach = function (canvasElement) {
      self.onscreen = canvasElement;
      self.onscreen.width = self.width;
      self.onscreen.height = self.height;
      self.onscreen.context = self.onscreen.getContext('2d');
    };

    /**
        Set the target personality and calculates the target rotation.

        @param {Object} targetPersonality
    */
    self.setTarget = function (targetPersonality) {
      var deviation, round;

      reset();

      deviation = self.segmentAngle * 0.4;

      // NOTE (Emil): Randomly choose one of the two segments associated
      // with the personality.
      round = Math.floor(Math.random() + 0.5);

      self.personalities.forEach(function (personality, index) {
        if (targetPersonality.name === personality.name) {
          var angle = index * self.segmentAngle + (round * Math.PI);
          var min = angle + deviation;
          var max = angle - deviation;
          var deviated = Math.random() * (max - min) + min;

          self.targetRotation = self.targetRotation - deviated;

          return;
        }
      });
    };

    /**
      Draw the wheel of fortune

      @param {CanvasRenderingContext2D} context
      @param {number} rotation
      @param {HTMLElement} canvas
    */
    self.draw = function (context, rotation, canvas) {
      context.clearRect(0, 0, self.onscreen.width, self.onscreen.height);

      drawWheel(context, rotation, canvas);
      drawNub(context, self.center, self.nubRadius, self.colors.nub);
    };

    /**
      The main animation loop. Starts the callback loop to requestAnimationFrame.
      A call to 'setTarget' is required before calling this function.
    */
    self.animate = function () {
      var end, start;
      self.rotation = 0;

      function _animate (timestamp) {
        var dt, scale, rotation;

        end = end ? end : timestamp;
        start = timestamp;

        dt = (start - end) / 1000;
        scale = 1 - (self.rotation / self.targetRotation);
        rotation = Math.max(scale * dt * self.rotationSpeed, 0.01);

        if (self.rotation < self.targetRotation) {
          // NOTE (Emil): Always move atleast a little until the targetRotation is achieved.
          self.rotation += Math.min(rotation, self.targetRotation - self.rotation);

          self.draw(self.onscreen.context, self.rotation, self.offscreen);

          window.requestAnimationFrame(_animate);
        }
        else {
          quiz.trigger('wheel-animation-end');
        }
      }

      window.requestAnimationFrame(_animate);
    };
  };
})(H5P.jQuery, H5P.PersonalityQuiz);

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists