<commit_before>var React = require('react');
var ReactDOM = require('react-dom');

module.exports = {
  createClass: function(chartType, methodNames, dataKey) {
    var classData = {
      displayName: chartType + 'Chart',
      getInitialState: function() { return {}; },
      render: function() {
        var _props = {
          ref: 'canvass'
        };
        for (var name in this.props) {
          if (this.props.hasOwnProperty(name)) {
            if (name !== 'data' && name !== 'options') {
              _props[name] = this.props[name];
            }
          }
        }
        return React.createElement('canvas', _props);
      }
    };

    var extras = ['clear', 'stop', 'resize', 'toBase64Image', 'generateLegend', 'update', 'addData', 'removeData'];
    function extra(type) {
      classData[type] = function() {
        return this.state.chart[type].apply(this.state.chart, arguments);
      };
    }

    classData.componentDidMount = function() {
      this.initializeChart(this.props);
    };

    classData.componentWillUnmount = function() {
      var chart = this.state.chart;
      chart.destroy();
    };

    classData.componentWillReceiveProps = function(nextProps) {
      var chart = this.state.chart;
      if (nextProps.redraw) {
        chart.destroy();
        this.initializeChart(nextProps);
      } else {
        dataKey = dataKey || dataKeys[chart.name];
        updatePoints(nextProps, chart, dataKey);
        if (chart.scale) {
          chart.scale.xLabels = nextProps.data.labels;

            if (chart.scale.calculateXLabelRotation){
          chart.scale.calculateXLabelRotation();
            }
        }
        chart.update();
      }
    };

    classData.initializeChart = function(nextProps) {
      var Chart = require('chart.js');
      var el = ReactDOM.findDOMNode(this);
      var ctx = el.getContext("2d");
      var chart = new Chart(ctx)[chartType](nextProps.data, nextProps.options || {});
      this.state.chart = chart;
    };

    // return the chartjs instance
    classData.getChart = function() {
      return this.state.chart;
    };

    // return the canvass element that contains the chart
    classData.getCanvass = function() {
      return this.refs.canvass;
    };

    classData.getCanvas = classData.getCanvass;

    var i;
    for (i=0; i<extras.length; i++) {
      extra(extras[i]);
    }
    for (i=0; i<methodNames.length; i++) {
      extra(methodNames[i]);
    }

    return React.createClass(classData);
  }
};

var dataKeys = {
  'Line': 'points',
  'Radar': 'points',
  'Bar': 'bars'
};

var updatePoints = function(nextProps, chart, dataKey) {
  var name = chart.name;

  if (name === 'PolarArea' || name === 'Pie' || name === 'Doughnut') {
    nextProps.data.forEach(function(segment, segmentIndex) {
      if (!chart.segments[segmentIndex]) {
        chart.addData(segment);
      } else {
        Object.keys(segment).forEach(function (key) {
          chart.segments[segmentIndex][key] = segment[key];
        });
      }
    });

    while(nextProps.data.length < chart.segments.length) {
      chart.removeData();
    }
  } else if (name === "Radar") {
      chart.removeData();
      nextProps.data.datasets.forEach(function(set, setIndex) {
      set.data.forEach(function(val, pointIndex) {
        if (typeof(chart.datasets[setIndex][dataKey][pointIndex]) == "undefined") {
          addData(nextProps, chart, setIndex, pointIndex);
        } else {
          chart.datasets[setIndex][dataKey][pointIndex].value = val;
        }
      });
    });
  } else {
    while (chart.scale.xLabels.length > nextProps.data.labels.length) {
      chart.removeData();
    }
    nextProps.data.datasets.forEach(function(set, setIndex) {
      set.data.forEach(function(val, pointIndex) {
        if (typeof(chart.datasets[setIndex][dataKey][pointIndex]) == "undefined") {
          addData(nextProps, chart, setIndex, pointIndex);
        } else {
          chart.datasets[setIndex][dataKey][pointIndex].value = val;
        }
      });
    });
  }
};

var addData = function(nextProps, chart, setIndex, pointIndex) {
  var values = [];
  nextProps.data.datasets.forEach(function(set) {
    values.push(set.data[pointIndex]);
  });
  chart.addData(values, nextProps.data.labels[setIndex]);
};
<commit_msg>Fix: unknown prop 'redraw' warning in React v15.2<commit_after>var React = require('react');
var ReactDOM = require('react-dom');

module.exports = {
  createClass: function(chartType, methodNames, dataKey) {
    var excludedProps = ['data', 'options', 'redraw'];
    var classData = {
      displayName: chartType + 'Chart',
      getInitialState: function() { return {}; },
      render: function() {
        var _props = {
          ref: 'canvass'
        };
        for (var name in this.props) {
          if (this.props.hasOwnProperty(name)) {
            if (excludedProps.indexOf(name) === -1) {
              _props[name] = this.props[name];
            }
          }
        }
        return React.createElement('canvas', _props);
      }
    };

    var extras = ['clear', 'stop', 'resize', 'toBase64Image', 'generateLegend', 'update', 'addData', 'removeData'];
    function extra(type) {
      classData[type] = function() {
        return this.state.chart[type].apply(this.state.chart, arguments);
      };
    }

    classData.componentDidMount = function() {
      this.initializeChart(this.props);
    };

    classData.componentWillUnmount = function() {
      var chart = this.state.chart;
      chart.destroy();
    };

    classData.componentWillReceiveProps = function(nextProps) {
      var chart = this.state.chart;
      if (nextProps.redraw) {
        chart.destroy();
        this.initializeChart(nextProps);
      } else {
        dataKey = dataKey || dataKeys[chart.name];
        updatePoints(nextProps, chart, dataKey);
        if (chart.scale) {
          chart.scale.xLabels = nextProps.data.labels;

            if (chart.scale.calculateXLabelRotation){
          chart.scale.calculateXLabelRotation();
            }
        }
        chart.update();
      }
    };

    classData.initializeChart = function(nextProps) {
      var Chart = require('chart.js');
      var el = ReactDOM.findDOMNode(this);
      var ctx = el.getContext("2d");
      var chart = new Chart(ctx)[chartType](nextProps.data, nextProps.options || {});
      this.state.chart = chart;
    };

    // return the chartjs instance
    classData.getChart = function() {
      return this.state.chart;
    };

    // return the canvass element that contains the chart
    classData.getCanvass = function() {
      return this.refs.canvass;
    };

    classData.getCanvas = classData.getCanvass;

    var i;
    for (i=0; i<extras.length; i++) {
      extra(extras[i]);
    }
    for (i=0; i<methodNames.length; i++) {
      extra(methodNames[i]);
    }

    return React.createClass(classData);
  }
};

var dataKeys = {
  'Line': 'points',
  'Radar': 'points',
  'Bar': 'bars'
};

var updatePoints = function(nextProps, chart, dataKey) {
  var name = chart.name;

  if (name === 'PolarArea' || name === 'Pie' || name === 'Doughnut') {
    nextProps.data.forEach(function(segment, segmentIndex) {
      if (!chart.segments[segmentIndex]) {
        chart.addData(segment);
      } else {
        Object.keys(segment).forEach(function (key) {
          chart.segments[segmentIndex][key] = segment[key];
        });
      }
    });

    while(nextProps.data.length < chart.segments.length) {
      chart.removeData();
    }
  } else if (name === "Radar") {
      chart.removeData();
      nextProps.data.datasets.forEach(function(set, setIndex) {
      set.data.forEach(function(val, pointIndex) {
        if (typeof(chart.datasets[setIndex][dataKey][pointIndex]) == "undefined") {
          addData(nextProps, chart, setIndex, pointIndex);
        } else {
          chart.datasets[setIndex][dataKey][pointIndex].value = val;
        }
      });
    });
  } else {
    while (chart.scale.xLabels.length > nextProps.data.labels.length) {
      chart.removeData();
    }
    nextProps.data.datasets.forEach(function(set, setIndex) {
      set.data.forEach(function(val, pointIndex) {
        if (typeof(chart.datasets[setIndex][dataKey][pointIndex]) == "undefined") {
          addData(nextProps, chart, setIndex, pointIndex);
        } else {
          chart.datasets[setIndex][dataKey][pointIndex].value = val;
        }
      });
    });
  }
};

var addData = function(nextProps, chart, setIndex, pointIndex) {
  var values = [];
  nextProps.data.datasets.forEach(function(set) {
    values.push(set.data[pointIndex]);
  });
  chart.addData(values, nextProps.data.labels[setIndex]);
};
<|endoftext|>


<commit_before>// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.services','starter.controller'])

.run(function($ionicPlatform, $rootScope, $cordovaPushV5) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      cordova.plugins.Keyboard.disableScroll(true);

    }
    if (window.StatusBar) {
      // org.apache.cordova.statusbar required
      StatusBar.styleLightContent();
    }

    //notifiction option
    var options = {
      "android": {"senderID": "819680755320"},
      "ios": {},
      "windows": {}
    };

    //notification init
    $cordovaPushV5.initialize(options)
    console.log('device ready')
  });
})
.config(function ($stateProvider, $urlRouterProvider) {

    // Ionic uses AngularUI Router which uses the concept of states
    // Learn more here: https://github.com/angular-ui/ui-router
    // Set up the various states which the app can be in.
    // Each state's controller can be found in controllers.js
    $stateProvider
      .state('home', {
        url: "/home",
        templateUrl: "templates/home.html",
        controller: 'HomeCtrl'
      });

    // if none of the above states are matched, use this as the fallback
    $urlRouterProvider.otherwise('/home');

  });
<commit_msg>Injected ngCordova module<commit_after>// Ionic Starter App

// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'ngCordova', 'starter.services','starter.controller'])

.run(function($ionicPlatform, $rootScope, $cordovaPushV5) {
  $ionicPlatform.ready(function() {
    // Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
    // for form inputs)
    if (window.cordova && window.cordova.plugins && window.cordova.plugins.Keyboard) {
      cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
      cordova.plugins.Keyboard.disableScroll(true);

    }
    if (window.StatusBar) {
      // org.apache.cordova.statusbar required
      StatusBar.styleLightContent();
    }

    //notifiction option
    var options = {
      "android": {"senderID": "819680755320"},
      "ios": {},
      "windows": {}
    };

    //notification init
    $cordovaPushV5.initialize(options)
    console.log('device ready')
  });
})
.config(function ($stateProvider, $urlRouterProvider) {

    // Ionic uses AngularUI Router which uses the concept of states
    // Learn more here: https://github.com/angular-ui/ui-router
    // Set up the various states which the app can be in.
    // Each state's controller can be found in controllers.js
    $stateProvider
      .state('home', {
        url: "/home",
        templateUrl: "templates/home.html",
        controller: 'HomeCtrl'
      });

    // if none of the above states are matched, use this as the fallback
    $urlRouterProvider.otherwise('/home');

  });
<|endoftext|>


<commit_before>var $w;
var $h;
var $slides;
var $currentChapter;
var $currentSlideshow;
var $rails;
var $previous;
var $next;
var $play;
var $video;
var $waypoints;
var index = -1;
var currentSlide;
var currentPanel;

var setSlideHeight = function() {
    $w = $(window).width();
    $h = $(window).height();
    $slides.css('height', $h);
    $slides.css('width', $w);

    // also resize the video

    jwplayer('player').resize($w, $h);
};

var setUpPanelSnap = function() {
    var options = {
        $menu: $('footer .menu'),
        directionThreshold: 50,
        slideSpeed: 200,
        panelSelector: 'section',
        onSnapFinish: setSlideshow,
        keyboardNavigation: {
            enabled: true,
            nextPanelKey: 40,
            previousPanelKey: 38,
            wrapAround: false
        }
    };

    $('#content').panelSnap(options);
};

var setSlideshow = function() {
    // set up slideshow

    index = -1;
    $currentChapter = $('.chapter.active');
    $currentSlideshow = $currentChapter.find('.slide');

    // reset slideshow if returning to chapter

    currentSlide = $currentSlideshow[0];
    $currentChapter.find('.slide.present').removeClass('present');
    $currentChapter.addClass('present');

    // append slide controls if necessary
    if ($currentSlideshow.length > 0) {
        $currentChapter.append(JST.slide_nav());
        loadSlides($currentSlideshow);
        $rails = $('.rail');
        $previous = $('.previous-slide');
        $next = $('.next-slide');
        $previous.css('display', 'none');

        $previous.on('click', previousSlide);
        $next.on('click', nextSlide);
    }
    setChapterHash();

    // check for playing video
    if (jwplayer('player').getState() == 'PLAYING') {
        jwplayer('player').stop();
    }
};

var loadSlides = function(slideshow) {
    _.each(slideshow, function(slide) {
        if ($(slide).data('bgimage')) {
            var backgroundImage = 'assets/img/' + $(slide).data('bgimage');
            $(slide).css('background-image', 'url(' + backgroundImage + ')');
        }
    });
};

var setChapterHash = function() {
    currentPanel = $currentChapter.data('panel');
    hasher.setHash(currentPanel);
};

var setSlideHash = function() {
    if (index >= 0) {
        hasher.setHash(currentPanel + '/' + index);
    }
    else {
        hasher.setHash(currentPanel);
    }
};

var previousSlide = function() {
    if (index >= 0) {
        index--;
        $(currentSlide).removeClass('present');
        currentSlide = $currentSlideshow[index];
        $(currentSlide).addClass('present');
        setSlideHash();
        checkArrows();
    }
};

var nextSlide = function() {
    if (index < $currentSlideshow.length) {
        index++;
        $(currentSlide).removeClass('present');
        currentSlide = $currentSlideshow[index];
        $(currentSlide).addClass('present');
        setSlideHash();
        checkArrows();
    }
};

var checkArrows = function() {
    if (index < 0) {
        $previous.css('display', 'none');
    }
    else if (index === $currentSlideshow.length - 1) {
        $next.css('display', 'none');
    }
    else {
        $previous.css('display', 'block');
        $next.css('display', 'block');
    }
};

var handleKeyPress = function(e) {
    if (e.keyCode === 37 && index >= 0) {
        previousSlide();
    }
    else if (e.keyCode === 39 && index < $currentSlideshow.length - 1) {
        nextSlide();
    }
};

var setUpVideo = function() {
    var text = $(this).parents('.text');
    $(text).hide();
    $(text).parent().css('background-image', '');
    $(text).next().css('display', 'table-cell');
    var player = text.siblings('#player');
    initPlayer(player);
};

var initPlayer = function(player) {
    jwplayer('player').setup({
        modes: [{
            type: 'flash',
            src: 'http://www.npr.org/templates/javascript/jwplayer/player.swf',
            config: {
                skin: 'http://media.npr.org/templates/javascript/jwplayer/skins/mle/npr-video-archive/npr-video-archive.zip',
                file: 'http://pd.npr.org/npr-mp4/npr/nprvid/2013/02/20130219_nprvid_oscars-n-600000.mp4',
                image: 'http://apps.npr.org/oscars-2013/img/cheat-sheet-promo_wide.jpg',
                'hd.file': 'http://pd.npr.org/npr-mp4/npr/nprvid/2013/02/20130219_nprvid_oscars-n-1200000.mp4'
            }
        }, {
            type: 'html5',
            config: {
                levels: [
                    {
                        file: 'http://pd.npr.org/npr-mp4/npr/nprvid/2013/02/20130219_nprvid_oscars-n-600000.mp4',
                        image: 'http://apps.npr.org/oscars-2013/img/cheat-sheet-promo_wide.jpg'
                    }
                ]
            }
        }],
        bufferlength: '5',
        controlbar: 'over',
        icons: 'true',
        autostart: false,
        width: $w,
        height: $h
    });
    jwplayer('player').play();

};

//handle hash changes
var handleChanges = function(newHash, oldHash){
    // $.smoothScroll({ speed: 800, scrollTarget: '#' + newHash });
};

$(document).ready(function() {
    $slides = $('.slide');
    $currentChapter = $('.chapter.active');
    $currentSlideshow = $currentChapter.find('.slide');
    $play = $('.btn-play');
    $video = $('.video');
    currentSlide = $currentSlideshow[index];
    currentPanel = $currentChapter.data('panel');

    setSlideHeight();
    setUpPanelSnap();

    hasher.changed.add(handleChanges); //add hash change listener
    hasher.initialized.add(handleChanges); //add initialized listener (to grab initial value in case it is already set)
    hasher.init(); //initialize hasher (start listening for history changes)

    $(document).keydown(handleKeyPress);
    $play.on('click', setUpVideo);

    $slides.lazyload({
        threshold : 50,
    });

    $(window).resize(setSlideHeight);
});<commit_msg>just some friday documentation<commit_after>/*
* Global vars
*/

var $w;
var $h;
var $slides;
var $currentChapter;
var $currentSlideshow;
var $rails;
var $previous;
var $next;
var $play;
var $video;
var $waypoints;
var index = -1;
var currentSlide;
var currentPanel;

var setSlideHeight = function() {

    /*
    * Set the window width and height, make all slides fill the screen.
    */

    $w = $(window).width();
    $h = $(window).height();
    $slides.css('height', $h);
    $slides.css('width', $w);

    // also resize the video

    jwplayer('player').resize($w, $h);
};

var setUpPanelSnap = function() {

    /*
    * See jquery.panelsnap.js for the code this is using. Listens for section tags.
    */

    var options = {
        $menu: $('footer .menu'),
        directionThreshold: 50,
        slideSpeed: 200,
        panelSelector: 'section',
        onSnapFinish: setSlideshow,
        keyboardNavigation: {
            enabled: true,
            nextPanelKey: 40,
            previousPanelKey: 38,
            wrapAround: false
        }
    };

    $('#content').panelSnap(options);
};

var setSlideshow = function() {
    /*
    * If chapters have slideshows, do some legwork to make them work properly
    */

    // set up slideshow

    index = -1; // -1 because of the titlecard. This is awful.

    $currentChapter = $('.chapter.active');
    $currentSlideshow = $currentChapter.find('.slide'); // find all slides within the section

    // reset slideshow if returning to chapter

    currentSlide = $currentSlideshow[0];
    $currentChapter.find('.slide.present').removeClass('present');
    $currentChapter.addClass('present');

    // append slide controls and load slides, but only if necessary

    if ($currentSlideshow.length > 0) {
        $currentChapter.append(JST.slide_nav());
        loadSlides($currentSlideshow);
        $rails = $('.rail');
        $previous = $('.previous-slide');
        $next = $('.next-slide');
        $previous.css('display', 'none');

        $previous.on('click', previousSlide);
        $next.on('click', nextSlide);
    }

    // check for playing video, stop it if it is playing

    if (jwplayer('player').getState() == 'PLAYING') {
        jwplayer('player').stop();
    }

    setChapterHash();
};

var loadSlides = function(slideshow) {

    /*
    * Lazy loading for slideshow background images
    */

    _.each(slideshow, function(slide) {
        if ($(slide).data('bgimage')) {
            var backgroundImage = 'assets/img/' + $(slide).data('bgimage');
            $(slide).css('background-image', 'url(' + backgroundImage + ')');
        }
    });
};

var setChapterHash = function() {

    /*
    * Set hash for chapter panels
    */

    currentPanel = $currentChapter.data('panel');
    hasher.setHash(currentPanel);
};

var setSlideHash = function() {

    /*
    * Set hash for slides
    */

    if (index >= 0) {
        hasher.setHash(currentPanel + '/' + index);
    }
    else {
        hasher.setHash(currentPanel);
    }
};

var previousSlide = function() {

    /*
    * Handler for moving backwards in slideshows
    */

    if (index >= 0) {
        index--;
        $(currentSlide).removeClass('present');
        currentSlide = $currentSlideshow[index];
        $(currentSlide).addClass('present');
        setSlideHash();
        checkArrows();
    }
};

var nextSlide = function() {

    /*
    * Handler for moving forwards in slideshows
    */

    if (index < $currentSlideshow.length) {
        index++;
        $(currentSlide).removeClass('present');
        currentSlide = $currentSlideshow[index];
        $(currentSlide).addClass('present');
        setSlideHash();
        checkArrows();
    }
};

var checkArrows = function() {

    /*
    * Based on where you are in a slideshow, hide and show the appropriate arrow controls
    */

    if (index < 0) {
        $previous.css('display', 'none');
    }
    else if (index === $currentSlideshow.length - 1) {
        $next.css('display', 'none');
    }
    else {
        $previous.css('display', 'block');
        $next.css('display', 'block');
    }
};

var handleKeyPress = function(e) {

    /*
    * Enable keyboard navigation in slideshows
    */

    if (e.keyCode === 37 && index >= 0) {
        previousSlide();
    }
    else if (e.keyCode === 39 && index < $currentSlideshow.length - 1) {
        nextSlide();
    }
};

var revealVideo = function() {

    /*
    * Show the video.
    */

    var text = $(this).parents('.text');
    $(text).hide();
    $(text).parent().css('background-image', '');
    $(text).next().css('display', 'table-cell');
    var player = text.siblings('#player');
    initPlayer(player);
};

var initPlayer = function(player) {

    /*
    * Setup JWPlayer.
    */

    jwplayer('player').setup({
        modes: [{
            type: 'flash',
            src: 'http://www.npr.org/templates/javascript/jwplayer/player.swf',
            config: {
                skin: 'http://media.npr.org/templates/javascript/jwplayer/skins/mle/npr-video-archive/npr-video-archive.zip',
                file: 'http://pd.npr.org/npr-mp4/npr/nprvid/2013/02/20130219_nprvid_oscars-n-600000.mp4',
                image: 'http://apps.npr.org/oscars-2013/img/cheat-sheet-promo_wide.jpg',
                'hd.file': 'http://pd.npr.org/npr-mp4/npr/nprvid/2013/02/20130219_nprvid_oscars-n-1200000.mp4'
            }
        }, {
            type: 'html5',
            config: {
                levels: [
                    {
                        file: 'http://pd.npr.org/npr-mp4/npr/nprvid/2013/02/20130219_nprvid_oscars-n-600000.mp4',
                        image: 'http://apps.npr.org/oscars-2013/img/cheat-sheet-promo_wide.jpg'
                    }
                ]
            }
        }],
        bufferlength: '5',
        controlbar: 'over',
        icons: 'true',
        autostart: false,
        width: $w,
        height: $h
    });
    jwplayer('player').play();

};

var handleChanges = function(newHash, oldHash){

    /*
    * Do something when the hash changes. What are we doing here?
    */

};

$(document).ready(function() {

    /*
    * Define vars
    */

    $slides = $('.slide');
    $currentChapter = $('.chapter.active');
    $currentSlideshow = $currentChapter.find('.slide');
    $play = $('.btn-play');
    $video = $('.video');
    currentSlide = $currentSlideshow[index];
    currentPanel = $currentChapter.data('panel');

    // init chapters

    setSlideHeight();
    setUpPanelSnap();

    // hasher setup

    hasher.changed.add(handleChanges);
    hasher.initialized.add(handleChanges);
    hasher.init();

    // handlers

    $(document).keydown(handleKeyPress);
    $play.on('click', revealVideo);

    $slides.lazyload({
        threshold : 50,
    });

    // Redraw slides if the window resizes

    $(window).resize(setSlideHeight);
});<|endoftext|>


<commit_before>/**
 * @file Exports the Game Data API methods.
 * @module lib/data
 */

/**
 * Game Data class constructor.
 *
 * @constructor
 * @param  {Object} blizzard A Blizzard.js instance
 * @return {Function}        Data constructor function
 */
const Data = function Data (blizzard) {
  this.blizzard = blizzard;
};

/**
 * Fetch connected realm game data.
 *
 * @param  {Object} args              The user request arguments
 * @param  {String} args.access_token The user access token
 * @param  {String} args.namespace    The game data namespace
 * @param  {Number} [args.realm]      The connected realm id
 * @param  {String} [args.origin]     The region key
 * @param  {String} [args.locale]     A locale code for this region
 * @param  {Object} [instance]        An [axios](https://github.com/mzabriskie/axios) compatible instance configuration
 * @return {Promise}                  A thenable Promises/A+ reference
 */
Data.prototype.connectedRealm = function connectedRealm (args, instance) {
  if (args.realm) {
    return this.blizzard.get(`/data/wow/connected-realm/${args.realm}`, args, instance);
  }

  return this.blizzard.get('/data/wow/connected-realm/', args, instance);
};

/**
 * Fetch mythic keystone leaderboard game data.
 *
 * @param  {Object} args              The request arguments
 * @param  {String} args.access_token The user access token
 * @param  {String} args.namespace    The game data namespace
 * @param  {Number} args.realm        The connected realm id
 * @param  {Number} [args.dungeon]    The dungeon id
 * @param  {Number} [args.period]     The mythic leaderboard period
 * @param  {String} [args.origin]     The region key
 * @param  {String} [args.locale]     A locale code for this region
 * @param  {Object} [instance]        An [axios](https://github.com/mzabriskie/axios) compatible instance configuration
 * @return {Promise}                  A thenable Promises/A+ reference
 */
Data.prototype.mythicLeaderboard = function mythicLeaderboard (args, instance) {
  if (args.realm && args.dungeon && args.period) {
    return this.blizzard.get(`/data/wow/connected-realm/${args.realm}/mythic-leaderboard/${args.dungeon}/period/${args.period}`, args, instance);
  }

  return this.blizzard.get(`/data/wow/connected-realm/${args.realm}/mythic-leaderboard/`, args, instance);
};

/**
 * Fetch realm game data.
 *
 * @param  {Object} args                The user request arguments
 * @param  {String} args.access_token   The user access token
 * @param  {String} args.namespace      The game data namespace
 * @param  {String|Number} [args.realm] The realm slug or id
 * @param  {String} [args.origin]       The region key
 * @param  {String} [args.locale]       A locale code for this region
 * @param  {Object} [instance]          An [axios](https://github.com/mzabriskie/axios) compatible instance configuration
 * @return {Promise}                    A thenable Promises/A+ reference
 */
Data.prototype.realm = function realm (args, instance) {
  if (args.realm) {
    return this.blizzard.get(`/data/wow/realm/${args.realm}`, args, instance);
  }

  return this.blizzard.get('/data/wow/realm/', args, instance);
};

/**
 * Fetch region game data.
 *
 * @param  {Object} args              The user request arguments
 * @param  {String} args.access_token The user access token
 * @param  {String} args.namespace    The game data namespace
 * @param  {Number} [args.region]     The region id
 * @param  {String} [args.origin]     The region key
 * @param  {String} [args.locale]     A locale code for this region
 * @param  {Object} [instance]        An [axios](https://github.com/mzabriskie/axios) compatible instance configuration
 * @return {Promise}                  A thenable Promises/A+ reference
 */
Data.prototype.region = function region (args, instance) {
  if (args.region) {
    return this.blizzard.get(`/data/wow/region/${args.region}`, args, instance);
  }

  return this.blizzard.get('/data/wow/region/', args, instance);
};

/**
 * Fetch token game data.
 *
 * @param  {Object} args              The user request arguments
 * @param  {String} args.access_token The user access token
 * @param  {String} args.namespace    The game data namespace
 * @param  {String} [args.origin]     The region key
 * @param  {String} [args.locale]     A locale code for this region
 * @param  {Object} [instance]        An [axios](https://github.com/mzabriskie/axios) compatible instance configuration
 * @return {Promise}                  A thenable Promises/A+ reference
 */
Data.prototype.token = function token (args, instance) {
  return this.blizzard.get('/data/wow/token/', args, instance);
};

module.exports = Data;
<commit_msg>Ensure function args is always an object<commit_after>/**
 * @file Exports the Game Data API methods.
 * @module lib/data
 */

/**
 * Game Data class constructor.
 *
 * @constructor
 * @param  {Object} blizzard A Blizzard.js instance
 * @return {Function}        Data constructor function
 */
const Data = function Data (blizzard) {
  this.blizzard = blizzard;
};

/**
 * Fetch connected realm game data.
 *
 * @param  {Object} args              The user request arguments
 * @param  {String} args.access_token The user access token
 * @param  {String} args.namespace    The game data namespace
 * @param  {Number} [args.realm]      The connected realm id
 * @param  {String} [args.origin]     The region key
 * @param  {String} [args.locale]     A locale code for this region
 * @param  {Object} [instance]        An [axios](https://github.com/mzabriskie/axios) compatible instance configuration
 * @return {Promise}                  A thenable Promises/A+ reference
 */
Data.prototype.connectedRealm = function connectedRealm (args, instance) {
  const obj = Object.assign({}, args);

  if (obj.realm) {
    return this.blizzard.get(`/data/wow/connected-realm/${obj.realm}`, args, instance);
  }

  return this.blizzard.get('/data/wow/connected-realm/', args, instance);
};

/**
 * Fetch mythic keystone leaderboard game data.
 *
 * @param  {Object} args              The request arguments
 * @param  {String} args.access_token The user access token
 * @param  {String} args.namespace    The game data namespace
 * @param  {Number} args.realm        The connected realm id
 * @param  {Number} [args.dungeon]    The dungeon id
 * @param  {Number} [args.period]     The mythic leaderboard period
 * @param  {String} [args.origin]     The region key
 * @param  {String} [args.locale]     A locale code for this region
 * @param  {Object} [instance]        An [axios](https://github.com/mzabriskie/axios) compatible instance configuration
 * @return {Promise}                  A thenable Promises/A+ reference
 */
Data.prototype.mythicLeaderboard = function mythicLeaderboard (args, instance) {
  const obj = Object.assign({}, args);

  if (obj.realm && obj.dungeon && obj.period) {
    return this.blizzard.get(`/data/wow/connected-realm/${obj.realm}/mythic-leaderboard/${obj.dungeon}/period/${obj.period}`, args, instance);
  }

  return this.blizzard.get(`/data/wow/connected-realm/${obj.realm}/mythic-leaderboard/`, args, instance);
};

/**
 * Fetch realm game data.
 *
 * @param  {Object} args                The user request arguments
 * @param  {String} args.access_token   The user access token
 * @param  {String} args.namespace      The game data namespace
 * @param  {String|Number} [args.realm] The realm slug or id
 * @param  {String} [args.origin]       The region key
 * @param  {String} [args.locale]       A locale code for this region
 * @param  {Object} [instance]          An [axios](https://github.com/mzabriskie/axios) compatible instance configuration
 * @return {Promise}                    A thenable Promises/A+ reference
 */
Data.prototype.realm = function realm (args, instance) {
  const obj = Object.assign({}, args);

  if (obj.realm) {
    return this.blizzard.get(`/data/wow/realm/${obj.realm}`, args, instance);
  }

  return this.blizzard.get('/data/wow/realm/', args, instance);
};

/**
 * Fetch region game data.
 *
 * @param  {Object} args              The user request arguments
 * @param  {String} args.access_token The user access token
 * @param  {String} args.namespace    The game data namespace
 * @param  {Number} [args.region]     The region id
 * @param  {String} [args.origin]     The region key
 * @param  {String} [args.locale]     A locale code for this region
 * @param  {Object} [instance]        An [axios](https://github.com/mzabriskie/axios) compatible instance configuration
 * @return {Promise}                  A thenable Promises/A+ reference
 */
Data.prototype.region = function region (args, instance) {
  const obj = Object.assign({}, args);

  if (obj.region) {
    return this.blizzard.get(`/data/wow/region/${obj.region}`, args, instance);
  }

  return this.blizzard.get('/data/wow/region/', args, instance);
};

/**
 * Fetch token game data.
 *
 * @param  {Object} args              The user request arguments
 * @param  {String} args.access_token The user access token
 * @param  {String} args.namespace    The game data namespace
 * @param  {String} [args.origin]     The region key
 * @param  {String} [args.locale]     A locale code for this region
 * @param  {Object} [instance]        An [axios](https://github.com/mzabriskie/axios) compatible instance configuration
 * @return {Promise}                  A thenable Promises/A+ reference
 */
Data.prototype.token = function token (args, instance) {
  return this.blizzard.get('/data/wow/token/', args, instance);
};

module.exports = Data;
<|endoftext|>


<commit_before>//var _this = this;

osm.poi = {
  i18n: {},
  // layers:{},
  opt:{

  },

  initialize: function() {
    osm.poi.layer = new L.LayerGroup();
    //osm.map.addLayer(osm.poi.layer);
    osm.poi.tree=$('#leftpoi div.leftcontent')
      .jstree({
        "plugins" : ["json_data", "checkbox","ui"],
        "json_data" : {
          "ajax" : {
            "type": 'GET',
            "url": "data/poidatatree.json"
          }
        },
        "checkbox": {
          "override_ui": true
        }
      })
      .bind("change_state.check_box.jstree", function (event, data) {
        osm.poi.updateMarkerTree(event, data);
      });
    $.getJSON('data/poimarker.json',
      function(results){
        osm.poi._markers=results;
      }
    )
  },

  enable: function() {
    osm.map.addLayer(osm.poi.layer);
    this.opt.on=true;
    osm.map.on('moveend', osm.poi.updateMarkerTree);
    // osm.map.on('popupopen', osm.poi.bindOpenPopup);
    // osm.map.on('popupclose', osm.poi.bindClosePopup);
  },

  disable: function() {
    this.opt.on=false;
    osm.map.removeLayer(osm.poi.layer);
    osm.map.off('moveend',this.updateMarkerTree);
    // osm.map.off('popupopen', osm.poi.bindOpenPopup);
    // osm.map.off('popupclose', osm.poi.bindClosePopup);
  },

  updateMarkerTree: function(){
    var move = false;
    if (arguments[0].type=="moveend"){move=true}
    if (!move && arguments[1].args[1] && false) {
      incheck = arguments[1].args[0].parentNode.parentNode;
      isleaf=false;
      for (var i=0;i<incheck.classList.length;i++) {
        if (incheck.classList[i]=="jstree-leaf") {isleaf=true;}
      }
      if (isleaf) {
        for (item in osm.poi.layer._layers){
          a=1;
        }
      }

      arguments[1].args[0].parentNode.parentNode.attributes['nclass'].nodeValue
    }
    var checked=$('.jstree-checked.jstree-leaf', osm.poi.tree );
    var nclass=[];
    for (i=0;i<checked.length;i++) {
      nclass.push(checked[i].attributes['nclass'].nodeValue);
    }
    nclass=nclass.join(',');
    var bounds = osm.map.getBounds();
    var sw = bounds.getSouthWest(), ne = bounds.getNorthEast();
    $.getJSON('/api/poi', {action:"getpoibbox", nclass:nclass, t:ne.lat, r:ne.lng, b:sw.lat, l:sw.lng},
      function(results){
        markers={};
        for (item1 in osm.poi.layer._layers){
          markers[$(osm.poi.layer._layers[item1]._popup._content,'div.poi_popup').attr('id')]=osm.poi.layer._layers[item1]
        }
        //osm.poi.layer.clearLayers();
        for (item2 in results.data){
          if (markers[results.data[item2].id]){
            delete markers[results.data[item2].id];
          }
          else {
            if (osm.poi._markers.indexOf(results.data[item2].nclass) == -1)
              icon_url = 'img/poi_marker/default.png';
            else
              icon_url = 'img/poi_marker/'+results.data[item2].nclass+'.png';
            _marker = new L.Marker(new L.LatLng(results.data[item2].lat, results.data[item2].lon), {icon:new osm.poi.poiIcon({iconUrl: icon_url})});
            _marker.bindPopup(osm.poi.createPopupText(results.data[item2]));
            osm.poi.layer.addLayer(_marker);
          }
        }
        for (item3 in markers){
          osm.map.removeLayer(markers[item3]);
          delete osm.poi.layer._layers[markers[item3]._leaflet_id];
        }

      })
    .error(
      function(jqXHR, textStatus, errorThrown){
        console.log('Ошибка: ' + textStatus + '
' + errorThrown.message);
      });
  },
  poiIcon :  L.Icon.extend({
		options: {
			//iconUrl: 'img/marker-icon.png',
			iconSize: new L.Point(31, 31),
			shadowSize: new L.Point(0, 0),
			iconAnchor: new L.Point(16, 30),
			popupAnchor: new L.Point(0, -11)
		}
	}),

  createPopupText: function(getdata) {
    if (!(getdata == null)) {
      var operator;
      if (!(getdata.operator==null)) {
        operator=$('
').addClass('poi_operator')
          .append($('').text('Владелец: '))
          .append($('').text(getdata.operator).addClass('poi_value'))
      }
      var brand;
      if (!(getdata.brand==null)) {
        brand=$('
').addClass('poi_brand')
          .append($('').text('Бренд: '))
          .append($('').text(getdata.brand).addClass('poi_value'))
      }
      var phone;
      if (!(getdata.phone==null)) {
        phone=$('
').addClass('poi_phone')
          .append($('').text('Телефон: '))
          .append($('').text(getdata.phone).addClass('poi_value'))
      }
      var fax;
      if (!(getdata.fax==null)) {
        fax=$('
').addClass('poi_fax')
          .append($('').text('Факс: '))
          .append($('').text(getdata.fax).addClass('poi_value'))
      }

	var website;
	if (!(getdata.website==null)) {
		// assume http:// for protocol-less links
		var properLink = getdata.website;
		if (properLink.indexOf(':') < 0) {
			properLink = 'http://' + properLink;
		}

		website=$('
').addClass('poi_website')
			.append($('').text('Web-сайт: '))
			.append($('').addClass('poi_value')
				.append($('').attr('href', properLink).text(getdata.website))
			);
	}

      var moretags=$('');
      for (xName in getdata.tags_ru) {
        if (getdata.tags_ru[xName]!="неизвестно") {
          moretags.after($('
').addClass('poi_moretags')
            .append($('').text(xName+': '))
            .append($('').text(getdata.tags_ru[xName])))
        }
      }

      if (getdata.opening_hours) {
        getdata.opening_hours = getdata.opening_hours
          .replace('Mo', 'Пн')
          .replace('Tu', 'Вт')
          .replace('We', 'Ср')
          .replace('Th', 'Чт')
          .replace('Fr', 'Пт')
          .replace('Sa', 'Сб')
          .replace('Su', 'Вс');
      }
      ret = $('
').addClass('poi_popup').attr('id',getdata.id)
        .append($('
').addClass('poi_header')
          .append($('').text(getdata.class_ru).addClass('poi_name'))
          .append($('').text(getdata.name_ru||'').addClass('poi_value'))
        )
        .append($('
')
          .append($('
').addClass('poi_opening_hours')
            .append($('').text('Время работы: '))
            .append($('').text(getdata.opening_hours||osm.poi.opt.nulldisplay).addClass('poi_value'))
          )
          .append($('
').addClass('poi_addr')
            .append($('').text('Адрес: '))
            .append($('').text(getdata.addr_full_name||"").addClass('poi_value'))
          )
          .append(operator)
          .append(brand)
          .append(phone)
          .append(fax)
          .append(website)
          .append(moretags)
        )

      return $('
').append(ret.clone()).remove().html();
    }
  },

  createPopup: function(id, marker) {
    var textPopup = $('')
    textPopup = $('
').append(textPopup.clone()).remove().html();
    marker.bindPopup(textPopup);
    $.getJSON("/api/poi", {action: 'getpoiinfo', id: id}, function(json){
      if (!(json.data == null)) {

        textP = osm.poi.createPopupText(json.data);

        isopen=osm.map.hasLayer(marker._popup);
        if (isopen) {marker.closePopup();}
        marker.bindPopup(textP,{maxWidth:400});
        icon_url = 'img/poi_marker/'+json.data.nclass+'.png';
        marker.setIcon(new osm.poi.poiIcon({iconUrl: icon_url}));
        if (isopen) {marker.openPopup();}
      }
    })
  },

  bindOpenPopup: function(){
    osm.poi.openpopup=arguments[0].popup;
  },
  bindClosePopup: function(){
    delete osm.poi.openpopup;
  }

}

osm.poi.opt={
  on: false,
  nulldisplay: "Неизвестно"
}
<commit_msg>#121 открывать в новом окне<commit_after>//var _this = this;

osm.poi = {
  i18n: {},
  // layers:{},
  opt:{

  },

  initialize: function() {
    osm.poi.layer = new L.LayerGroup();
    //osm.map.addLayer(osm.poi.layer);
    osm.poi.tree=$('#leftpoi div.leftcontent')
      .jstree({
        "plugins" : ["json_data", "checkbox","ui"],
        "json_data" : {
          "ajax" : {
            "type": 'GET',
            "url": "data/poidatatree.json"
          }
        },
        "checkbox": {
          "override_ui": true
        }
      })
      .bind("change_state.check_box.jstree", function (event, data) {
        osm.poi.updateMarkerTree(event, data);
      });
    $.getJSON('data/poimarker.json',
      function(results){
        osm.poi._markers=results;
      }
    )
  },

  enable: function() {
    osm.map.addLayer(osm.poi.layer);
    this.opt.on=true;
    osm.map.on('moveend', osm.poi.updateMarkerTree);
    // osm.map.on('popupopen', osm.poi.bindOpenPopup);
    // osm.map.on('popupclose', osm.poi.bindClosePopup);
  },

  disable: function() {
    this.opt.on=false;
    osm.map.removeLayer(osm.poi.layer);
    osm.map.off('moveend',this.updateMarkerTree);
    // osm.map.off('popupopen', osm.poi.bindOpenPopup);
    // osm.map.off('popupclose', osm.poi.bindClosePopup);
  },

  updateMarkerTree: function(){
    var move = false;
    if (arguments[0].type=="moveend"){move=true}
    if (!move && arguments[1].args[1] && false) {
      incheck = arguments[1].args[0].parentNode.parentNode;
      isleaf=false;
      for (var i=0;i<incheck.classList.length;i++) {
        if (incheck.classList[i]=="jstree-leaf") {isleaf=true;}
      }
      if (isleaf) {
        for (item in osm.poi.layer._layers){
          a=1;
        }
      }

      arguments[1].args[0].parentNode.parentNode.attributes['nclass'].nodeValue
    }
    var checked=$('.jstree-checked.jstree-leaf', osm.poi.tree );
    var nclass=[];
    for (i=0;i<checked.length;i++) {
      nclass.push(checked[i].attributes['nclass'].nodeValue);
    }
    nclass=nclass.join(',');
    var bounds = osm.map.getBounds();
    var sw = bounds.getSouthWest(), ne = bounds.getNorthEast();
    $.getJSON('/api/poi', {action:"getpoibbox", nclass:nclass, t:ne.lat, r:ne.lng, b:sw.lat, l:sw.lng},
      function(results){
        markers={};
        for (item1 in osm.poi.layer._layers){
          markers[$(osm.poi.layer._layers[item1]._popup._content,'div.poi_popup').attr('id')]=osm.poi.layer._layers[item1]
        }
        //osm.poi.layer.clearLayers();
        for (item2 in results.data){
          if (markers[results.data[item2].id]){
            delete markers[results.data[item2].id];
          }
          else {
            if (osm.poi._markers.indexOf(results.data[item2].nclass) == -1)
              icon_url = 'img/poi_marker/default.png';
            else
              icon_url = 'img/poi_marker/'+results.data[item2].nclass+'.png';
            _marker = new L.Marker(new L.LatLng(results.data[item2].lat, results.data[item2].lon), {icon:new osm.poi.poiIcon({iconUrl: icon_url})});
            _marker.bindPopup(osm.poi.createPopupText(results.data[item2]));
            osm.poi.layer.addLayer(_marker);
          }
        }
        for (item3 in markers){
          osm.map.removeLayer(markers[item3]);
          delete osm.poi.layer._layers[markers[item3]._leaflet_id];
        }

      })
    .error(
      function(jqXHR, textStatus, errorThrown){
        console.log('Ошибка: ' + textStatus + '
' + errorThrown.message);
      });
  },
  poiIcon :  L.Icon.extend({
		options: {
			//iconUrl: 'img/marker-icon.png',
			iconSize: new L.Point(31, 31),
			shadowSize: new L.Point(0, 0),
			iconAnchor: new L.Point(16, 30),
			popupAnchor: new L.Point(0, -11)
		}
	}),

  createPopupText: function(getdata) {
    if (!(getdata == null)) {
      var operator;
      if (!(getdata.operator==null)) {
        operator=$('
').addClass('poi_operator')
          .append($('').text('Владелец: '))
          .append($('').text(getdata.operator).addClass('poi_value'))
      }
      var brand;
      if (!(getdata.brand==null)) {
        brand=$('
').addClass('poi_brand')
          .append($('').text('Бренд: '))
          .append($('').text(getdata.brand).addClass('poi_value'))
      }
      var phone;
      if (!(getdata.phone==null)) {
        phone=$('
').addClass('poi_phone')
          .append($('').text('Телефон: '))
          .append($('').text(getdata.phone).addClass('poi_value'))
      }
      var fax;
      if (!(getdata.fax==null)) {
        fax=$('
').addClass('poi_fax')
          .append($('').text('Факс: '))
          .append($('').text(getdata.fax).addClass('poi_value'))
      }

	var website;
	if (!(getdata.website==null)) {
		// assume http:// for protocol-less links
		var properLink = getdata.website;
		if (properLink.indexOf(':') < 0) {
			properLink = 'http://' + properLink;
		}

		website=$('
').addClass('poi_website')
			.append($('').text('Web-сайт: '))
			.append($('').addClass('poi_value')
				.append($('').attr('href', properLink).attr('target', '_blank').text(getdata.website))
			);
	}

      var moretags=$('');
      for (xName in getdata.tags_ru) {
        if (getdata.tags_ru[xName]!="неизвестно") {
          moretags.after($('
').addClass('poi_moretags')
            .append($('').text(xName+': '))
            .append($('').text(getdata.tags_ru[xName])))
        }
      }

      if (getdata.opening_hours) {
        getdata.opening_hours = getdata.opening_hours
          .replace('Mo', 'Пн')
          .replace('Tu', 'Вт')
          .replace('We', 'Ср')
          .replace('Th', 'Чт')
          .replace('Fr', 'Пт')
          .replace('Sa', 'Сб')
          .replace('Su', 'Вс');
      }
      ret = $('
').addClass('poi_popup').attr('id',getdata.id)
        .append($('
').addClass('poi_header')
          .append($('').text(getdata.class_ru).addClass('poi_name'))
          .append($('').text(getdata.name_ru||'').addClass('poi_value'))
        )
        .append($('
')
          .append($('
').addClass('poi_opening_hours')
            .append($('').text('Время работы: '))
            .append($('').text(getdata.opening_hours||osm.poi.opt.nulldisplay).addClass('poi_value'))
          )
          .append($('
').addClass('poi_addr')
            .append($('').text('Адрес: '))
            .append($('').text(getdata.addr_full_name||"").addClass('poi_value'))
          )
          .append(operator)
          .append(brand)
          .append(phone)
          .append(fax)
          .append(website)
          .append(moretags)
        )

      return $('
').append(ret.clone()).remove().html();
    }
  },

  createPopup: function(id, marker) {
    var textPopup = $('')
    textPopup = $('
').append(textPopup.clone()).remove().html();
    marker.bindPopup(textPopup);
    $.getJSON("/api/poi", {action: 'getpoiinfo', id: id}, function(json){
      if (!(json.data == null)) {

        textP = osm.poi.createPopupText(json.data);

        isopen=osm.map.hasLayer(marker._popup);
        if (isopen) {marker.closePopup();}
        marker.bindPopup(textP,{maxWidth:400});
        icon_url = 'img/poi_marker/'+json.data.nclass+'.png';
        marker.setIcon(new osm.poi.poiIcon({iconUrl: icon_url}));
        if (isopen) {marker.openPopup();}
      }
    })
  },

  bindOpenPopup: function(){
    osm.poi.openpopup=arguments[0].popup;
  },
  bindClosePopup: function(){
    delete osm.poi.openpopup;
  }

}

osm.poi.opt={
  on: false,
  nulldisplay: "Неизвестно"
}
<|endoftext|>


<commit_before>'use strict';

function Player(game, x, y, bulletManager, id, weaponManager, enemyManager)
{
var self = this;

//just in case
if(game.playerList[id] == undefined)
	{
	console.log("~~ player " + id + " was not set in game.playerList yet !?");
	game.playerList[id] = {};
	game.playerList[id].totalScore = 0;
	}

if(!game.playerList[id].totalScore)
	{
	game.playerList[id].totalScore = 0;
	}

var bullets = ['bullet1', 'bullet2', 'bullet3', 'bullet4', 'bullet5', 'bullet6'];
var sprites = ['player1', 'player2', 'player3', 'player4', 'player5', 'player6'];
var input;
//self.playerClass = Math.floor((Math.random() * 6)); //rand 0-5
self.playerClass;
self.playerName;
self.id = id;

self.score = 0;

var hitColorTime = 50;

self.maxHealth = 200;
self.currentHealth = self.maxHealth;

self.dead = false;
//var randomSprite = sprites[Math.floor((Math.random() * 6))];

self.sprite = game.add.sprite(x, y, 'empty');
self.sprite.anchor.setTo(0.5, 0.5);
self.sprite.exists = false;
self.sprite.playerObj = self;  //powerups need the player object, bad solution, anythign better?
var setupDone = false;

var flipped = false;

var fireRate = 200;
var baseFireRate = 200;

var nextFire = 0;

var movementSpeed = 200;
var baseMovementSpeed = 200;

var respawnTime = 250;
var nextRespawn = 0;

var bulletDamage = 2;
var bulletSpeed = 1000;
var bulletLifespan = 1000;

var cameraPadding = 20;

var headingPoint = new Phaser.Point();
var vectorPoint = new Phaser.Point();
vectorPoint.x = -1;
vectorPoint.y = 0;

var activePowerUps = [];

var pHUD;

// Spawn timeout stuff, will maybe become obsolete when spawning part of sprite spritesheet

var spawnDelay = game.effectManager.getSpawnDuration();
var spawnTimer = game.time.now;
var deathRelativePos = {x: 0, y: 0};
var enemyFreeSpawnRadius = game.width/15;
var spawnBorder = game.width/15;

var scale = function ()
	{
	if (flipped)
		{
		self.sprite.scale.x = -scalingFactors.x;
		self.sprite.body.setSize(-self.sprite.width, self.sprite.height);
		}
	else
		{
		self.sprite.scale.x = scalingFactors.x;
		self.sprite.body.setSize(self.sprite.width, self.sprite.height);
		}
	self.sprite.scale.y = scalingFactors.y;
	};

/**
* Creates the player object
* Sets the sprite and weapon, along with creating a healthbar and setting the player name
*/
var createPlayer = function ()
	{
	self.sprite.loadTexture(sprites[self.playerClass]);

	game.physics.enable(self.sprite, Phaser.Physics.ARCADE);
	self.sprite.body.collideWorldBounds = true;
	self.sprite.body.bounce = (1,1);

	self.weapon = weaponManager.createWeapon(self, sprites[self.playerClass]);

	pHUD = new Hud(game, self);
	pHUD.setName(self.playerName);
	self.sprite.exists = true;

	};

self.setInput = function (inputArray)
	{
	input = inputArray;
	};

//called by controller once it is created
var setClassAndName = function (pClass, pName)
	{
	self.playerClass = pClass;
	self.playerName = pName;
	game.playerList[id].name = pName;
	game.playerList[id].class = pClass;
	//console.log('pname: ' + self.playerName + ', pclass: ' + self.playerClass);
	};

self.update = function ()
	{

	self.sprite.exists = ! (spawnTimer + spawnDelay > game.time.now || self.dead);
	if (self.weapon != undefined) self.weapon.sprite.exists = ! (spawnTimer + spawnDelay > game.time.now || self.dead);

	scale();
	if (!self.dead)
		{
		if (input != undefined)
			{
			if(!setupDone)
				{
				//setting the player up here is a workaround to enable play on firefox
				//console.log('setting up player');
				setClassAndName(input.pClass, input.pName);
				createPlayer();
				setupDone = true;
				}
			var length = input.moveLength;
			if(length > 1)
				{
				length = 1;
				}
			var moveAngle = input.moveAngle;
			game.physics.arcade.velocityFromAngle(moveAngle, movementSpeed * length, self.sprite.body.velocity);

			var shooting = input.shootAngle != 0;

			if(Math.abs(input.shootAngle) > 180/2 && !flipped)
				{
				flipped = true;
				}
			else if(Math.abs(input.shootAngle) < 180/2 && flipped)
				{
				flipped = false;
				}

			if (self.sprite.body.velocity.x > 0 && flipped && !shooting)
				{
				flipped = false;
				}
				else if (self.sprite.body.velocity.x < 0 && !flipped && !shooting)
				{
				flipped = true;
				}

			if (shooting && (game.time.now > nextFire))
				{
				nextFire = game.time.now + fireRate;
				bulletManager.createBullet(bullets[self.playerClass], bulletDamage, self.id, input.shootAngle, self.sprite.position, bulletSpeed, bulletLifespan);
				}
			self.weapon.sprite.angle = input.shootAngle;
			self.weapon.update(flipped, input);
			}

		//We should only check for collisions when there are collidable objects on screen
		if(bulletManager.enemyBulletCount > 0)
			{
			game.physics.arcade.overlap(bulletManager.enemyBulletGroups, self.sprite, self.playerHit, null, self);
			}

		//Check for powerups only if powerups are active
		if(activePowerUps.length > 0) {
			for (var i = activePowerUps.length - 1; i >= 0; i--) {
				if(activePowerUps[i] != 'undefined') {
					if(activePowerUps[i].endTime <= game.time.now) {
						if(activePowerUps[i].powerUpID == 'incSpeed')
						{
							self.setSpeed(baseMovementSpeed);
						}

						else if (activePowerUps[i].powerUpID == 'incFireRate')
						{
							self.setFireRate(baseFireRate);
						}
						activePowerUps.splice(i,1); //We remove the expired powerup from the array
					}
				}
			}
		}

		} else if (self.dead && nextRespawn < 0) {
		self.sprite.position.x = game.camera.x + deathRelativePos.x;
		self.sprite.position.y = game.camera.y + deathRelativePos.y;
		checkSpawnPosition();
		game.effectManager.createSpawnEffect(self.sprite.position);
		spawnTimer = game.time.now;
		self.dead = false;
		self.currentHealth = self.maxHealth;
		gameClient.callClientRpc(self.id, "setDeath", [true], self, null);
		pHUD.updateHealthBar();
		} else {
		nextRespawn--;
		}

		// We always check if the player has fallen behing the camera

		if (self.sprite.position.x < game.camera.x + cameraPadding)
		{
			self.sprite.position.x = game.camera.x + cameraPadding;
		} else if (self.sprite.position.x > game.camera.x + game.camera.width - cameraPadding)
		{
			self.sprite.position.x = game.camera.x + game.camera.width - cameraPadding;
		}

		if (self.sprite.position.y < game.camera.y + cameraPadding)
		{
			self.sprite.position.y = game.camera.y + cameraPadding;
		} else if (self.sprite.position.y > game.camera.y + game.camera.height - cameraPadding)
		{
			self.sprite.position.y = game.camera.y + game.camera.height - cameraPadding;
		}
	};

/**
* Triggers when the player is hit
* Changes player color and applies damage
* @param {player} player - The player object which is hit
* @param {bullet} bullet - The bullet object which hits the player
*/

self.playerHit = function(player, bullet)
	{
	self.sprite.tint = 0xCC0000;
	game.time.events.add(hitColorTime, function() {self.sprite.tint = 0xFFFFFF;});
	var damage = bullet.damage;
	bulletManager.killbullet(bullet);
	self.takeDamage(damage);
	gameClient.callClientRpc(self.id, "setHapticFeedback", [50], self, null);
	};

/**
* Triggers when the player takes damage
* Decreases health and updates the healthbar, also kills the payer if necessery
* @param {Number} damage - The amount of damage to deal
*/
self.takeDamage = function(damage)
	{
	self.currentHealth = self.currentHealth-damage;
	if(self.currentHealth <= 0 && !self.dead)
		{
		self.dead = true;
		self.kill();
		self.currentHealth = 0;
		}
		pHUD.updateHealthBar();
	};

/**
* Heals the player for specified amount
* @param {Number} amount - The amount of health to restore
*/
self.heal = function(amount)
{
	if(self.currentHealth + amount >= self.maxHealth) {
		self.currentHealth = self.maxHealth;
	} else {
		self.currentHealth += amount;
	}
	pHUD.updateHealthBar();
}

self.setFireRate = function(amount)
{
	fireRate = amount;
}

self.setSpeed = function(amount)
{
	movementSpeed = amount;

}

/**
* Starts a powerup on the player object
* @param {string} pUpID - The ID of the powerup as displayed in pUpDictionary
* @param {Number} pUpDuration - The Duration of the powerup in milliseconds
* @param {Number} pUpStats - The value for the powerup
*/
self.startPowerUp = function(pUpID, pUpDuration, pUpStats)
{
	var powerupFound = false;

	//If the player picks two powerups we simply extend the duration.
	for (var i = activePowerUps.length - 1; i >= 0; i--) {
		if(activePowerUps[i].powerUpID == pUpID) {
			activePowerUps[i].endTime = game.time.now + pUpDuration;
			powerupFound = true;
		}
	}
	//If this is the first instance of a powerup we add it to the active list
	if(!powerupFound) {
		var newPowerUp = {powerUpID: pUpID, endTime: game.time.now + pUpDuration};
		activePowerUps.push(newPowerUp);
		switch(pUpID)
		{
			case 'incSpeed':
				self.setSpeed(movementSpeed + pUpStats);
				break;

			case 'incFireRate':
				self.setFireRate(fireRate - pUpStats);
				break;

			default:
				break;
		}
	}
}

/**
* Kills the player object
*/
self.kill = function ()
	{
	clearAllPowerups();
	game.effectManager.popupScoreText('-100',self.sprite);
	self.sprite.exists = false;
	self.weapon.sprite.exists = false;
	gameClient.callClientRpc(self.id, "setHapticFeedback", [200], self, null);
	gameClient.callClientRpc(self.id, "setDeath", [false], self, null);
	game.effectManager.createDeathEffect(self);
	nextRespawn = respawnTime;
	deathRelativePos.x = self.sprite.position.x - game.camera.x;
	deathRelativePos.y = self.sprite.position.y - game.camera.y;
	self.losePoints(100);
	};

/**
* Adds a specified amount of points to the player
* @param {Number} amount - The amount of points to add
*/
self.getPoints =  function(amount)
	{
	self.score += amount;
	if(game.playerList[id] != undefined)
		{
		game.playerList[id].totalScore += amount;
		}
	}

/**
* Removes a specified amount of points to the player
* @param {Number} amount - The amount of points to remove
*/
self.losePoints = function(amount)
	{
	self.score -= amount;
	if(game.playerList[id] != undefined)
		{
		game.playerList[id].totalScore -= amount;
		}
	}

var checkSpawnPosition = function()
	{
	var distance = dClosestEnemy(enemyManager.enemyList, self.sprite.position); //why doesn't work getAllLivingFromObject('enemyList')?
	while(distance < enemyFreeSpawnRadius)
		{
		findNewSpawnPostion();
		distance = dClosestEnemy(enemyManager.enemyList, self.sprite.position); //no need to update aliveEnemies?
		}
	};

var findNewSpawnPostion = function()
	{
	var newPosition = getRandomPosition(spawnBorder);
	self.sprite.position.x = newPosition.x;
	self.sprite.position.y = newPosition.y;
	};

var clearAllPowerups = function ()
	{
	self.setSpeed(baseMovementSpeed);
	self.setFireRate(baseFireRate);
	activePowerUps = [];
	};
}
<commit_msg>comment removed<commit_after>'use strict';

function Player(game, x, y, bulletManager, id, weaponManager, enemyManager)
{
var self = this;

//just in case
if(game.playerList[id] == undefined)
	{
	console.log("~~ player " + id + " was not set in game.playerList yet !?");
	game.playerList[id] = {};
	game.playerList[id].totalScore = 0;
	}

if(!game.playerList[id].totalScore)
	{
	game.playerList[id].totalScore = 0;
	}

var bullets = ['bullet1', 'bullet2', 'bullet3', 'bullet4', 'bullet5', 'bullet6'];
var sprites = ['player1', 'player2', 'player3', 'player4', 'player5', 'player6'];
var input;
//self.playerClass = Math.floor((Math.random() * 6)); //rand 0-5
self.playerClass;
self.playerName;
self.id = id;

self.score = 0;

var hitColorTime = 50;

self.maxHealth = 200;
self.currentHealth = self.maxHealth;

self.dead = false;
//var randomSprite = sprites[Math.floor((Math.random() * 6))];

self.sprite = game.add.sprite(x, y, 'empty');
self.sprite.anchor.setTo(0.5, 0.5);
self.sprite.exists = false;
self.sprite.playerObj = self;  //powerups need the player object, bad solution, anythign better?
var setupDone = false;

var flipped = false;

var fireRate = 200;
var baseFireRate = 200;

var nextFire = 0;

var movementSpeed = 200;
var baseMovementSpeed = 200;

var respawnTime = 250;
var nextRespawn = 0;

var bulletDamage = 2;
var bulletSpeed = 1000;
var bulletLifespan = 1000;

var cameraPadding = 20;

var headingPoint = new Phaser.Point();
var vectorPoint = new Phaser.Point();
vectorPoint.x = -1;
vectorPoint.y = 0;

var activePowerUps = [];

var pHUD;

// Spawn timeout stuff, will maybe become obsolete when spawning part of sprite spritesheet

var spawnDelay = game.effectManager.getSpawnDuration();
var spawnTimer = game.time.now;
var deathRelativePos = {x: 0, y: 0};
var enemyFreeSpawnRadius = game.width/15;
var spawnBorder = game.width/15;

var scale = function ()
	{
	if (flipped)
		{
		self.sprite.scale.x = -scalingFactors.x;
		self.sprite.body.setSize(-self.sprite.width, self.sprite.height);
		}
	else
		{
		self.sprite.scale.x = scalingFactors.x;
		self.sprite.body.setSize(self.sprite.width, self.sprite.height);
		}
	self.sprite.scale.y = scalingFactors.y;
	};

/**
* Creates the player object
* Sets the sprite and weapon, along with creating a healthbar and setting the player name
*/
var createPlayer = function ()
	{
	self.sprite.loadTexture(sprites[self.playerClass]);

	game.physics.enable(self.sprite, Phaser.Physics.ARCADE);
	self.sprite.body.collideWorldBounds = true;
	self.sprite.body.bounce = (1,1);

	self.weapon = weaponManager.createWeapon(self, sprites[self.playerClass]);

	pHUD = new Hud(game, self);
	pHUD.setName(self.playerName);
	self.sprite.exists = true;

	};

self.setInput = function (inputArray)
	{
	input = inputArray;
	};

//called by controller once it is created
var setClassAndName = function (pClass, pName)
	{
	self.playerClass = pClass;
	self.playerName = pName;
	game.playerList[id].name = pName;
	game.playerList[id].class = pClass;
	//console.log('pname: ' + self.playerName + ', pclass: ' + self.playerClass);
	};

self.update = function ()
	{

	self.sprite.exists = ! (spawnTimer + spawnDelay > game.time.now || self.dead);
	if (self.weapon != undefined) self.weapon.sprite.exists = ! (spawnTimer + spawnDelay > game.time.now || self.dead);

	scale();
	if (!self.dead)
		{
		if (input != undefined)
			{
			if(!setupDone)
				{
				//setting the player up here is a workaround to enable play on firefox
				//console.log('setting up player');
				setClassAndName(input.pClass, input.pName);
				createPlayer();
				setupDone = true;
				}
			var length = input.moveLength;
			if(length > 1)
				{
				length = 1;
				}
			var moveAngle = input.moveAngle;
			game.physics.arcade.velocityFromAngle(moveAngle, movementSpeed * length, self.sprite.body.velocity);

			var shooting = input.shootAngle != 0;

			if(Math.abs(input.shootAngle) > 180/2 && !flipped)
				{
				flipped = true;
				}
			else if(Math.abs(input.shootAngle) < 180/2 && flipped)
				{
				flipped = false;
				}

			if (self.sprite.body.velocity.x > 0 && flipped && !shooting)
				{
				flipped = false;
				}
				else if (self.sprite.body.velocity.x < 0 && !flipped && !shooting)
				{
				flipped = true;
				}

			if (shooting && (game.time.now > nextFire))
				{
				nextFire = game.time.now + fireRate;
				bulletManager.createBullet(bullets[self.playerClass], bulletDamage, self.id, input.shootAngle, self.sprite.position, bulletSpeed, bulletLifespan);
				}
			self.weapon.sprite.angle = input.shootAngle;
			self.weapon.update(flipped, input);
			}

		//We should only check for collisions when there are collidable objects on screen
		if(bulletManager.enemyBulletCount > 0)
			{
			game.physics.arcade.overlap(bulletManager.enemyBulletGroups, self.sprite, self.playerHit, null, self);
			}

		//Check for powerups only if powerups are active
		if(activePowerUps.length > 0) {
			for (var i = activePowerUps.length - 1; i >= 0; i--) {
				if(activePowerUps[i] != 'undefined') {
					if(activePowerUps[i].endTime <= game.time.now) {
						if(activePowerUps[i].powerUpID == 'incSpeed')
						{
							self.setSpeed(baseMovementSpeed);
						}

						else if (activePowerUps[i].powerUpID == 'incFireRate')
						{
							self.setFireRate(baseFireRate);
						}
						activePowerUps.splice(i,1); //We remove the expired powerup from the array
					}
				}
			}
		}

		} else if (self.dead && nextRespawn < 0) {
		self.sprite.position.x = game.camera.x + deathRelativePos.x;
		self.sprite.position.y = game.camera.y + deathRelativePos.y;
		checkSpawnPosition();
		game.effectManager.createSpawnEffect(self.sprite.position);
		spawnTimer = game.time.now;
		self.dead = false;
		self.currentHealth = self.maxHealth;
		gameClient.callClientRpc(self.id, "setDeath", [true], self, null);
		pHUD.updateHealthBar();
		} else {
		nextRespawn--;
		}

		// We always check if the player has fallen behing the camera

		if (self.sprite.position.x < game.camera.x + cameraPadding)
		{
			self.sprite.position.x = game.camera.x + cameraPadding;
		} else if (self.sprite.position.x > game.camera.x + game.camera.width - cameraPadding)
		{
			self.sprite.position.x = game.camera.x + game.camera.width - cameraPadding;
		}

		if (self.sprite.position.y < game.camera.y + cameraPadding)
		{
			self.sprite.position.y = game.camera.y + cameraPadding;
		} else if (self.sprite.position.y > game.camera.y + game.camera.height - cameraPadding)
		{
			self.sprite.position.y = game.camera.y + game.camera.height - cameraPadding;
		}
	};

/**
* Triggers when the player is hit
* Changes player color and applies damage
* @param {player} player - The player object which is hit
* @param {bullet} bullet - The bullet object which hits the player
*/

self.playerHit = function(player, bullet)
	{
	self.sprite.tint = 0xCC0000;
	game.time.events.add(hitColorTime, function() {self.sprite.tint = 0xFFFFFF;});
	var damage = bullet.damage;
	bulletManager.killbullet(bullet);
	self.takeDamage(damage);
	gameClient.callClientRpc(self.id, "setHapticFeedback", [50], self, null);
	};

/**
* Triggers when the player takes damage
* Decreases health and updates the healthbar, also kills the payer if necessery
* @param {Number} damage - The amount of damage to deal
*/
self.takeDamage = function(damage)
	{
	self.currentHealth = self.currentHealth-damage;
	if(self.currentHealth <= 0 && !self.dead)
		{
		self.dead = true;
		self.kill();
		self.currentHealth = 0;
		}
		pHUD.updateHealthBar();
	};

/**
* Heals the player for specified amount
* @param {Number} amount - The amount of health to restore
*/
self.heal = function(amount)
{
	if(self.currentHealth + amount >= self.maxHealth) {
		self.currentHealth = self.maxHealth;
	} else {
		self.currentHealth += amount;
	}
	pHUD.updateHealthBar();
}

self.setFireRate = function(amount)
{
	fireRate = amount;
}

self.setSpeed = function(amount)
{
	movementSpeed = amount;

}

/**
* Starts a powerup on the player object
* @param {string} pUpID - The ID of the powerup as displayed in pUpDictionary
* @param {Number} pUpDuration - The Duration of the powerup in milliseconds
* @param {Number} pUpStats - The value for the powerup
*/
self.startPowerUp = function(pUpID, pUpDuration, pUpStats)
{
	var powerupFound = false;

	//If the player picks two powerups we simply extend the duration.
	for (var i = activePowerUps.length - 1; i >= 0; i--) {
		if(activePowerUps[i].powerUpID == pUpID) {
			activePowerUps[i].endTime = game.time.now + pUpDuration;
			powerupFound = true;
		}
	}
	//If this is the first instance of a powerup we add it to the active list
	if(!powerupFound) {
		var newPowerUp = {powerUpID: pUpID, endTime: game.time.now + pUpDuration};
		activePowerUps.push(newPowerUp);
		switch(pUpID)
		{
			case 'incSpeed':
				self.setSpeed(movementSpeed + pUpStats);
				break;

			case 'incFireRate':
				self.setFireRate(fireRate - pUpStats);
				break;

			default:
				break;
		}
	}
}

/**
* Kills the player object
*/
self.kill = function ()
	{
	clearAllPowerups();
	game.effectManager.popupScoreText('-100',self.sprite);
	self.sprite.exists = false;
	self.weapon.sprite.exists = false;
	gameClient.callClientRpc(self.id, "setHapticFeedback", [200], self, null);
	gameClient.callClientRpc(self.id, "setDeath", [false], self, null);
	game.effectManager.createDeathEffect(self);
	nextRespawn = respawnTime;
	deathRelativePos.x = self.sprite.position.x - game.camera.x;
	deathRelativePos.y = self.sprite.position.y - game.camera.y;
	self.losePoints(100);
	};

/**
* Adds a specified amount of points to the player
* @param {Number} amount - The amount of points to add
*/
self.getPoints =  function(amount)
	{
	self.score += amount;
	if(game.playerList[id] != undefined)
		{
		game.playerList[id].totalScore += amount;
		}
	}

/**
* Removes a specified amount of points to the player
* @param {Number} amount - The amount of points to remove
*/
self.losePoints = function(amount)
	{
	self.score -= amount;
	if(game.playerList[id] != undefined)
		{
		game.playerList[id].totalScore -= amount;
		}
	}

var checkSpawnPosition = function()
	{
	var distance = dClosestEnemy(enemyManager.enemyList, self.sprite.position); //why doesn't work getAllLivingFromObject('enemyList')?
	while(distance < enemyFreeSpawnRadius)
		{
		findNewSpawnPostion();
		distance = dClosestEnemy(enemyManager.enemyList, self.sprite.position);
		}
	};

var findNewSpawnPostion = function()
	{
	var newPosition = getRandomPosition(spawnBorder);
	self.sprite.position.x = newPosition.x;
	self.sprite.position.y = newPosition.y;
	};

var clearAllPowerups = function ()
	{
	self.setSpeed(baseMovementSpeed);
	self.setFireRate(baseFireRate);
	activePowerUps = [];
	};
}
<|endoftext|>


<commit_before>/**
 * The file cache class.
 *
 * @class Cache
 */
var fs = require('fs');
var zlib = require('zlib');
var mime = require('mime');
var crypto = require('crypto');
var minifyHtml = require('html-minifier').minify;
var minifyCSS =  require('clean-css');
var UglifyJS = require('uglify-js');
var watch = require("fwatcher");
var html_minifier_options = {
    removeComments: true,
    removeCommentsFromCDATA: true,
    removeCDATASectionsFromCDATA: true,
    removeAttributeQuotes: true,
    removeRedundantAttributes: true,
    removeEmptyAttributes: true,
    removeOptionalTags: true,
    collapseBooleanAttributes: true,
    collapseWhitespace: true
};

// regular expressions
//var removeFingerprint = /\.[^\.]+\.js$/;
var suffix = /\.\w+$/;
var replaceDoubleSlash = /\/{2,}/g;
var checkFp = /\.@[a-z0-9]{7}\.(?:js|css|html)$/i;

// global file cache
var fileCache = engine.pojo('files');

// this is not quaranteed to be stable! why?
zlib.Z_DEFAULT_COMPRESSION = 9;

/**
 * Read a file or get it from the cache.
 *
 * @public
 * @param {string} The file path.
 * @param {function} The callback function.
 * @param {array} Give an array with allowed paths. (optional)
 * @param {string} A string, which is prepended to a path.
 */
var getFile = exports.get = function getFile (file, callback, index) {

    if (typeof file === 'string') {
        file = {path: file};
    }

    // path must be absolute
    if (!file || !file.path || file.path.indexOf('../') !== -1) {
        var err = new Error('Invalid path.');
        console.error('lib/file.js#51', err.toString());
        return callback(err);
    }

    // set default base path to public app folder
    file.base = file.base || engine.paths.app_public;

    // create a clean path without the fingerprint
    file.clean = removeFingerprint(file.path);

    // create absolute path
    file.read = (file.base + file.clean).replace(replaceDoubleSlash, '/');

    // check if file is already in cache
    var cachedFile = fileCache.get(file.read);
    if (cachedFile) {
        return callback(null, cachedFile, index);
    }

    // check if path had fingerprint
    file.fpInPath = file.fpInPath || (file.clean === file.path ? false : true);

    // get file type
    file.type = mime.lookup(file.clean);

    // read the file from the file system
    fs.readFile(file.read, function (err, data) {

        if (err) {
            console.error('lib/file.js#83', err.toString());
            return callback(err);
        }

        // watch for file changes
        if (cachedFile !== null) {
            watch(file.read, function (err) {
                if (err) {
                    return console.error(err);
                }

                // remove cached data on file change, to force reload
                console.log('FILE CHANGE:', file.read);

                // set file item to null
                fileCache.set(file.read, null);
            });
        }

        // minify js, html or css
        switch (file.type) {
            case 'text/html':

                // TODO don't compress as long html imports or binary ws data is available
                file.noCompression = true;
                data = minifyHtml(data.toString(), html_minifier_options);
                break;

            case 'text/css':
                data = new minifyCSS({processImport: false}).minify(data.toString()).styles;
                break;
            case 'application/javascript':

                // wrap javascript files, except the engine client
                if (file.clean !== 'engine.js') {
                    data = "E('" + ((file.wrap || '')  + file.clean).replace(replaceDoubleSlash, '/') + "',function(require,module,exports,global,engine){\n" + data.toString() + "\nreturn module});";
                }

                if (engine.production && (data = UglifyJS.minify(data.toString(), {fromString: true}))) {
                    data = data.code;
                }
                break;
        }

        // create fingerprint
        file.fp = crypto.createHash('md5').update(data).digest('hex').substr(0, 7);

        // add the data to the file object
        file.data = data;

        // don't compress data
        if (file.noCompression) {
            return createCacheObject(file, callback, index);
        }

        zlib.gzip(file.data, function (err, data) {

            if (err) {
                console.error('lib/file.js#218', err.toString());
                return callback(err);
            }

            // update file data with compressed data
            file.data = data;

            createCacheObject(file, callback, index);
        });
    });
};

/**
 * Create an cache object with the data buffer and the http headers.
 *
 * @private
 * @param {string} The file name without the fingerprint.
 * @param {string} The file path wihtout the fingerprint.
 * @param {blob} The file data.
 * @param {string} The mime type.
 * @param {string} The fingerprint.
 * @param {function} The callback function.
 */
function createCacheObject (file, callback, index) {

    // get the modification time
    fs.stat(file.read, function (err, stats) {

        if (err) {
            console.error('lib/file.js#245', err.toString());
            return callback(err);
        }

        // create http headers
        // TODO send not modified for non scrips and css
        file.http = {
            'Vary': 'Accept-Encoding',
            'Cache-Control': 'public, max-age=' + (file.fpInPath ? engine.http.maxAge_fingerprint : engine.http.maxAge),
            'Content-Encoding': 'gzip',
            'Content-Length': file.data.length,
            'Content-Type': file.type,
            'Last-Modified': stats.mtime,
            'Etag': file.fp
        };

        // TODO don't append fingerprints to the markup until it's loaded via html import
        if (file.type !== 'text/html') {

            // handle files with suffix
            if (suffix.test(file.clean)) {

                file.ext = file.path.split('.');

                // add public file identifier to path
                if (file.ext[0][0] === '/') {
                    file.ext[0] = '/!' + file.ext[0];
                }

                file.ext.splice(file.ext.length - 1, 0, '@' + file.fp);
                file.ext = file.ext.join('.');

            // handle files without suffix
            } else {
                file.ext = file.path + '.' + '@' + file.fp;
            }
        }

        // add module id to module paths
        file.ext = (file.path[0] !== '/' ? file.wrap : '') + (file.ext || file.path);

        // save zipped data in cache
        fileCache.set(file.read, file);

        // return data
        callback(null, file, index);
    });
}

/**
 * Prepare external component file paths.
 *
 * @public
 * @param {object} The load context, ex a module package.
 * @param {function} The callback function.
 */
exports.prepareComponents = function (loadContext, callback) {

    if (!loadContext || !loadContext.components) {
        var err = new Error('Invalid load context.');
        console.error('lib/file.js#227', err.toString());
        return callback(err);
    }

    // check if there are components to load
    if (
        (!loadContext.components.scripts || !loadContext.components.scripts.length) &&
        (!loadContext.components.markup || !loadContext.components.markup.length) &&
        (!loadContext.components.styles || !loadContext.components.styles.length)
    ) {
        return callback(null, loadContext);
    }

    var count = 0;

    // the prepend path for external module resource urls
    var modulePath = loadContext._id  + '/';

    var handler = function (err, file, index) {

        if (err) {
            console.error('lib/file.js#247', err.toString());
            if (--count === 0) {
                callback(null, loadContext);
            }
            return;
        }

        // update module components paths
        if (loadContext.components[file.compType] && loadContext.components[file.compType][index]) {
            loadContext.components[file.compType][index] = file.ext;
        }

        if (--count === 0) {
            callback(null, loadContext);
        }
    }

    for (var type in loadContext.components) {

        // check if type is allowed
        switch (type) {
            case 'scripts':
            case 'markup':
            case 'styles':
                break;
            default:
              continue;
        }

        // get file paths array
        var files = loadContext.components[type];

        // update count
        count += files.length;

        for (var i = 0, file; i < files.length; ++i) {

            // ignore external paths
            if (files[i].indexOf('//') > -1) {
                if (--count === 0) {
                    callback(null, loadContext);
                }
                continue;
            }

            // create file object
            file = {path: files[i]};

            // save component type to update the components later
            file.compType = type;

            // set a longer cache time for fingerprinted files
            file.fpInPath = true;

            // handle absolute files
            if (file.path[0] === '/') {
                file.base = type === 'markup' ? engine.paths.app_markup : engine.paths.app_public;

            // handle module files
            } else {
                file.base = loadContext._base;
                file.wrap = modulePath;
            }

            // read the file
            getFile(file, handler, i);
        }
    }
}

/**f
 * Remove fingerprint from path
 *
 * @private
 * @param {string} The file path.
 */
function removeFingerprint (path) {

    // remove fingerprint if it's found in path
    if (checkFp.test(path)) {

        // split path
        path = path.split('.');

        // get fingerprint and remove fingerprint from read path
        path.splice(path.length - 2, 1)[0];

        // create path without fingerprint
        path = path.join('.');
    }

    // return path
    return path;
}
<commit_msg>ignore external urls that start with "//"<commit_after>/**
 * The file cache class.
 *
 * @class Cache
 */
var fs = require('fs');
var zlib = require('zlib');
var mime = require('mime');
var crypto = require('crypto');
var minifyHtml = require('html-minifier').minify;
var minifyCSS =  require('clean-css');
var UglifyJS = require('uglify-js');
var watch = require("fwatcher");
var html_minifier_options = {
    removeComments: true,
    removeCommentsFromCDATA: true,
    removeCDATASectionsFromCDATA: true,
    removeAttributeQuotes: true,
    removeRedundantAttributes: true,
    removeEmptyAttributes: true,
    removeOptionalTags: true,
    collapseBooleanAttributes: true,
    collapseWhitespace: true
};

// regular expressions
//var removeFingerprint = /\.[^\.]+\.js$/;
var suffix = /\.\w+$/;
var replaceDoubleSlash = /\/{2,}/g;
var checkFp = /\.@[a-z0-9]{7}\.(?:js|css|html)$/i;

// global file cache
var fileCache = engine.pojo('files');

// this is not quaranteed to be stable! why?
zlib.Z_DEFAULT_COMPRESSION = 9;

/**
 * Read a file or get it from the cache.
 *
 * @public
 * @param {string} The file path.
 * @param {function} The callback function.
 * @param {array} Give an array with allowed paths. (optional)
 * @param {string} A string, which is prepended to a path.
 */
var getFile = exports.get = function getFile (file, callback, index) {

    if (typeof file === 'string') {
        file = {path: file};
    }

    // path must be absolute
    if (!file || !file.path || file.path.indexOf('../') !== -1) {
        var err = new Error('Invalid path.');
        console.error('lib/file.js#51', err.toString());
        return callback(err);
    }

    // set default base path to public app folder
    file.base = file.base || engine.paths.app_public;

    // create a clean path without the fingerprint
    file.clean = removeFingerprint(file.path);

    // create absolute path
    file.read = (file.base + file.clean).replace(replaceDoubleSlash, '/');

    // check if file is already in cache
    var cachedFile = fileCache.get(file.read);
    if (cachedFile) {
        return callback(null, cachedFile, index);
    }

    // check if path had fingerprint
    file.fpInPath = file.fpInPath || (file.clean === file.path ? false : true);

    // get file type
    file.type = mime.lookup(file.clean);

    // read the file from the file system
    fs.readFile(file.read, function (err, data) {

        if (err) {
            console.error('lib/file.js#83', err.toString());
            return callback(err);
        }

        // watch for file changes
        if (cachedFile !== null) {
            watch(file.read, function (err) {
                if (err) {
                    return console.error(err);
                }

                // remove cached data on file change, to force reload
                console.log('FILE CHANGE:', file.read);

                // set file item to null
                fileCache.set(file.read, null);
            });
        }

        // minify js, html or css
        switch (file.type) {
            case 'text/html':

                // TODO don't compress as long html imports or binary ws data is available
                file.noCompression = true;
                data = minifyHtml(data.toString(), html_minifier_options);
                break;

            case 'text/css':
                data = new minifyCSS({processImport: false}).minify(data.toString()).styles;
                break;
            case 'application/javascript':

                // wrap javascript files, except the engine client
                if (file.clean !== 'engine.js') {
                    data = "E('" + ((file.wrap || '')  + file.clean).replace(replaceDoubleSlash, '/') + "',function(require,module,exports,global,engine){\n" + data.toString() + "\nreturn module});";
                }

                if (engine.production && (data = UglifyJS.minify(data.toString(), {fromString: true}))) {
                    data = data.code;
                }
                break;
        }

        // create fingerprint
        file.fp = crypto.createHash('md5').update(data).digest('hex').substr(0, 7);

        // add the data to the file object
        file.data = data;

        // don't compress data
        if (file.noCompression) {
            return createCacheObject(file, callback, index);
        }

        zlib.gzip(file.data, function (err, data) {

            if (err) {
                console.error('lib/file.js#218', err.toString());
                return callback(err);
            }

            // update file data with compressed data
            file.data = data;

            createCacheObject(file, callback, index);
        });
    });
};

/**
 * Create an cache object with the data buffer and the http headers.
 *
 * @private
 * @param {string} The file name without the fingerprint.
 * @param {string} The file path wihtout the fingerprint.
 * @param {blob} The file data.
 * @param {string} The mime type.
 * @param {string} The fingerprint.
 * @param {function} The callback function.
 */
function createCacheObject (file, callback, index) {

    // get the modification time
    fs.stat(file.read, function (err, stats) {

        if (err) {
            console.error('lib/file.js#245', err.toString());
            return callback(err);
        }

        // create http headers
        // TODO send not modified for non scrips and css
        file.http = {
            'Vary': 'Accept-Encoding',
            'Cache-Control': 'public, max-age=' + (file.fpInPath ? engine.http.maxAge_fingerprint : engine.http.maxAge),
            'Content-Encoding': 'gzip',
            'Content-Length': file.data.length,
            'Content-Type': file.type,
            'Last-Modified': stats.mtime,
            'Etag': file.fp
        };

        // TODO don't append fingerprints to the markup until it's loaded via html import
        if (file.type !== 'text/html') {

            // handle files with suffix
            if (suffix.test(file.clean)) {

                file.ext = file.path.split('.');

                // add public file identifier to path
                if (file.ext[0][0] === '/' && file.ext[0][1] !== '/') {
                    file.ext[0] = '/!' + file.ext[0];
                }

                file.ext.splice(file.ext.length - 1, 0, '@' + file.fp);
                file.ext = file.ext.join('.');

            // handle files without suffix
            } else {
                file.ext = file.path + '.' + '@' + file.fp;
            }
        }

        // add module id to module paths
        file.ext = (file.path[0] !== '/' ? file.wrap : '') + (file.ext || file.path);

        // save zipped data in cache
        fileCache.set(file.read, file);

        // return data
        callback(null, file, index);
    });
}

/**
 * Prepare external component file paths.
 *
 * @public
 * @param {object} The load context, ex a module package.
 * @param {function} The callback function.
 */
exports.prepareComponents = function (loadContext, callback) {

    if (!loadContext || !loadContext.components) {
        var err = new Error('Invalid load context.');
        console.error('lib/file.js#227', err.toString());
        return callback(err);
    }

    // check if there are components to load
    if (
        (!loadContext.components.scripts || !loadContext.components.scripts.length) &&
        (!loadContext.components.markup || !loadContext.components.markup.length) &&
        (!loadContext.components.styles || !loadContext.components.styles.length)
    ) {
        return callback(null, loadContext);
    }

    var count = 0;

    // the prepend path for external module resource urls
    var modulePath = loadContext._id  + '/';

    var handler = function (err, file, index) {

        if (err) {
            console.error('lib/file.js#247', err.toString());
            if (--count === 0) {
                callback(null, loadContext);
            }
            return;
        }

        // update module components paths
        if (loadContext.components[file.compType] && loadContext.components[file.compType][index]) {
            loadContext.components[file.compType][index] = file.ext;
        }

        if (--count === 0) {
            callback(null, loadContext);
        }
    }

    for (var type in loadContext.components) {

        // check if type is allowed
        switch (type) {
            case 'scripts':
            case 'markup':
            case 'styles':
                break;
            default:
              continue;
        }

        // get file paths array
        var files = loadContext.components[type];

        // update count
        count += files.length;

        for (var i = 0, file; i < files.length; ++i) {

            // ignore external paths
            if (files[i].indexOf('//') > -1) {
                if (--count === 0) {
                    callback(null, loadContext);
                }
                continue;
            }

            // create file object
            file = {path: files[i]};

            // save component type to update the components later
            file.compType = type;

            // set a longer cache time for fingerprinted files
            file.fpInPath = true;

            // handle absolute files
            if (file.path[0] === '/') {
                file.base = type === 'markup' ? engine.paths.app_markup : engine.paths.app_public;

            // handle module files
            } else {
                file.base = loadContext._base;
                file.wrap = modulePath;
            }

            // read the file
            getFile(file, handler, i);
        }
    }
}

/**f
 * Remove fingerprint from path
 *
 * @private
 * @param {string} The file path.
 */
function removeFingerprint (path) {

    // remove fingerprint if it's found in path
    if (checkFp.test(path)) {

        // split path
        path = path.split('.');

        // get fingerprint and remove fingerprint from read path
        path.splice(path.length - 2, 1)[0];

        // create path without fingerprint
        path = path.join('.');
    }

    // return path
    return path;
}
<|endoftext|>


<commit_before>/**
 * Утилиты для работы с файлами
 */
var fs = require('fs');
var path = require('path');
var glob = require('glob-all');
var async = require('async');
var mkdirp = require('mkdirp');

var utils = require('./common');

/**
 * Читает содержимое файлов, переданных в списке
 * @param  {Array}    list     Список путей к файлам, которые нужно прочитать
 * @param  {Function} callback
 */
function readList(list, callback) {
	async.map(list, function(file, callback) {
		fs.readFile(file, {encoding: 'utf8'}, function(err, content) {
			callback(err, {
				file: file,
				content: content
			});
		});
	}, callback);
}

function absPathList(list, options) {
	if (options && options.cwd) {
		list = list.map(function(p) {
			return path.normalize(path.join(options.cwd, p));
		});
	}

	return list;
}

/**
 * Нормализация указанного файлового объекта
 * @param  {Object} fileObj
 * @return {Object}
 */
function normalizeFiles(fileObj) {
	if (Array.isArray(fileObj)) {
		return {
			files: fileObj,
			options: {}
		};
	}

	if (typeof fileObj === 'object') {
		var options = utils.extend({}, fileObj);
		if ('src' in options) {
			delete options.src;
		}

		return {
			files: Array.isArray(fileObj.src) ? fileObj.src : [fileObj.src],
			options: options
		};
	}

	return {
		files: [fileObj],
		options: {}
	};
}

module.exports = {
	read: function(f, options, callback) {
		if (!Array.isArray(f)) {
			f = [f];
		}

		if (typeof options === 'function') {
			callback = options;
			options = {};
		}

		var output = [];
		async.each(f, function(file, callback) {
			if (file instanceof Buffer) {
				output.push({
					file: null,
					content: file.toString()
				});
				return callback();
			}

			async.waterfall([
				function(callback) {
					glob(file, options, callback)
				},
				function(result, callback) {
					callback(null, absPathList(result, options));
				},
				readList,
				function(content, callback) {
					callback(null, output = output.concat(content));
				}
			], callback);
		}, function(err) {
			callback(err, output);
		});
	},

	/**
	 * Сохраняет содержимое файла
	 * @param  {String}   dest     Абсолютный путь, куда нужно сохранить файл
	 * @param  {String}   content  Содержимое файла
	 * @param  {Function} callback
	 */
	saveFile: function(dest, content, callback) {
		async.waterfall([
			function(callback) {
				mkdirp(path.dirname(dest), callback);
			},
			function(result, callback) {
				fs.writeFile(dest, content, callback);
			}
		], callback);
	},

	/**
	 * Быстрое копирование файлов
	 * @param  {String}   source Откуда копировать файл
	 * @param  {String}   target Куда копировать файл
	 * @param  {Function} callback
	 */
	copy: function(source, target, callback) {
		async.waterfall([
			function(callback) {
				mkdirp(path.dirname(target), callback);
			},
			function(result, callback) {
				var cbCalled = false;
				var done = function(err) {
					if (!cbCalled) {
						callback(err);
						cbCalled = true;
					}
				};

				var rd = fs.createReadStream(source);
				rd.on('error', done);

				var wr = fs.createWriteStream(target);
				wr.on('error', done);
				wr.on('close', function(ex) {
					done();
				});
				rd.pipe(wr);
			}
		], callback);
	}
};<commit_msg>Fixed batch file reader<commit_after>/**
 * Утилиты для работы с файлами
 */
var fs = require('fs');
var path = require('path');
var glob = require('glob-all');
var async = require('async');
var mkdirp = require('mkdirp');

var utils = require('./common');

/**
 * Читает содержимое файлов, переданных в списке
 * @param  {Array}    list     Список путей к файлам, которые нужно прочитать
 * @param  {Function} callback
 */
function readList(list, callback) {
	async.map(list, function(file, callback) {
		fs.readFile(file, {encoding: 'utf8'}, function(err, content) {
			callback(err, {
				file: file,
				content: content
			});
		});
	}, callback);
}

function absPathList(list, options) {
	if (options && options.cwd) {
		list = list.map(function(p) {
			return path.normalize(path.join(options.cwd, p));
		});
	}

	return list;
}

module.exports = {
	/**
	 * Нормализация указанного файлового объекта
	 * @param  {Object} fileObj
	 * @return {Object}
	 */
	normalize: function(fileObj) {
		if (Array.isArray(fileObj)) {
			return {
				files: fileObj,
				options: {}
			};
		}

		if (typeof fileObj === 'object') {
			var options = utils.extend({}, fileObj);
			if ('src' in options) {
				delete options.src;
			}

			return {
				files: Array.isArray(fileObj.src) ? fileObj.src : [fileObj.src],
				options: options
			};
		}

		return {
			files: [fileObj],
			options: {}
		};
	},

	/**
	 * Читает указанный набор файлов.
	 * @param  {Object}   fileObj  Объект, указывающий, какие файлы нужно преобразовать
	 * (см. `this.normalize()`)
	 * @param  {Function} callback
	 */
	read: function(fileObj, callback) {
		fileObj = this.normalize(fileObj);

		var output = [];
		async.each(fileObj.files, function(file, callback) {
			if (file instanceof Buffer) {
				output.push({
					file: null,
					content: file.toString()
				});
				return callback();
			}

			async.waterfall([
				function(callback) {
					glob(file, fileObj.options, callback)
				},
				function(result, callback) {
					callback(null, absPathList(result, fileObj.options));
				},
				readList,
				function(content, callback) {
					callback(null, output = output.concat(content));
				}
			], callback);
		}, function(err) {
			callback(err, output);
		});
	},

	/**
	 * Сохраняет содержимое файла
	 * @param  {String}   dest     Абсолютный путь, куда нужно сохранить файл
	 * @param  {String}   content  Содержимое файла
	 * @param  {Function} callback
	 */
	saveFile: function(dest, content, callback) {
		async.waterfall([
			function(callback) {
				mkdirp(path.dirname(dest), callback);
			},
			function(result, callback) {
				fs.writeFile(dest, content, callback);
			}
		], callback);
	},

	/**
	 * Быстрое копирование файлов
	 * @param  {String}   source Откуда копировать файл
	 * @param  {String}   target Куда копировать файл
	 * @param  {Function} callback
	 */
	copy: function(source, target, callback) {
		async.waterfall([
			function(callback) {
				mkdirp(path.dirname(target), callback);
			},
			function(result, callback) {
				var cbCalled = false;
				var done = function(err) {
					if (!cbCalled) {
						callback(err);
						cbCalled = true;
					}
				};

				var rd = fs.createReadStream(source);
				rd.on('error', done);

				var wr = fs.createWriteStream(target);
				wr.on('error', done);
				wr.on('close', function(ex) {
					done();
				});
				rd.pipe(wr);
			}
		], callback);
	}
};<|endoftext|>