<commit_before>var fs = require('fs')
var glob = require('glob')
var path = require('path')
var validateName = require('validate-npm-package-name')
var npa = require('npm-package-arg')

// more popular packages should go here, maybe?
function isTestPkg (p) {
  return !!p.match(/^(expresso|mocha|tap|coffee-script|coco|streamline)$/)
}

function niceName (n) {
  return n.replace(/^node-|[.-]js$/g, '')
}

function readDeps (test) { return function (cb) {
  fs.readdir('node_modules', function (er, dir) {
    if (er) return cb()
    var deps = {}
    var n = dir.length
    if (n === 0) return cb(null, deps)
    dir.forEach(function (d) {
      if (d.match(/^\./)) return next()
      if (test !== isTestPkg(d))
        return next()

      var dp = path.join(dirname, 'node_modules', d, 'package.json')
      fs.readFile(dp, 'utf8', function (er, p) {
        if (er) return next()
        try { p = JSON.parse(p) }
        catch (e) { return next() }
        if (!p.version) return next()
        deps[d] = config.get('save-exact') ? p.version : config.get('save-prefix') + p.version
        return next()
      })
    })
    function next () {
      if (--n === 0) return cb(null, deps)
    }
  })
}}

var name = package.name || basename
var spec = npa(name)
var scope = config.get('scope')
if (scope) {
  if (scope.charAt(0) !== '@') scope = '@' + scope
  if (spec.scope) {
    name = scope + '/' + spec.name.split('/')[1]
  } else {
    name = scope + '/' + name
  }
}
exports.name =  yes ? name : prompt('name', name, function (data) {
  var its = validateName(data)
  if (its.validForNewPackages) return data
  var er = new Error('Sorry, ' + its.errors.join(' and ') + '.')
  er.notValid = true
  return er
})

var version = package.version ||
              config.get('init.version') ||
              config.get('init-version') ||
              '1.0.0'
exports.version = yes ? version : prompt('version', version)

if (!package.description) {
  exports.description = yes ? '' : prompt('description')
}

if (!package.main) {
  exports.main = function (cb) {
    fs.readdir(dirname, function (er, f) {
      if (er) f = []

      f = f.filter(function (f) {
        return f.match(/\.js$/)
      })

      if (f.indexOf('index.js') !== -1)
        f = 'index.js'
      else if (f.indexOf('main.js') !== -1)
        f = 'main.js'
      else if (f.indexOf(basename + '.js') !== -1)
        f = basename + '.js'
      else
        f = f[0]

      var index = f || 'index.js'
      return cb(null, yes ? index : prompt('entry point', index))
    })
  }
}

if (!package.bin) {
  exports.bin = function (cb) {
    fs.readdir(path.resolve(dirname, 'bin'), function (er, d) {
      // no bins
      if (er) return cb()
      // just take the first js file we find there, or nada
      return cb(null, d.filter(function (f) {
        return f.match(/\.js$/)
      })[0])
    })
  }
}

exports.directories = function (cb) {
  fs.readdir(dirname, function (er, dirs) {
    if (er) return cb(er)
    var res = {}
    dirs.forEach(function (d) {
      switch (d) {
        case 'example': case 'examples': return res.example = d
        case 'test': case 'tests': return res.test = d
        case 'doc': case 'docs': return res.doc = d
        case 'man': return res.man = d
      }
    })
    if (Object.keys(res).length === 0) res = undefined
    return cb(null, res)
  })
}

if (!package.dependencies) {
  exports.dependencies = readDeps(false)
}

if (!package.devDependencies) {
  exports.devDependencies = readDeps(true)
}

// MUST have a test script!
var s = package.scripts || {}
var notest = 'echo "Error: no test specified" && exit 1'
if (!package.scripts) {
  exports.scripts = function (cb) {
    fs.readdir(path.join(dirname, 'node_modules'), function (er, d) {
      setupScripts(d || [], cb)
    })
  }
}
function setupScripts (d, cb) {
  // check to see what framework is in use, if any
  function tx (test) {
    return test || notest
  }
  if (!s.test || s.test === notest) {
    var commands = {
      'tap':'tap test/*.js'
    , 'expresso':'expresso test'
    , 'mocha':'mocha'
    }
    var command
    Object.keys(commands).forEach(function (k) {
      if (d.indexOf(k) !== -1) command = commands[k]
    })
    var ps = 'test command'
    if (yes) {
      s.test = command || notest
    } else {
      s.test = command ? prompt(ps, command, tx) : prompt(ps, tx)
    }
  }
  return cb(null, s)
}

if (!package.repository) {
  exports.repository = function (cb) {
    fs.readFile('.git/config', 'utf8', function (er, gconf) {
      if (er || !gconf) {
        return cb(null, yes ? '' : prompt('git repository'))
      }
      gconf = gconf.split(/\r?\n/)
      var i = gconf.indexOf('[remote "origin"]')
      if (i !== -1) {
        var u = gconf[i + 1]
        if (!u.match(/^\s*url =/)) u = gconf[i + 2]
        if (!u.match(/^\s*url =/)) u = null
        else u = u.replace(/^\s*url = /, '')
      }
      if (u && u.match(/^git@github.com:/))
        u = u.replace(/^git@github.com:/, 'https://github.com/')

      return cb(null, yes ? u : prompt('git repository', u))
    })
  }
}

if (!package.keywords) {
  exports.keywords = yes ? '' : prompt('keywords', function (s) {
    if (!s) return undefined
    if (Array.isArray(s)) s = s.join(' ')
    if (typeof s !== 'string') return s
    return s.split(/[\s,]+/)
  })
}

if (!package.author) {
  exports.author = config.get('init.author.name') ||
                   config.get('init-author-name')
  ? {
      "name" : config.get('init.author.name') ||
               config.get('init-author-name'),
      "email" : config.get('init.author.email') ||
                config.get('init-author-email'),
      "url" : config.get('init.author.url') ||
              config.get('init-author-url')
    }
  : yes ? '' : prompt('author')
}

var license = package.license ||
              config.get('init.license') ||
              config.get('init-license') ||
              'ISC'
exports.license = yes ? license : prompt('license', license)
<commit_msg>Concatenate error/warning message while validating name<commit_after>var fs = require('fs')
var glob = require('glob')
var path = require('path')
var validateName = require('validate-npm-package-name')
var npa = require('npm-package-arg')

// more popular packages should go here, maybe?
function isTestPkg (p) {
  return !!p.match(/^(expresso|mocha|tap|coffee-script|coco|streamline)$/)
}

function niceName (n) {
  return n.replace(/^node-|[.-]js$/g, '')
}

function readDeps (test) { return function (cb) {
  fs.readdir('node_modules', function (er, dir) {
    if (er) return cb()
    var deps = {}
    var n = dir.length
    if (n === 0) return cb(null, deps)
    dir.forEach(function (d) {
      if (d.match(/^\./)) return next()
      if (test !== isTestPkg(d))
        return next()

      var dp = path.join(dirname, 'node_modules', d, 'package.json')
      fs.readFile(dp, 'utf8', function (er, p) {
        if (er) return next()
        try { p = JSON.parse(p) }
        catch (e) { return next() }
        if (!p.version) return next()
        deps[d] = config.get('save-exact') ? p.version : config.get('save-prefix') + p.version
        return next()
      })
    })
    function next () {
      if (--n === 0) return cb(null, deps)
    }
  })
}}

var name = package.name || basename
var spec = npa(name)
var scope = config.get('scope')
if (scope) {
  if (scope.charAt(0) !== '@') scope = '@' + scope
  if (spec.scope) {
    name = scope + '/' + spec.name.split('/')[1]
  } else {
    name = scope + '/' + name
  }
}
exports.name =  yes ? name : prompt('name', name, function (data) {
  var its = validateName(data)
  if (its.validForNewPackages) return data
  var errors = [].concat(its.errors || []).concat(its.warnings || [])
  var er = new Error('Sorry, ' + errors.join(' and ') + '.')
  er.notValid = true
  return er
})

var version = package.version ||
              config.get('init.version') ||
              config.get('init-version') ||
              '1.0.0'
exports.version = yes ? version : prompt('version', version)

if (!package.description) {
  exports.description = yes ? '' : prompt('description')
}

if (!package.main) {
  exports.main = function (cb) {
    fs.readdir(dirname, function (er, f) {
      if (er) f = []

      f = f.filter(function (f) {
        return f.match(/\.js$/)
      })

      if (f.indexOf('index.js') !== -1)
        f = 'index.js'
      else if (f.indexOf('main.js') !== -1)
        f = 'main.js'
      else if (f.indexOf(basename + '.js') !== -1)
        f = basename + '.js'
      else
        f = f[0]

      var index = f || 'index.js'
      return cb(null, yes ? index : prompt('entry point', index))
    })
  }
}

if (!package.bin) {
  exports.bin = function (cb) {
    fs.readdir(path.resolve(dirname, 'bin'), function (er, d) {
      // no bins
      if (er) return cb()
      // just take the first js file we find there, or nada
      return cb(null, d.filter(function (f) {
        return f.match(/\.js$/)
      })[0])
    })
  }
}

exports.directories = function (cb) {
  fs.readdir(dirname, function (er, dirs) {
    if (er) return cb(er)
    var res = {}
    dirs.forEach(function (d) {
      switch (d) {
        case 'example': case 'examples': return res.example = d
        case 'test': case 'tests': return res.test = d
        case 'doc': case 'docs': return res.doc = d
        case 'man': return res.man = d
      }
    })
    if (Object.keys(res).length === 0) res = undefined
    return cb(null, res)
  })
}

if (!package.dependencies) {
  exports.dependencies = readDeps(false)
}

if (!package.devDependencies) {
  exports.devDependencies = readDeps(true)
}

// MUST have a test script!
var s = package.scripts || {}
var notest = 'echo "Error: no test specified" && exit 1'
if (!package.scripts) {
  exports.scripts = function (cb) {
    fs.readdir(path.join(dirname, 'node_modules'), function (er, d) {
      setupScripts(d || [], cb)
    })
  }
}
function setupScripts (d, cb) {
  // check to see what framework is in use, if any
  function tx (test) {
    return test || notest
  }
  if (!s.test || s.test === notest) {
    var commands = {
      'tap':'tap test/*.js'
    , 'expresso':'expresso test'
    , 'mocha':'mocha'
    }
    var command
    Object.keys(commands).forEach(function (k) {
      if (d.indexOf(k) !== -1) command = commands[k]
    })
    var ps = 'test command'
    if (yes) {
      s.test = command || notest
    } else {
      s.test = command ? prompt(ps, command, tx) : prompt(ps, tx)
    }
  }
  return cb(null, s)
}

if (!package.repository) {
  exports.repository = function (cb) {
    fs.readFile('.git/config', 'utf8', function (er, gconf) {
      if (er || !gconf) {
        return cb(null, yes ? '' : prompt('git repository'))
      }
      gconf = gconf.split(/\r?\n/)
      var i = gconf.indexOf('[remote "origin"]')
      if (i !== -1) {
        var u = gconf[i + 1]
        if (!u.match(/^\s*url =/)) u = gconf[i + 2]
        if (!u.match(/^\s*url =/)) u = null
        else u = u.replace(/^\s*url = /, '')
      }
      if (u && u.match(/^git@github.com:/))
        u = u.replace(/^git@github.com:/, 'https://github.com/')

      return cb(null, yes ? u : prompt('git repository', u))
    })
  }
}

if (!package.keywords) {
  exports.keywords = yes ? '' : prompt('keywords', function (s) {
    if (!s) return undefined
    if (Array.isArray(s)) s = s.join(' ')
    if (typeof s !== 'string') return s
    return s.split(/[\s,]+/)
  })
}

if (!package.author) {
  exports.author = config.get('init.author.name') ||
                   config.get('init-author-name')
  ? {
      "name" : config.get('init.author.name') ||
               config.get('init-author-name'),
      "email" : config.get('init.author.email') ||
                config.get('init-author-email'),
      "url" : config.get('init.author.url') ||
              config.get('init-author-url')
    }
  : yes ? '' : prompt('author')
}

var license = package.license ||
              config.get('init.license') ||
              config.get('init-license') ||
              'ISC'
exports.license = yes ? license : prompt('license', license)
<|endoftext|>


<commit_before>(function () {
    'use strict';
    angular.module('Tombola.Games.Bingo90.Core')

        .controller('MainController', ['$scope','LoginApi','gameApi','LoginProxy',  function($scope, loginApi, loginProxy) {
            $scope.gameTitle = 'tombola';
            $scope.model = loginProxy;

            $scope.login = function (){
                loginApi.loginButton($scope.username, $scope.password);
            };

            $scope.nextGame = function (){
                gameApi.nextButton($scope.model.playerToken);
                console.log($scope.model.playerToken);
            };

        }]);
})();<commit_msg>Working on injection error<commit_after>(function () {
    'use strict';
    angular.module('Tombola.Games.Bingo90.Core')

        .controller('MainController', ['$scope','LoginApi','gameApi','LoginProxy',  function($scope, loginApi, loginProxy) {
            $scope.gameTitle = 'tombola';
            $scope.model = loginProxy;

            $scope.login = function (){
                loginApi.loginButton($scope.username, $scope.password);
            };

            $scope.nextGame = function (){
                gameApi.nextButton($scope.model.playerToken);
                console.log($scope.model.playerToken);
            };

        }]);
})();<|endoftext|>


<commit_before>serveRSS = function() {
  var feed = new RSS({
    title: getSetting('title'),
    description: getSetting('tagline'),
    feed_url: Meteor.absoluteUrl()+'feed.xml',
    site_url: Meteor.absoluteUrl(),
    image_url: Meteor.absoluteUrl()+'img/favicon.png',
  });

  Posts.find({status: STATUS_APPROVED}, {sort: {submitted: -1}, limit: 20}).forEach(function(post) {
    feed.item({
     title: post.headline,
     description: post.body+'

 Comments',
     author: post.author,
     date: post.submitted,
     url: (post.url ? getOutgoingUrl(post.url) : getPostUrl(post._id)),
     guid: post._id
    });
  });

  return feed.xml();
}
<commit_msg> RSS Feed에서 category가 isModerator인 것들은 제외.<commit_after>serveRSS = function() {
  var feed = new RSS({
    title: getSetting('title'),
    description: getSetting('tagline'),
    feed_url: Meteor.absoluteUrl()+'feed.xml',
    site_url: Meteor.absoluteUrl(),
    image_url: Meteor.absoluteUrl()+'img/favicon.png'
  });

  Posts.find({status: STATUS_APPROVED, categories:{$not:{$elemMatch:{isModerator:true}}}}, {sort: {submitted: -1}, limit: 20}).forEach(function(post) {
    feed.item({
     title: post.headline,
     description: post.body+'

 Comments',
     author: post.author,
     date: post.submitted,
     url: (post.url ? getOutgoingUrl(post.url) : getPostUrl(post._id)),
     guid: post._id
    });
  });

  return feed.xml();
}
<|endoftext|>


<commit_before>var fs = require('fs');
var os = require('os');
var generator = require('yeoman-generator');
var ejs = require('ejs');
var is = {
  macos: os.platform() === 'darwin',
  linux: os.platform() === 'linux',
  windows: os.platform() === 'win32'
};

module.exports = generator.Base.extend({
  prompting: function () {
    var done = this.async();

    this.prompt([{
      type    : 'input',
      name    : 'name',
      message : 'Name of project for Cordova',
      default : this.appname // Default to current folder name
    }, {
      type    : 'input',
      name    : 'id',
      message : 'ID of project for Cordova',
      default: 'com.donejs.' + this.appname.replace(/[\. ,:-]+/g, "")
    }, {
      type: 'checkbox',
      name: 'platforms',
      message: 'What platforms would you like to support (needs SDK installed)',
      choices: [{
        name: 'ios',
        checked: is.macos,
        disabled: !is.macos
      }, {
        name: 'android'
      }, {
        name: 'wp8',
        checked: is.windows,
        disabled: !is.windows
      }, {
        name: 'windows',
        checked: is.windows,
        disabled: !is.windows
      }, {
        name: 'amazon-fireos'
      }, {
        name: 'blackberry10'
      }, {
        name: 'Firefox OS'
      }, {
        name: 'Ubuntu',
        checked: is.linux,
        disabled: !is.linux
      }, {
        name: 'tizen'
      }]
    }], function (answers) {
      this.config.set('name', answers.name);
      this.config.set('id', answers.id);
      this.config.set('platforms', answers.platforms);
      done();
    }.bind(this));
  },
  installingStealCordova: function() {
    this.npmInstall(['steal-cordova'], { 'saveDev': true });
  },
  writing: function () {
    var done = this.async();
    var outputBuildjs = this.destinationPath('build.js');

    var context = {
      name: this.config.get('name'),
      id: this.config.get('id'),
      platforms: this.config.get('platforms')
    };

    if (!this.fs.exists(outputBuildjs)) {
      this.fs.copyTpl(
        this.templatePath('build.ejs'),
        outputBuildjs,
        context
      );
      done();
    } else {
      fs.readFile(outputBuildjs, 'utf8', function(err, data) {
        var commentStartText = this.fs.read(this.templatePath('commentStart.ejs'), 'utf8'),
            commentEndText = this.fs.read(this.templatePath('commentEnd.ejs'), 'utf8'),
            cordovaOptionsText = this.fs.read(this.templatePath('cordovaOptions.ejs'), 'utf8'),
            commentStartIndex = data.indexOf(commentStartText),
            commentEndIndex = data.indexOf(commentEndText),
            newContent;

        if (commentStartIndex < 0 && commentEndIndex < 0) {
          // add nwOptions
          newContent = data +
            ejs.render(commentStartText, context) +
            ejs.render(cordovaOptionsText, context) +
            ejs.render(commentEndText, context);
        } else {
          // replace existing nwOptions
          newContent = data.substring(data, commentStartIndex) +
            ejs.render(commentStartText, context) +
            ejs.render(cordovaOptionsText, context) +
            ejs.render(commentEndText, context) +
            data.substring(commentEndIndex + commentEndText.length);
        }

        fs.writeFile(outputBuildjs, newContent, done);
      }.bind(this));
    }
  }
});
<commit_msg>removing platforms other than ios and android<commit_after>var fs = require('fs');
var os = require('os');
var generator = require('yeoman-generator');
var ejs = require('ejs');
var is = {
  macos: os.platform() === 'darwin',
  linux: os.platform() === 'linux',
  windows: os.platform() === 'win32'
};

module.exports = generator.Base.extend({
  prompting: function () {
    var done = this.async();

    this.prompt([{
      type    : 'input',
      name    : 'name',
      message : 'Name of project for Cordova',
      default : this.appname // Default to current folder name
    }, {
      type    : 'input',
      name    : 'id',
      message : 'ID of project for Cordova',
      default: 'com.donejs.' + this.appname.replace(/[\. ,:-]+/g, "")
    }, {
      type: 'checkbox',
      name: 'platforms',
      message: 'What platforms would you like to support (needs SDK installed)',
      choices: [{
        name: 'ios',
        checked: is.macos,
        disabled: !is.macos
      }, {
        name: 'android'
      }]
    }], function (answers) {
      this.config.set('name', answers.name);
      this.config.set('id', answers.id);
      this.config.set('platforms', answers.platforms);
      done();
    }.bind(this));
  },
  installingStealCordova: function() {
    this.npmInstall(['steal-cordova'], { 'saveDev': true });
  },
  writing: function () {
    var done = this.async();
    var outputBuildjs = this.destinationPath('build.js');

    var context = {
      name: this.config.get('name'),
      id: this.config.get('id'),
      platforms: this.config.get('platforms')
    };

    if (!this.fs.exists(outputBuildjs)) {
      this.fs.copyTpl(
        this.templatePath('build.ejs'),
        outputBuildjs,
        context
      );
      done();
    } else {
      fs.readFile(outputBuildjs, 'utf8', function(err, data) {
        var commentStartText = this.fs.read(this.templatePath('commentStart.ejs'), 'utf8'),
            commentEndText = this.fs.read(this.templatePath('commentEnd.ejs'), 'utf8'),
            cordovaOptionsText = this.fs.read(this.templatePath('cordovaOptions.ejs'), 'utf8'),
            commentStartIndex = data.indexOf(commentStartText),
            commentEndIndex = data.indexOf(commentEndText),
            newContent;

        if (commentStartIndex < 0 && commentEndIndex < 0) {
          // add nwOptions
          newContent = data +
            ejs.render(commentStartText, context) +
            ejs.render(cordovaOptionsText, context) +
            ejs.render(commentEndText, context);
        } else {
          // replace existing nwOptions
          newContent = data.substring(data, commentStartIndex) +
            ejs.render(commentStartText, context) +
            ejs.render(cordovaOptionsText, context) +
            ejs.render(commentEndText, context) +
            data.substring(commentEndIndex + commentEndText.length);
        }

        fs.writeFile(outputBuildjs, newContent, done);
      }.bind(this));
    }
  }
});
<|endoftext|>


<commit_before>oscar.Control.MeasurementTools = oscar
		.BaseClass(
				oscar.Control.MultiControl,
				{
					autoActivate : true,

					/**
					 * Property: defaultUnit {String} The default display unit
					 * of the measurement. Set to metric.
					 */
					defaultUnit : 'metric',

					/**
					 * Property: currentUnit {String} The current display unit.
					 */
					currentUnit : null,

					/**
					 * Property: popup
					 */
					popup : null,

					sketchSymbolizers : {
						"Point" : {
							pointRadius : 4,
							graphicName : "square",
							fillColor : "white",
							fillOpacity : 1,
							strokeWidth : 1,
							strokeOpacity : 1,
							strokeColor : "#333333"
						},
						"Line" : {
							strokeWidth : 3,
							strokeOpacity : 1,
							strokeColor : "#f00",
							strokeDashstyle : "solid"
						},
						"Polygon" : {
							strokeWidth : 2,
							strokeOpacity : 1,
							strokeColor : "#f00",
							fillColor : "white",
							fillOpacity : 0.3
						}
					},
					initialize : function(options) {
						oscar.Control.MultiControl.prototype.initialize.apply(
								this, [ options ]);

						// Setup the sketchSymbolisers
						if (options && options.sketchSymbolizers) {
							for ( var key in this.sketchSymbolizers) {
								this._setupSketchSymbolizers(
										this.sketchSymbolizers[key],
										options.sketchSymbolizers[key]);
							}
						}
						this.style = new OpenLayers.Style();
						this.style.addRules([ new OpenLayers.Rule({
							symbolizer : this.sketchSymbolizers
						}) ]);
						this.styleMap = new OpenLayers.StyleMap({
							"default" : this.style
						});

						this.controls = {
							line : new OpenLayers.Control.Measure(
									OpenLayers.Handler.Path, {
										persist : true,
										handlerOptions : {
											layerOptions : {
												styleMap : this.styleMap
											}
										}
									}, {
										displaySystem : this.defaultUnit
									}),
							polygon : new OpenLayers.Control.Measure(
									OpenLayers.Handler.Polygon, {
										persist : true,
										handlerOptions : {
											layerOptions : {
												styleMap : this.styleMap
											}
										}
									}, {
										displaySystem : this.defaultUnit
									})
						};
						this.controls.line.events.includeXY = true;
					},
					draw : function(options) {
						var scope = this;
						oscar.Control.MultiControl.prototype.draw.apply(this,
								[ options ]);

						var line = $$("

");
						line.addClass("subTool");
						line.addClass("line");
						line.data("tool", "line");
						this.addMuliControl(line);
						var polygon = $$("

");
						polygon.addClass("subTool");
						polygon.addClass("polygon");
						polygon.data("tool", "polygon");

						this.addMuliControl(polygon);

						this._createUnits();

						return this.div;
					},

					/**
					 * Method: _createUnits
					 *
					 * Description: This method creates the dropdown list for
					 * the available units.
					 */

					_createUnits : function() {
						var units = [ 'english', 'metric' ];
						var container = document.createElement("span");
						oscar.jQuery(container).css("float", "left");
						oscar.jQuery(container)
								.css("background", "transparent");
						oscar.jQuery(container).css("display", "block");
						oscar.jQuery(container).css("padding-top", "7px");

						var select = document.createElement("select");
						select.id = "oscarMeasureUnits";
						oscar.jQuery(select).addClass("measurementUnits");
						var option = document.createElement("option");
						select.options[select.options.length]

						for ( var unit = 0; unit < units.length; unit++) {
							var option = document.createElement("option");
							select.options[select.options.length]
							option.value = units[unit];
							option.text = oscar.i18n(units[unit]);
							if (units[unit] == this.defaultUnit)
								option.selected = true;
							select.options[select.options.length] = option;
						}
						var scope = this;

						$$(select).change(function(evt) {
							scope.changeUnits();
						});

						$$(container).append($$(select));
						$$(this.div).append($$(container));
					},
					/**
					 * Method: changeUnits This method is called when there is a
					 * change in units drop down menu and updates the current
					 * units
					 *
					 * Parameters: evt - {<OpenLayers.Event>}
					 */

					changeUnits : function(evt) {
						var select = $('oscarMeasureUnits');
						unit = select.options[select.selectedIndex].value;

						if (unit == -1)
							return;
						this.currentUnit = unit;
						if (this.activeControl)
							this.activeControl.displaySystem = unit;

					},

					activate : function() {
						oscar.Control.MultiControl.prototype.activate
								.apply(this);
						var control;
						for ( var key in this.controls) {
							control = this.controls[key];
							control.events.on({
								"measure" : this.handleMeasurements,
								"measurepartial" : this.handleMeasurements,
								scope : this
							});
							this.map.addControl(control);
						}
					},
					deactivate : function() {
						if (this.popup) {
							this.map.removePopup(this.popup);
						}
						var control;
						for ( var key in this.controls) {
							control = this.controls[key];

							control.events.un({
								"measure" : this.handleMeasurements,
								"measurepartial" : this.handleMeasurements,
								scope : this
							});
							control.deactivate();
							this.map.removeControl(control);
						}
						oscar.Control.MultiControl.prototype.deactivate
								.apply(this);

					},
					/**
					 * Method: _setupSketchSymbolizers This method will setup
					 * the customise sketch symbolisers.
					 *
					 * Parameter: defaultSketchSymbolizersOpts - an object to
					 * represent the default sketch symbolisers options that are
					 * defined in the Measure classes. sketchSymbolizersOpts -
					 * an object that represent the new customise sketch
					 * symbolisers, and they will replace the default sketch
					 * symbolisers.
					 */
					_setupSketchSymbolizers : function(
							defaultSketchSymbolisersOpts, sketchSymbolisersOpts) {
						if (defaultSketchSymbolisersOpts
								&& sketchSymbolisersOpts) {
							OpenLayers.Util.extend(
									defaultSketchSymbolisersOpts,
									sketchSymbolisersOpts);
						}
					},
					/**
					 * Method: handleMeasurements This method displays the
					 * measurement on screen.
					 *
					 * Parameters: event - {Object}
					 */
					handleMeasurements : function(event) {
						var geometry = event.geometry;
						var point = new OpenLayers.Geometry.Point(0, 0);
						if (geometry.id
								.indexOf("OpenLayers.Geometry.LineString") > -1) {
							var components = geometry.components;
							point = components[components.length - 1];
						} else { // it's a polygon
							var components = geometry.components[0].components;
							point = components[components.length - 2];
						}

						if (this.popup) {
							this.map.removePopup(this.popup);
						}
						var lonlat = new OpenLayers.LonLat(point.x, point.y);
						var units = event.units;
						var order = event.order;
						var measure = event.measure;
						var element = document.getElementById('measureInfo');
						var out = "";
						if (measure.toFixed(2) == 0.00) {
							return;
						}

						if (order == 1) {
							out += measure.toFixed(2) + " " + units;
						} else {
							out += measure.toFixed(2) + " " + units
									+ "2</" + "sup>";
						}

						this.popup = new oscar.FramedCloud("id", lonlat, null,
								out, null, true);
						this.popup.autoSize = true;
						this.map.addPopup(this.popup);
					},
					CLASS_NAME : "oscar.Control.MeasurementTools"
				});<commit_msg>SFV-1368<commit_after>oscar.Control.MeasurementTools = oscar
		.BaseClass(
				oscar.Control.MultiControl,
				{
					autoActivate : true,

					/**
					 * Property: defaultUnit {String} The default display unit
					 * of the measurement. Set to metric.
					 */
					defaultUnit : 'metric',

					/**
					 * Property: currentUnit {String} The current display unit.
					 */
					currentUnit : null,

					/**
					 * Property: popup
					 */
					popup : null,

					sketchSymbolizers : {
						"Point" : {
							pointRadius : 4,
							graphicName : "square",
							fillColor : "white",
							fillOpacity : 1,
							strokeWidth : 1,
							strokeOpacity : 1,
							strokeColor : "#333333"
						},
						"Line" : {
							strokeWidth : 3,
							strokeOpacity : 1,
							strokeColor : "#f00",
							strokeDashstyle : "solid"
						},
						"Polygon" : {
							strokeWidth : 2,
							strokeOpacity : 1,
							strokeColor : "#f00",
							fillColor : "white",
							fillOpacity : 0.3
						}
					},
					initialize : function(options) {
						oscar.Control.MultiControl.prototype.initialize.apply(
								this, [ options ]);

						// Setup the sketchSymbolisers
						if (options && options.sketchSymbolizers) {
							for ( var key in this.sketchSymbolizers) {
								this._setupSketchSymbolizers(
										this.sketchSymbolizers[key],
										options.sketchSymbolizers[key]);
							}
						}
						this.style = new OpenLayers.Style();
						this.style.addRules([ new OpenLayers.Rule({
							symbolizer : this.sketchSymbolizers
						}) ]);
						this.styleMap = new OpenLayers.StyleMap({
							"default" : this.style
						});

						this.controls = {
							line : new OpenLayers.Control.Measure(
									OpenLayers.Handler.Path, {
										persist : true,
										handlerOptions : {
											layerOptions : {
												styleMap : this.styleMap
											}
										}
									}, {
										displaySystem : this.defaultUnit
									}),
							polygon : new OpenLayers.Control.Measure(
									OpenLayers.Handler.Polygon, {
										persist : true,
										handlerOptions : {
											layerOptions : {
												styleMap : this.styleMap
											}
										}
									}, {
										displaySystem : this.defaultUnit
									})
						};
						this.controls.line.events.includeXY = true;
					},
					draw : function(options) {
						var scope = this;
						oscar.Control.MultiControl.prototype.draw.apply(this,
								[ options ]);

						var line = $$("

");
						line.addClass("subTool");
						line.addClass("line");
						line.data("tool", "line");
						this.addMuliControl(line);
						var polygon = $$("

");
						polygon.addClass("subTool");
						polygon.addClass("polygon");
						polygon.data("tool", "polygon");

						this.addMuliControl(polygon);

						this._createUnits();

						return this.div;
					},

					/**
					 * Method: _createUnits
					 *
					 * Description: This method creates the dropdown list for
					 * the available units.
					 */

					_createUnits : function() {
						var units = [ 'english', 'metric' ];
						var container = document.createElement("span");
						oscar.jQuery(container).css("float", "left");
						oscar.jQuery(container)
								.css("background", "transparent");
						oscar.jQuery(container).css("display", "block");
						oscar.jQuery(container).css("padding-top", "7px");

						var select = document.createElement("select");
						select.id = "oscarMeasureUnits";
						oscar.jQuery(select).addClass("measurementUnits");
						var option = document.createElement("option");
						select.options[select.options.length]

						for ( var unit = 0; unit < units.length; unit++) {
							var option = document.createElement("option");
							select.options[select.options.length]
							option.value = units[unit];
							option.text = oscar.i18n(units[unit]);
							if (units[unit] == this.defaultUnit)
								option.selected = true;
							select.options[select.options.length] = option;
						}
						var scope = this;

						$$(select).change(function(evt) {
							scope.changeUnits();
						});

						$$(container).append($$(select));
						$$(this.div).append($$(container));
					},
					/**
					 * Method: changeUnits This method is called when there is a
					 * change in units drop down menu and updates the current
					 * units
					 *
					 * Parameters: evt - {<OpenLayers.Event>}
					 */

					changeUnits : function(evt) {
						var select = $('oscarMeasureUnits');
						unit = select.options[select.selectedIndex].value;

						if (unit == -1)
							return;
						this.currentUnit = unit;

						for ( var key in this.controls) {
							this.controls[key].displaySystem = unit;
						}

					},

					activate : function() {
						oscar.Control.MultiControl.prototype.activate
								.apply(this);
						var control;
						for ( var key in this.controls) {
							control = this.controls[key];
							control.events.on({
								"measure" : this.handleMeasurements,
								"measurepartial" : this.handleMeasurements,
								scope : this
							});
							this.map.addControl(control);
						}
					},
					deactivate : function() {
						if (this.popup) {
							this.map.removePopup(this.popup);
						}
						var control;
						for ( var key in this.controls) {
							control = this.controls[key];

							control.events.un({
								"measure" : this.handleMeasurements,
								"measurepartial" : this.handleMeasurements,
								scope : this
							});
							control.deactivate();
							this.map.removeControl(control);
						}
						oscar.Control.MultiControl.prototype.deactivate
								.apply(this);

					},
					/**
					 * Method: _setupSketchSymbolizers This method will setup
					 * the customise sketch symbolisers.
					 *
					 * Parameter: defaultSketchSymbolizersOpts - an object to
					 * represent the default sketch symbolisers options that are
					 * defined in the Measure classes. sketchSymbolizersOpts -
					 * an object that represent the new customise sketch
					 * symbolisers, and they will replace the default sketch
					 * symbolisers.
					 */
					_setupSketchSymbolizers : function(
							defaultSketchSymbolisersOpts, sketchSymbolisersOpts) {
						if (defaultSketchSymbolisersOpts
								&& sketchSymbolisersOpts) {
							OpenLayers.Util.extend(
									defaultSketchSymbolisersOpts,
									sketchSymbolisersOpts);
						}
					},
					/**
					 * Method: handleMeasurements This method displays the
					 * measurement on screen.
					 *
					 * Parameters: event - {Object}
					 */
					handleMeasurements : function(event) {
						var geometry = event.geometry;
						var point = new OpenLayers.Geometry.Point(0, 0);
						if (geometry.id
								.indexOf("OpenLayers.Geometry.LineString") > -1) {
							var components = geometry.components;
							point = components[components.length - 1];
						} else { // it's a polygon
							var components = geometry.components[0].components;
							point = components[components.length - 2];
						}

						if (this.popup) {
							this.map.removePopup(this.popup);
						}
						var lonlat = new OpenLayers.LonLat(point.x, point.y);
						var units = event.units;
						var order = event.order;
						var measure = event.measure;
						var element = document.getElementById('measureInfo');
						var out = "";
						if (measure.toFixed(2) == 0.00) {
							return;
						}

						if (order == 1) {
							out += measure.toFixed(2) + " " + units;
						} else {
							out += measure.toFixed(2) + " " + units
									+ "2</" + "sup>";
						}

						this.popup = new oscar.FramedCloud("id", lonlat, null,
								out, null, true);
						this.popup.autoSize = true;
						this.map.addPopup(this.popup);
					},
					CLASS_NAME : "oscar.Control.MeasurementTools"
				});<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var bench = require( '@stdlib/bench' );
var randu = require( '@stdlib/random/base/randu' );
var Float64Array = require( '@stdlib/array/float64' );
var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' );
var pkg = require( './../package.json' ).name;
var array = require( './../lib' );

// MAIN //

bench( pkg+'::1d,instantiation,linear_buffer', function benchmark( b ) {
	var out;
	var arr;
	var i;

	arr = new Float64Array( [ 1.0, 2.0, 3.0 ] );

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		arr[ 0 ] = randu();
		out = array( arr );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});
<commit_msg>Update benchmarks<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var bench = require( '@stdlib/bench' );
var Float64Array = require( '@stdlib/array/float64' );
var isndarrayLike = require( '@stdlib/assert/is-ndarray-like' );
var pkg = require( './../package.json' ).name;
var array = require( './../lib' );

// MAIN //

bench( pkg+'::1d,instantiation', function benchmark( b ) {
	var out;
	var arr;
	var i;

	arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		out = array( arr );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::1d,instantiation,no_cast', function benchmark( b ) {
	var opts;
	var out;
	var arr;
	var i;

	arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
	opts = {
		'dtype': 'float64'
	};

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		out = array( arr, opts );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::1d,instantiation,cast', function benchmark( b ) {
	var opts;
	var out;
	var arr;
	var i;

	arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
	opts = {
		'dtype': 'float32'
	};

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		out = array( arr, opts );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::1d,instantiation:copy=false', function benchmark( b ) {
	var opts;
	var out;
	var arr;
	var i;

	arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
	opts = {
		'copy': false
	};

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		out = array( arr, opts );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::1d,instantiation:copy=true', function benchmark( b ) {
	var opts;
	var out;
	var arr;
	var i;

	arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
	opts = {
		'copy': true
	};

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		out = array( arr, opts );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::1d,instantiation:codegen=false', function benchmark( b ) {
	var opts;
	var out;
	var arr;
	var i;

	arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
	opts = {
		'codegen': false
	};

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		out = array( arr, opts );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::1d,instantiation:codegen=true', function benchmark( b ) {
	var opts;
	var out;
	var arr;
	var i;

	arr = new Float64Array( [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ] );
	opts = {
		'codegen': true
	};

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		out = array( arr, opts );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::1d,instantiation:dtype=generic', function benchmark( b ) {
	var opts;
	var out;
	var arr;
	var i;

	arr = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ];
	opts = {
		'dtype': 'generic'
	};

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		out = array( arr, opts );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::1d,instantiation:dtype=generic,flatten=true', function benchmark( b ) {
	var opts;
	var out;
	var arr;
	var i;

	arr = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ];
	opts = {
		'dtype': 'generic',
		'flatten': true
	};

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		out = array( arr, opts );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});

bench( pkg+'::1d,instantiation:dtype=generic,flatten=false', function benchmark( b ) {
	var opts;
	var out;
	var arr;
	var i;

	arr = [ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 ];
	opts = {
		'dtype': 'generic',
		'flatten': false
	};

	b.tic();
	for ( i = 0; i < b.iterations; i++ ) {
		out = array( arr, opts );
		if ( typeof out !== 'object' ) {
			b.fail( 'should return an object' );
		}
	}
	b.toc();
	if ( !isndarrayLike( out ) ) {
		b.fail( 'should return an ndarray' );
	}
	b.pass( 'benchmark finished' );
	b.end();
});
<|endoftext|>


<commit_before>const PLAYER_MAX_HEALTH = 3;
const PLAYER_FALL_SPEED_LIMIT = 1000;
const PLAYER_VELOCITY = 300;
const PLAYER_JUMP_VELOCITY = 300;
const PLAYER_JUMP_SWIPE_THRESHOLD = 50;
export const PLAYER_SPIKE_VELOCITY = 50;

export class Player extends Phaser.Sprite {

    constructor(game, state, x, y) {
        super(game, x, y, 'player');
        this.state = state;
        this.anchor.setTo(0.5);
        this.game.add.existing(this);
        this.game.physics.arcade.enable(this);
        this.game.camera.follow(this);
        this.maxHealth = PLAYER_MAX_HEALTH;
        this.health = this.maxHealth;
        this.tooFast = false;
        //Adding gamepad controller
        if(this.game.input.gamepad.supported && this.game.input.gamepad.active && this.game.input.gamepad.pad1.connected) {
            this.pad = this.game.input.gamepad.pad1;
        }
        this.allowJump = true;
        this.immune = false;
    }

    update() {
        //Checking Input
        this.body.velocity.x = 0;

        if(this.isMovingLeft()) {
            this.body.velocity.x -= PLAYER_VELOCITY;
            this.scale.setTo(-1, 1);
        }
        if(this.isMovingRight()) {
            this.body.velocity.x += PLAYER_VELOCITY;
            this.scale.setTo(1, 1);
        }

        if(this.body.velocity.y > PLAYER_FALL_SPEED_LIMIT) {
            this.tooFast = true;
        }

        if (this.canJump() && this.isJumping()) {
            this.body.velocity.y = -PLAYER_JUMP_VELOCITY;
        }

        this.body.allowGravity = true;
        // player.body.velocity.y = 0;
        this.state.physics.arcade.overlap(this, this.state.rope, function(player) {
            if (player.isGrabbingTheRope()) {
                player.disableGravity();
            }
        });

        this.state.physics.arcade.overlap(this, this.state.chests, function(player, chest) {
            if(!chest.open) {
                //Opening the chest and cancel player jump
                player.allowJump = false;
                if(player.isGrabbingTheRope()) {
                    chest.open = true;
                    //Spawning coins
                    let n = this.game.rnd.integerInRange(1, 5);
                    for(let i = 0; i < n; i++) {
                        let coin = this.state.coins.getFirstExists(false);
                        if(coin) {
                            coin.reset(chest.x, chest.y);
                        } else {
                            coin = this.state.coins.create(chest.x, chest.y, 'coin');
                            coin.anchor.setTo(0.5);
                        }
                        coin.allowedPickup = false;
                        let coinTimer = this.game.time.create(this.game, true);
                        coinTimer.add(1*Phaser.Timer.SECOND, function() {
                            coin.allowedPickup = true;
                        }, this);
                        coinTimer.start();
                        coin.body.bounce.set(0.9);
                        coin.body.velocity.x = this.game.rnd.between(-100, 100);
                        coin.body.velocity.y = this.game.rnd.between(-200, -50);
                    }
                    let timer = this.game.time.create(this.game, true);
                    timer.add(0.5*Phaser.Timer.SECOND, function() {
                        player.allowJump = true;
                    }, this);
                    timer.start();
                }
            }
        }, null, this);
    }

    isMovingLeft() {
        return this.game.input.keyboard.isDown(Phaser.Keyboard.A) || this.pad && (this.pad.isDown(Phaser.Gamepad.XBOX360_DPAD_LEFT) || this.pad.axis(Phaser.Gamepad.XBOX360_STICK_LEFT_X) < -0.1) ||
        this.game.input.activePointer.isDown && this.game.input.activePointer.position.x < this.position.x;
    }

    isMovingRight() {
        return this.game.input.keyboard.isDown(Phaser.Keyboard.D) || this.pad && (this.pad.isDown(Phaser.Gamepad.XBOX360_DPAD_LEFT) || this.pad.axis(Phaser.Gamepad.XBOX360_STICK_LEFT_X) < -0.1) ||
        this.game.input.activePointer.isDown && this.game.input.activePointer.position.x > this.position.x;
    }

    canJump() {
        return this.body.blocked.down && this.allowJump;
    }

    isJumping() {
        return this.game.input.keyboard.isDown(Phaser.Keyboard.W) || this.pad &&
        (this.pad.isDown(Phaser.Gamepad.XBOX360_DPAD_UP) || this.pad.axis(Phaser.Gamepad.XBOX360_STICK_LEFT_Y) > 0.1) ||
        this.game.input.activePointer.isDown && this.game.input.activePointer.position.y - this.game.input.activePointer.positionDown.y < -PLAYER_JUMP_SWIPE_THRESHOLD;
    }

    isGrabbingTheRope() {
        return this.game.input.keyboard.isDown(Phaser.Keyboard.W) || this.pad &&
        (this.pad.isDown(Phaser.Gamepad.XBOX360_DPAD_UP) || this.pad.axis(Phaser.Gamepad.XBOX360_STICK_LEFT_Y) > 0.1) ||
        this.game.input.activePointer.isDown;
    }

    loseHealth(health) {
        if(!this.immune) {
            this.health -= health;
            this.immune = true;
            let timer = this.game.time.create(this.game, true);
            timer.add(2*Phaser.Timer.SECOND, function() {
                this.immune = false;
            }, this);
            timer.start();
            this.state.updateHealthHud();
        }
    }

    loseAllHealth() {
        this.loseHealth(this.health);
    }

    isDead() {
        return this.health <= 0;
    }

    disableGravity () {
        this.body.allowGravity = false;
        this.body.velocity.y = 0;
    }
}
<commit_msg>Add a simple immunity feedback using tweens<commit_after>const PLAYER_MAX_HEALTH = 3;
const PLAYER_FALL_SPEED_LIMIT = 1000;
const PLAYER_VELOCITY = 300;
const PLAYER_JUMP_VELOCITY = 300;
const PLAYER_JUMP_SWIPE_THRESHOLD = 50;
export const PLAYER_SPIKE_VELOCITY = 50;

export class Player extends Phaser.Sprite {

    constructor(game, state, x, y) {
        super(game, x, y, 'player');
        this.state = state;
        this.anchor.setTo(0.5);
        this.game.add.existing(this);
        this.game.physics.arcade.enable(this);
        this.game.camera.follow(this);
        this.maxHealth = PLAYER_MAX_HEALTH;
        this.health = this.maxHealth;
        this.tooFast = false;
        //Adding gamepad controller
        if(this.game.input.gamepad.supported && this.game.input.gamepad.active && this.game.input.gamepad.pad1.connected) {
            this.pad = this.game.input.gamepad.pad1;
        }
        this.allowJump = true;
        this.immune = false;
    }

    update() {
        //Checking Input
        this.body.velocity.x = 0;

        if(this.isMovingLeft()) {
            this.body.velocity.x -= PLAYER_VELOCITY;
            this.scale.setTo(-1, 1);
        }
        if(this.isMovingRight()) {
            this.body.velocity.x += PLAYER_VELOCITY;
            this.scale.setTo(1, 1);
        }

        if(this.body.velocity.y > PLAYER_FALL_SPEED_LIMIT) {
            this.tooFast = true;
        }

        if (this.canJump() && this.isJumping()) {
            this.body.velocity.y = -PLAYER_JUMP_VELOCITY;
        }

        this.body.allowGravity = true;
        // player.body.velocity.y = 0;
        this.state.physics.arcade.overlap(this, this.state.rope, function(player) {
            if (player.isGrabbingTheRope()) {
                player.disableGravity();
            }
        });

        this.state.physics.arcade.overlap(this, this.state.chests, function(player, chest) {
            if(!chest.open) {
                //Opening the chest and cancel player jump
                player.allowJump = false;
                if(player.isGrabbingTheRope()) {
                    chest.open = true;
                    //Spawning coins
                    let n = this.game.rnd.integerInRange(1, 5);
                    for(let i = 0; i < n; i++) {
                        let coin = this.state.coins.getFirstExists(false);
                        if(coin) {
                            coin.reset(chest.x, chest.y);
                        } else {
                            coin = this.state.coins.create(chest.x, chest.y, 'coin');
                            coin.anchor.setTo(0.5);
                        }
                        coin.allowedPickup = false;
                        let coinTimer = this.game.time.create(this.game, true);
                        coinTimer.add(1*Phaser.Timer.SECOND, function() {
                            coin.allowedPickup = true;
                        }, this);
                        coinTimer.start();
                        coin.body.bounce.set(0.9);
                        coin.body.velocity.x = this.game.rnd.between(-100, 100);
                        coin.body.velocity.y = this.game.rnd.between(-200, -50);
                    }
                    let timer = this.game.time.create(this.game, true);
                    timer.add(0.5*Phaser.Timer.SECOND, function() {
                        player.allowJump = true;
                    }, this);
                    timer.start();
                }
            }
        }, null, this);
    }

    isMovingLeft() {
        return this.game.input.keyboard.isDown(Phaser.Keyboard.A) || this.pad && (this.pad.isDown(Phaser.Gamepad.XBOX360_DPAD_LEFT) || this.pad.axis(Phaser.Gamepad.XBOX360_STICK_LEFT_X) < -0.1) ||
        this.game.input.activePointer.isDown && this.game.input.activePointer.position.x < this.position.x;
    }

    isMovingRight() {
        return this.game.input.keyboard.isDown(Phaser.Keyboard.D) || this.pad && (this.pad.isDown(Phaser.Gamepad.XBOX360_DPAD_LEFT) || this.pad.axis(Phaser.Gamepad.XBOX360_STICK_LEFT_X) < -0.1) ||
        this.game.input.activePointer.isDown && this.game.input.activePointer.position.x > this.position.x;
    }

    canJump() {
        return this.body.blocked.down && this.allowJump;
    }

    isJumping() {
        return this.game.input.keyboard.isDown(Phaser.Keyboard.W) || this.pad &&
        (this.pad.isDown(Phaser.Gamepad.XBOX360_DPAD_UP) || this.pad.axis(Phaser.Gamepad.XBOX360_STICK_LEFT_Y) > 0.1) ||
        this.game.input.activePointer.isDown && this.game.input.activePointer.position.y - this.game.input.activePointer.positionDown.y < -PLAYER_JUMP_SWIPE_THRESHOLD;
    }

    isGrabbingTheRope() {
        return this.game.input.keyboard.isDown(Phaser.Keyboard.W) || this.pad &&
        (this.pad.isDown(Phaser.Gamepad.XBOX360_DPAD_UP) || this.pad.axis(Phaser.Gamepad.XBOX360_STICK_LEFT_Y) > 0.1) ||
        this.game.input.activePointer.isDown;
    }

    loseHealth(health) {
        if(!this.immune) {
            this.health -= health;
            this.immune = true;
            let timer = this.game.time.create(this.game, true);
            this.immunityTween = this.game.add.tween(this).to({ visible: false }, 0.01 * Phaser.Timer.SECOND, "Linear", true, 0, -1);
            this.immunityTween.yoyo(true, 0);
            timer.add(2*Phaser.Timer.SECOND, function() {
                this.game.tweens.remove(this.immunityTween);
                this.immune = false;
                this.visible = true;
            }, this);
            timer.start();
            this.state.updateHealthHud();
        }
    }

    loseAllHealth() {
        this.loseHealth(this.health);
    }

    isDead() {
        return this.health <= 0;
    }

    disableGravity () {
        this.body.allowGravity = false;
        this.body.velocity.y = 0;
    }
}
<|endoftext|>


<commit_before>/*
 Copyright 2016 - 2018 by Jan Dockx

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/* eslint-env mocha */

'use strict'

const testUtil = require('../_util/testUtil')
const util = require('../../lib/_private/util')
const common = require('./ExceptionConditionViolationCommon')
const ExceptionConditionViolation = require('../../lib/IV/ExceptionConditionViolation')

// noinspection JSUnresolvedVariable
const argsCases = common.argsCases.filter(a => util.typeOf(a) === 'array')

describe('IV/ExceptionConditionViolation', function () {
  describe('#prototype', function () {
    it('has a condition', function () {
      // noinspection JSUnresolvedVariable
      ExceptionConditionViolation.prototype.condition.must.be.a.function()
      // noinspection JSUnresolvedVariable
      ExceptionConditionViolation.prototype.condition.must.not.throw()
    })
  })

  describe('#ExceptionConditionViolation()', function () {
    // noinspection JSUnresolvedVariable
    common.selfCaseGenerators.forEach(selfCaseGenerator => {
      argsCases.forEach(args => {
        common.exceptionCaseGenerators.forEach(exceptionCaseGenerator => {
          const self = selfCaseGenerator()
          const exception = exceptionCaseGenerator()
          it('creates an instance with all toppings for ' + self + ' - ' + args + ' - ' + exception, function () {
            // noinspection JSUnresolvedFunction
            const contractFunction = common.createCandidateContractFunction()
            const doctoredArgs = args.slice()
            doctoredArgs.push(exception)
            doctoredArgs.push(contractFunction.bind(self))
            // noinspection JSUnresolvedVariable
            const creationResult = new ExceptionConditionViolation(
              contractFunction,
              common.conditionCase,
              self,
              doctoredArgs
            )
            // noinspection JSUnresolvedVariable
            common.expectConstructorPost(
              creationResult,
              contractFunction,
              common.conditionCase,
              self,
              args,
              exception
            )
            common.expectInvariants(creationResult)
            testUtil.log('result.stack:\n%s', creationResult.stack)
          })
        })
      })
    })
  })

  // noinspection JSUnresolvedFunction, JSUnresolvedVariable
  common.generatePrototypeMethodsDescriptions(
    () => {
      // noinspection JSUnresolvedFunction
      const contractFunction = common.createCandidateContractFunction()
      const self = null
      // noinspection JSUnresolvedVariable
      const doctoredArgs = common.doctorArgs(common.argsCases[0], contractFunction.bind(self))
      // noinspection JSUnresolvedVariable
      return new ExceptionConditionViolation(contractFunction, common.conditionCase, self, doctoredArgs)
    },
    testUtil
      .x(common.conditionCases, common.selfCaseGenerators, argsCases, common.exceptionCaseGenerators)
      .map(parameters => {
        const self = parameters[1]()
        return {
          subject: () => {
            // noinspection JSUnresolvedFunction
            const contractFunction = common.createCandidateContractFunction()
            const doctoredArgs = common.doctorArgs(parameters[2], contractFunction.bind(self), parameters[3]())
            return new ExceptionConditionViolation(contractFunction, parameters[0], self, doctoredArgs)
          },
          description: parameters[0] + ' — ' + self + ' – ' + parameters[2] + ' – ' + parameters[3]
        }
      })
  )
})
<commit_msg>Linearize Exception condition cases (less cases by a factor 6)<commit_after>/*
 Copyright 2016 - 2018 by Jan Dockx

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */

/* eslint-env mocha */

'use strict'

const testUtil = require('../_util/testUtil')
const util = require('../../lib/_private/util')
const common = require('./ExceptionConditionViolationCommon')
const ExceptionConditionViolation = require('../../lib/IV/ExceptionConditionViolation')

// noinspection JSUnresolvedVariable
const argsCases = common.argsCases.filter(a => util.typeOf(a) === 'array')

describe('IV/ExceptionConditionViolation', function () {
  describe('#prototype', function () {
    it('has a condition', function () {
      // noinspection JSUnresolvedVariable
      ExceptionConditionViolation.prototype.condition.must.be.a.function()
      // noinspection JSUnresolvedVariable
      ExceptionConditionViolation.prototype.condition.must.not.throw()
    })
  })

  describe('#ExceptionConditionViolation()', function () {
    // noinspection JSUnresolvedVariable
    common.selfCaseGenerators.forEach(selfCaseGenerator => {
      argsCases.forEach(args => {
        common.exceptionCaseGenerators.forEach(exceptionCaseGenerator => {
          const self = selfCaseGenerator()
          const exception = exceptionCaseGenerator()
          it('creates an instance with all toppings for ' + self + ' - ' + args + ' - ' + exception, function () {
            // noinspection JSUnresolvedFunction
            const contractFunction = common.createCandidateContractFunction()
            const doctoredArgs = args.slice()
            doctoredArgs.push(exception)
            doctoredArgs.push(contractFunction.bind(self))
            // noinspection JSUnresolvedVariable
            const creationResult = new ExceptionConditionViolation(
              contractFunction,
              common.conditionCase,
              self,
              doctoredArgs
            )
            // noinspection JSUnresolvedVariable
            common.expectConstructorPost(
              creationResult,
              contractFunction,
              common.conditionCase,
              self,
              args,
              exception
            )
            common.expectInvariants(creationResult)
            testUtil.log('result.stack:\n%s', creationResult.stack)
          })
        })
      })
    })
  })

  // noinspection JSUnresolvedVariable
  const cases = testUtil
    .x(common.conditionCases, [() => common.oneSelfCase], [() => common.oneArgsCase], common.exceptionCaseGenerators)
    .concat(testUtil.x([common.conditionCase], common.selfCaseGenerators, [() => common.oneArgsCase], [() => new Error('test error')]))
    .concat(testUtil.x([common.conditionCase], [() => common.oneSelfCase], argsCases, [() => new Error('test error')]))

  // noinspection JSUnresolvedFunction, JSUnresolvedVariable
  common.generatePrototypeMethodsDescriptions(
    () => {
      // noinspection JSUnresolvedFunction
      const contractFunction = common.createCandidateContractFunction()
      const self = null
      // noinspection JSUnresolvedVariable
      const doctoredArgs = common.doctorArgs(common.argsCases[0], contractFunction.bind(self))
      // noinspection JSUnresolvedVariable
      return new ExceptionConditionViolation(contractFunction, common.conditionCase, self, doctoredArgs)
    },
    cases.map(parameters => {
      const self = parameters[1]()
      return {
        subject: () => {
          // noinspection JSUnresolvedFunction
          const contractFunction = common.createCandidateContractFunction()
          const doctoredArgs = common.doctorArgs(parameters[2], contractFunction.bind(self), parameters[3]())
          return new ExceptionConditionViolation(contractFunction, parameters[0], self, doctoredArgs)
        },
        description: parameters[0] + ' — ' + self + ' – ' + parameters[2] + ' – ' + parameters[3]
      }
    })
  )
})
<|endoftext|>


<commit_before>const UI_PORT = 8080	// Port to serve HTML UI on
const SOCKET_SERVER = "http://futuwear.tunk.org:13337/"; // Where to listen to Vör messages

var options = {
	analyzation: {
		riskyMuscles: ["Back_Y", "Back_X"] // Muscles that should be excercised every now and then

	}
}

var devices = {}

// Dependencies
const http = require("http")
const fs = require("fs")
const express = require('express');
const socketIO = require('socket.io-client');
const mysql = require('mysql');
const crypto = require('crypto');

var app = express();

// Serve all static files
app.use(express.static('public'));

// Request parsers
var bodyParser = require('body-parser')
app.use(bodyParser.json());       	// to support JSON-encoded bodies
app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
  extended: true
}));

/* Method to get archived data with */
app.get('/fetch', function (req, res) {

	var content = req.query.data // TODO: Safety
	content = JSON.parse(content)

	getData(parseInt(content.time0), parseInt(content.timeT), req, res)
});

/* Method to get registered sensors with */
app.get('/sensors', getSensors);

/* Method to save new sensors to a device */
app.post('/manage.html', function (req, res) {
	var content = req.body
	var id = content.name + "_" + Math.round(Math.random()*1000000)
	saveSensor(id, content.name, content.device)
	res.redirect("/manage.html");
});

app.listen(UI_PORT, function () {
	nodeLog('Serving on port ' + UI_PORT.toString());
});

///////////////////////////
// Vör socket management //
///////////////////////////

const client = socketIO.connect(SOCKET_SERVER);

client.on('connect', () => nodeLog(`Connected to Vör socket ${SOCKET_SERVER}`));
client.on('disconnect', () => nodeLog(`Client socket disconnected ${SOCKET_SERVER} :  ${new Date()}`));
client.on('reconnect_attempt', error => console.error(`Error - cannot connect to ${SOCKET_SERVER} : ${error} : ${new Date()}`));
client.on('error', error => console.error(`Error - socket connection: ${error} : ${new Date()}`));

// Listen to vör messages
client.on('message', msg => {

	try {
		var md5 = crypto.createHash('md5')

		var sensors = json(msg)["sensors"]
		var serial = "Rand0mSens0rSerialNumber" // TODO: Get from database

		md5.update(JSON.stringify(sensors) + serial); // TODO: SHA256
		var computedHash = md5.digest('hex')

		var receivedHash = json(msg)["token"]

		/* AES-CBC-MAC salaus+autentikointi*/

		if (computedHash != receivedHash)
			throw new Error("Received hash " + receivedHash + " didn't match the computed hash " + computedHash)

		// Allow a single sensor to not be inside of list
		if (!sensors[0])
			sensors = [sensors]

		//nodeLog("Got vör message [" + sensors.length + " sensor(s)].")

		// Iterate through every sensor
		for (var i = 0; i < sensors.length; i++) {
			var sensor = sensors[i]

			// Iterate through every value
			for (var j = 0; j < sensor["collection"].length; j++) {
				var value = parseInt(sensor["collection"][j]["value"])
				if (isNaN(value))
					throw new Error("Sensor value was not an integer.")
				saveData(sensor["id"], value)
			}

		}
	} catch (e) {
		nodeLog("Could not save vör data (" + e.message + "): " + JSON.stringify(msg))
	}

});

/////////////////////////
// Manage the database //
/////////////////////////

const db = require("./connection-strings")
var c;

// Wrap the database connection inside a function, so that it can be re-established on disconnect
function maintainConnection() {
	c = mysql.createConnection(db);

	c.connect(function(err){
		if(err){
			nodeLog('Error connecting to Db: ' + err.message);
			setTimeout(maintainConnection(), 1000) // Retry soon
			return;
		}
		nodeLog('Database connection established');
	});

	c.on('error', function (err) {
		nodeLog("Database error: " + err);
		if(err.code === 'PROTOCOL_CONNECTION_LOST') {
			maintainConnection(); // Reconnect
		}
		else {
			throw err;
		}
	})

}
maintainConnection();

var accuracy = 1 			// Seconds, ie. what to average at (60 => 1 minute averages)

/* Method to extract archived sensor data (JSON) */
function getData(time1, timeT, req, res) {
	var changePeriod = 1 * 60 	// Seconds

	var devices = getUserDevices(req)
	var time0 = Math.max(time1 - changePeriod, 0)

	if (!devices)
		return res && res.send(JSON.stringify({error: "No devices stored with user"}, null, 3));

	var sql = '	SELECT sensorID, name AS sensorName, UNIX_TIMESTAMP(ROUND(AVG(logged))) AS logged, ROUND(AVG(val)) AS val \
				FROM Data INNER JOIN Sensors \
				WHERE logged >= FROM_UNIXTIME(?) AND logged <= FROM_UNIXTIME(?) AND ownerKey IN (?) \
				GROUP BY ID, ROUND(logged/?) \
				ORDER BY logged DESC \
				LIMIT 43200;'

	c.query(sql, [time0, timeT, devices, accuracy], function(err, result) {
		res.setHeader('Content-Type', 'application/json');

		if (!err) {
			nodeLog("Found " + result.length + " data points between " + (new Date(time0*1000)).toLocaleString() + " and " + (new Date(timeT*1000)).toLocaleString())
			res.send(JSON.stringify(result, null, 3));
		}
		else  {
			nodeLog("Mysql error while fetching from archive: " + JSON.stringify(err))
			res.send(JSON.stringify({}, null, 3));
		}
	});
}

function analyzeData(ownerKey) {
	var sql = '	SELECT sensorID, name AS sensorName, STD(val) AS std, ownerKey AS device \
				FROM Data INNER JOIN Sensors \
				WHERE logged >= FROM_UNIXTIME(?) AND logged <= FROM_UNIXTIME(?) AND ownerKey IN (?) \
				GROUP BY sensorID \
				LIMIT 100;'
	var now = Math.ceil(Date.now()/1000)
	var period = 60 // Mins
	c.query(sql, [now - period * 15, now, [ownerKey], accuracy], function(err, result) {

		if (err)
			return nodeLog("Mysql error while analyzing from archive: " + JSON.stringify(err))

		for (var i = 0; i < result.length; i++) {
			var sensor = result[i]
			notify(sensor.device, "You've been still for a while now", sensor.sensorName + " needs a shake, because it's standard deviation is " + sensor.std)
		}
	});
}

/* Saves a given value as reported by #sensorID */
function saveData(sensorID, val, failCallback) {
	c.query('SELECT DISTINCT ownerKey FROM Sensors WHERE ID=?;', [sensorID], function(err, result) {
		try {
			var sensorExists = result.length > 0
			if (!sensorExists)
				throw new Error("Sensor #" + sensorID + " has not been registered.");
			var insertion = {sensorID: sensorID, val: val} // Information to INSERT INTO the "Data" table

			analyzeData(result.ownerKey)

			c.query('INSERT INTO Data SET ?;', insertion, function(err, result) {
				if (err)
					nodeLog("Mysql error: " + JSON.stringify(err));
			});
		} catch (e) {
			nodeLog("Data save error: " + e.message)
			if (typeof failCallback == "function")
				return failCallback()
		}
	});
}

/* Registers a new sensor into the system */
function saveSensor(ID, name, device) {
	c.query('SELECT Count(ID) AS results FROM Sensors WHERE ID=?;', [ID], function(err, result) {
		if (!err) {
			var found = !isNaN(result[0]["results"]) && parseInt(result[0]["results"]) > 0

			if (!found) {
				var insertion = {ID: ID, type: "kinetic", name: name, ownerKey: device}
				c.query('INSERT INTO Sensors SET ?;', insertion, function(err, result) {
					if (!err) {
						nodeLog("Registered new sensor " + ID + " with device " + device)
					}
					else  {
						nodeLog("Mysql sensor insertion error: " + JSON.stringify(err))
					}
				});
			}
			else nodeLog("Sensor #" + ID + " already exists, please give a fresh id.")
		}
		else {
			nodeLog("Mysql error: " + JSON.stringify(err))
		}
	});
}

/* Method to get a list of owned/viewed sensors*/
function getSensors(req, res) {
	var devices = getUserDevices(req)

	if (!devices)
		return res.send(JSON.stringify({error: "No devices were found."}, null, 3));

	var sql = '	SELECT ID, name, ownerKey, COUNT(ID) - 1 AS collection \
				FROM Sensors \
				LEFT JOIN Data ON Sensors.ID=Data.sensorID \
				WHERE ownerKey IN (?) \
				GROUP BY Sensors.ID \
				ORDER BY ownerKey \
				LIMIT 100;'

	c.query(sql, [devices], function(err, result) {
		res.setHeader('Content-Type', 'application/json');

		if (!err) {
			res.send(JSON.stringify(result, null, 3));
		}
		else  {
			nodeLog("Mysql error while getting sensors: " + JSON.stringify(err))
			res.send(JSON.stringify({error: JSON.stringify(err)}, null, 3));
		}
	});
}

/////////////////////////////
// Server helper functions //
/////////////////////////////

/* Method to force data into JSON object */
function json(data) {
	try {
		if (typeof data == "string")
			return JSON.parse(data)
		else if (typeof JSON.parse(JSON.stringify(data)) == "object")
			return data
		else throw new Error("")
	} catch (e) {
		nodeLog("JSON data is faulty, calling it {}")
		return {}
	}
}

/* Server logging*/
function nodeLog(str) {
	var currentTime = new Date()
	var clock = [currentTime.getHours(), currentTime.getMinutes(), currentTime.getSeconds()]
	clock = clock.map(function (digit) {
        if (digit.toString().length == 1)
            return "0" + digit;
		else return digit
	})
	console.log(clock.join(':') + ' ' + str)
}

/* From http://stackoverflow.com/a/3409200 */
function parseCookies (request) {
    var list = {},
        rc = request.headers.cookie;

    rc && rc.split(';').forEach(function( cookie ) {
        var parts = cookie.split('=');
        list[parts.shift().trim()] = decodeURI(parts.join('='));
    });

    return list;
}

/* Method to parse user's devices from cookie */
function getUserDevices(req) {
	var cookies = parseCookies(req);
	if (typeof cookies.devices == "undefined")
		return false
	var devices = cookies.devices.split(",")
	return devices
}

function analyze() {

}

function notify(device, title, message) {
	client.emit(device, {title: title, message: message})
}

<commit_msg>Fixed syntax<commit_after>const UI_PORT = 8080	// Port to serve HTML UI on
const SOCKET_SERVER = "http://futuwear.tunk.org:13337/"; // Where to listen to Vör messages

var options = {
	analyzation: {
		riskyMuscles: ["Back_Y", "Back_X"] // Muscles that should be excercised every now and then

	}
}

var devices = {}

// Dependencies
const http = require("http")
const fs = require("fs")
const express = require('express');
const socketIO = require('socket.io-client');
const mysql = require('mysql');
const crypto = require('crypto');

var app = express();

// Serve all static files
app.use(express.static('public'));

// Request parsers
var bodyParser = require('body-parser')
app.use(bodyParser.json());       	// to support JSON-encoded bodies
app.use(bodyParser.urlencoded({     // to support URL-encoded bodies
  extended: true
}));

/* Method to get archived data with */
app.get('/fetch', function (req, res) {

	var content = req.query.data // TODO: Safety
	content = JSON.parse(content)

	getData(parseInt(content.time0), parseInt(content.timeT), req, res)
});

/* Method to get registered sensors with */
app.get('/sensors', getSensors);

/* Method to save new sensors to a device */
app.post('/manage.html', function (req, res) {
	var content = req.body
	var id = content.name + "_" + Math.round(Math.random()*1000000)
	saveSensor(id, content.name, content.device)
	res.redirect("/manage.html");
});

app.listen(UI_PORT, function () {
	nodeLog('Serving on port ' + UI_PORT.toString());
});

///////////////////////////
// Vör socket management //
///////////////////////////

const client = socketIO.connect(SOCKET_SERVER);

client.on('connect', () => nodeLog(`Connected to Vör socket ${SOCKET_SERVER}`));
client.on('disconnect', () => nodeLog(`Client socket disconnected ${SOCKET_SERVER} :  ${new Date()}`));
client.on('reconnect_attempt', error => console.error(`Error - cannot connect to ${SOCKET_SERVER} : ${error} : ${new Date()}`));
client.on('error', error => console.error(`Error - socket connection: ${error} : ${new Date()}`));

// Listen to vör messages
client.on('message', msg => {

	try {
		var md5 = crypto.createHash('md5')

		var sensors = json(msg)["sensors"]
		var serial = "Rand0mSens0rSerialNumber" // TODO: Get from database

		md5.update(JSON.stringify(sensors) + serial); // TODO: SHA256
		var computedHash = md5.digest('hex')

		var receivedHash = json(msg)["token"]

		/* AES-CBC-MAC salaus+autentikointi */

		if (computedHash != receivedHash)
			throw new Error("Received hash " + receivedHash + " didn't match the computed hash " + computedHash)

		// Allow a single sensor to not be inside of list
		if (!sensors[0])
			sensors = [sensors]

		//nodeLog("Got vör message [" + sensors.length + " sensor(s)].")

		// Iterate through every sensor
		for (var i = 0; i < sensors.length; i++) {
			var sensor = sensors[i]

			// Iterate through every value
			for (var j = 0; j < sensor["collection"].length; j++) {
				var value = parseInt(sensor["collection"][j]["value"])
				if (isNaN(value))
					throw new Error("Sensor value was not an integer.")
				saveData(sensor["id"], value)
			}

		}
	} catch (e) {
		nodeLog("Could not save vör data (" + e.message + "): " + JSON.stringify(msg))
	}

});

/////////////////////////
// Manage the database //
/////////////////////////

const db = require("./connection-strings")
var c;

// Wrap the database connection inside a function, so that it can be re-established on disconnect
function maintainConnection() {
	c = mysql.createConnection(db);

	c.connect(function(err){
		if(err){
			nodeLog('Error connecting to Db: ' + err.message);
			setTimeout(maintainConnection(), 1000) // Retry soon
			return;
		}
		nodeLog('Database connection established');
	});

	c.on('error', function (err) {
		nodeLog("Database error: " + err);
		if(err.code === 'PROTOCOL_CONNECTION_LOST') {
			maintainConnection(); // Reconnect
		}
		else {
			throw err;
		}
	})

}
maintainConnection();

var accuracy = 1 			// Seconds, ie. what to average at (60 => 1 minute averages)

/* Method to extract archived sensor data (JSON) */
function getData(time1, timeT, req, res) {
	var changePeriod = 1 * 60 	// Seconds

	var devices = getUserDevices(req)
	var time0 = Math.max(time1 - changePeriod, 0)

	if (!devices)
		return res && res.send(JSON.stringify({error: "No devices stored with user"}, null, 3));

	var sql = '	SELECT sensorID, name AS sensorName, UNIX_TIMESTAMP(ROUND(AVG(logged))) AS logged, ROUND(AVG(val)) AS val \
				FROM Data INNER JOIN Sensors \
				WHERE logged >= FROM_UNIXTIME(?) AND logged <= FROM_UNIXTIME(?) AND ownerKey IN (?) \
				GROUP BY ID, ROUND(logged/?) \
				ORDER BY logged DESC \
				LIMIT 43200;'

	c.query(sql, [time0, timeT, devices, accuracy], function(err, result) {
		res.setHeader('Content-Type', 'application/json');

		if (!err) {
			nodeLog("Found " + result.length + " data points between " + (new Date(time0*1000)).toLocaleString() + " and " + (new Date(timeT*1000)).toLocaleString())
			res.send(JSON.stringify(result, null, 3));
		}
		else  {
			nodeLog("Mysql error while fetching from archive: " + JSON.stringify(err))
			res.send(JSON.stringify({}, null, 3));
		}
	});
}

function analyzeData(ownerKey) {
	var sql = '	SELECT sensorID, name AS sensorName, STD(val) AS std, ownerKey AS device \
				FROM Data INNER JOIN Sensors \
				WHERE logged >= FROM_UNIXTIME(?) AND logged <= FROM_UNIXTIME(?) AND ownerKey IN (?) \
				GROUP BY sensorID \
				LIMIT 100;'
	var now = Math.ceil(Date.now()/1000)
	var period = 60 // Mins
	c.query(sql, [now - period * 15, now, [ownerKey], accuracy], function(err, result) {

		if (err)
			return nodeLog("Mysql error while analyzing from archive: " + JSON.stringify(err))

		for (var i = 0; i < result.length; i++) {
			var sensor = result[i]
			notify(sensor.device, "You've been still for a while now", sensor.sensorName + " needs a shake, because it's standard deviation is " + sensor.std)
		}
	});
}

/* Saves a given value as reported by #sensorID */
function saveData(sensorID, val, failCallback) {
	c.query('SELECT DISTINCT ownerKey FROM Sensors WHERE ID=?;', [sensorID], function(err, result) {
		try {
			var sensorExists = result.length > 0
			if (!sensorExists)
				throw new Error("Sensor #" + sensorID + " has not been registered.");
			var insertion = {sensorID: sensorID, val: val} // Information to INSERT INTO the "Data" table

			analyzeData(result[0].ownerKey)

			c.query('INSERT INTO Data SET ?;', insertion, function(err, result) {
				if (err)
					nodeLog("Mysql error: " + JSON.stringify(err));
			});
		} catch (e) {
			nodeLog("Data save error: " + e.message)
			if (typeof failCallback == "function")
				return failCallback()
		}
	});
}

/* Registers a new sensor into the system */
function saveSensor(ID, name, device) {
	c.query('SELECT Count(ID) AS results FROM Sensors WHERE ID=?;', [ID], function(err, result) {
		if (!err) {
			var found = !isNaN(result[0]["results"]) && parseInt(result[0]["results"]) > 0

			if (!found) {
				var insertion = {ID: ID, type: "kinetic", name: name, ownerKey: device}
				c.query('INSERT INTO Sensors SET ?;', insertion, function(err, result) {
					if (!err) {
						nodeLog("Registered new sensor " + ID + " with device " + device)
					}
					else  {
						nodeLog("Mysql sensor insertion error: " + JSON.stringify(err))
					}
				});
			}
			else nodeLog("Sensor #" + ID + " already exists, please give a fresh id.")
		}
		else {
			nodeLog("Mysql error: " + JSON.stringify(err))
		}
	});
}

/* Method to get a list of owned/viewed sensors*/
function getSensors(req, res) {
	var devices = getUserDevices(req)

	if (!devices)
		return res.send(JSON.stringify({error: "No devices were found."}, null, 3));

	var sql = '	SELECT ID, name, ownerKey, COUNT(ID) - 1 AS collection \
				FROM Sensors \
				LEFT JOIN Data ON Sensors.ID=Data.sensorID \
				WHERE ownerKey IN (?) \
				GROUP BY Sensors.ID \
				ORDER BY ownerKey \
				LIMIT 100;'

	c.query(sql, [devices], function(err, result) {
		res.setHeader('Content-Type', 'application/json');

		if (!err) {
			res.send(JSON.stringify(result, null, 3));
		}
		else  {
			nodeLog("Mysql error while getting sensors: " + JSON.stringify(err))
			res.send(JSON.stringify({error: JSON.stringify(err)}, null, 3));
		}
	});
}

/////////////////////////////
// Server helper functions //
/////////////////////////////

/* Method to force data into JSON object */
function json(data) {
	try {
		if (typeof data == "string")
			return JSON.parse(data)
		else if (typeof JSON.parse(JSON.stringify(data)) == "object")
			return data
		else throw new Error("")
	} catch (e) {
		nodeLog("JSON data is faulty, calling it {}")
		return {}
	}
}

/* Server logging*/
function nodeLog(str) {
	var currentTime = new Date()
	var clock = [currentTime.getHours(), currentTime.getMinutes(), currentTime.getSeconds()]
	clock = clock.map(function (digit) {
        if (digit.toString().length == 1)
            return "0" + digit;
		else return digit
	})
	console.log(clock.join(':') + ' ' + str)
}

/* From http://stackoverflow.com/a/3409200 */
function parseCookies (request) {
    var list = {},
        rc = request.headers.cookie;

    rc && rc.split(';').forEach(function( cookie ) {
        var parts = cookie.split('=');
        list[parts.shift().trim()] = decodeURI(parts.join('='));
    });

    return list;
}

/* Method to parse user's devices from cookie */
function getUserDevices(req) {
	var cookies = parseCookies(req);
	if (typeof cookies.devices == "undefined")
		return false
	var devices = cookies.devices.split(",")
	return devices
}

function analyze() {

}

function notify(device, title, message) {
	client.emit(device, {title: title, message: message})
}

<|endoftext|>


<commit_before>function trim( str, charlist ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: mdsjack (http://www.mdsjack.bo.it)
    // +   improved by: Alexander Ermolaev (http://snippets.dzone.com/user/AlexanderErmolaev)
    // +      input by: Erkekjetter
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: DxGx
    // +   improved by: Steven Levithan (http://blog.stevenlevithan.com)
    // +   improved by: Jack
    // *     example 1: trim('    Kevin van Zonneveld    ');
    // *     returns 1: 'Kevin van Zonneveld'
    // *     example 2: trim('Hello World', 'Hdle');
    // *     returns 2: 'o Wor'

    var whitespace, l = 0;

    if (!charlist) {
        whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
    } else {
        whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '\$1');
    }

    l = str.length;
    for (var i = 0; i < l; i++) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(i);
            break;
        }
    }

    l = str.length;
    for (i = l - 1; i >= 0; i--) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(0, i + 1);
            break;
        }
    }

    return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}<commit_msg>Fixed trim<commit_after>function trim( str, charlist ) {
    // http://kevin.vanzonneveld.net
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: mdsjack (http://www.mdsjack.bo.it)
    // +   improved by: Alexander Ermolaev (http://snippets.dzone.com/user/AlexanderErmolaev)
    // +      input by: Erkekjetter
    // +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +      input by: DxGx
    // +   improved by: Steven Levithan (http://blog.stevenlevithan.com)
    // +    tweaked by: Jack
    // *     example 1: trim('    Kevin van Zonneveld    ');
    // *     returns 1: 'Kevin van Zonneveld'
    // *     example 2: trim('Hello World', 'Hdle');
    // *     returns 2: 'o Wor'

    var whitespace, l = 0, i = 0;

    if (!charlist) {
        whitespace = ' \n\r\t\f\x0b\xa0\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200a\u200b\u2028\u2029\u3000';
    } else {
        whitespace = charlist.replace(/([\[\]\(\)\.\?\/\*\{\}\+\$\^\:])/g, '\$1');
    }

    l = str.length;
    for (i = 0; i < l; i++) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(i);
            break;
        }
    }

    l = str.length;
    for (i = l - 1; i >= 0; i--) {
        if (whitespace.indexOf(str.charAt(i)) === -1) {
            str = str.substring(0, i + 1);
            break;
        }
    }

    return whitespace.indexOf(str.charAt(0)) === -1 ? str : '';
}<|endoftext|>


<commit_before>import {
	LM_NONE, LM_SINGLE, LM_MULTIPLE, SHADING_CURSOR, SHADING_HEIGHT, SHADING_INCLINATION, SHADING_SURFACE
} from '../core/constants';

import { Page } from './Page';

const surfaceShadingModes = {
	'surface.shading.height':        SHADING_HEIGHT,
	'surface.shading.inclination':   SHADING_INCLINATION,
	'surface.shading.height_cursor': SHADING_CURSOR,
	'surface.shading.fixed':         SHADING_SURFACE
};

const lightingModes = {
	'terrain.lightingmodes.none': LM_NONE,
	'terrain.lightingmodes.single': LM_SINGLE,
	'terrain.lightingmodes.multiple': LM_MULTIPLE
};

class SurfacePage extends Page {

	constructor ( frame, viewer ) {

		const controls = [];

		super( 'icon_terrain', 'surface' );

		frame.addPage ( this );

		this.addHeader( 'surface.header' );

		if ( viewer.hasSurfaceLegs ) {

			this.addCheckbox( 'surface.legs', viewer, 'surfaceLegs' );
			this.addSelect( 'surface.shading.caption', surfaceShadingModes, viewer, 'surfaceShading' );

		}

		if ( viewer.hasTerrain ) {

			this.addHeader( 'terrain.header' );

			this.addCheckbox( 'terrain.terrain', viewer, 'terrain' );

			controls.push( this.addSelect( 'terrain.shading.caption', viewer.terrainShadingModes, viewer, 'terrainShading' ) );

			controls.push( this.addRange( 'terrain.opacity', viewer, 'terrainOpacity' ) );

			controls.push( this.addSelect( 'terrain.lightingmode', lightingModes, viewer, 'terrainLightingMode' ) );

			if ( ! viewer.hasRealTerrain ) {

				controls.push( this.addDownloadButton( 'terrain.downloadTileSet', viewer.terrainTileSet, 'tileSetEntry.json' ) );

			}

			this.addCheckbox( 'terrain.datum_shift', viewer, 'terrainDatumShift' );
			this.addNumber( 'terrain.datum_shift_value', viewer, 'terrainDatumShiftValue' );

			viewer.terrainAttributions.forEach( attribution => {

				this.addText( attribution );

			} );

		}

		_onChange( { name: 'terrain' } );

		this.onChange = _onChange;

		return this;

		function _onChange ( event ) {

			// change UI dynamicly to only display useful controls
			if ( event.name === 'terrain' ) {

				frame.setControlsVisibility( controls, viewer.terrain );

			}

		}

	}

}

export { SurfacePage };<commit_msg>reorder controls<commit_after>import {
	LM_NONE, LM_SINGLE, LM_MULTIPLE, SHADING_CURSOR, SHADING_HEIGHT, SHADING_INCLINATION, SHADING_SURFACE
} from '../core/constants';

import { Page } from './Page';

const surfaceShadingModes = {
	'surface.shading.height':        SHADING_HEIGHT,
	'surface.shading.inclination':   SHADING_INCLINATION,
	'surface.shading.height_cursor': SHADING_CURSOR,
	'surface.shading.fixed':         SHADING_SURFACE
};

const lightingModes = {
	'terrain.lightingmodes.none': LM_NONE,
	'terrain.lightingmodes.single': LM_SINGLE,
	'terrain.lightingmodes.multiple': LM_MULTIPLE
};

class SurfacePage extends Page {

	constructor ( frame, viewer ) {

		const controls = [];

		super( 'icon_terrain', 'surface' );

		frame.addPage ( this );

		this.addHeader( 'surface.header' );

		if ( viewer.hasSurfaceLegs ) {

			this.addCheckbox( 'surface.legs', viewer, 'surfaceLegs' );
			this.addSelect( 'surface.shading.caption', surfaceShadingModes, viewer, 'surfaceShading' );

		}

		if ( viewer.hasTerrain ) {

			this.addHeader( 'terrain.header' );

			this.addCheckbox( 'terrain.terrain', viewer, 'terrain' );

			controls.push( this.addSelect( 'terrain.shading.caption', viewer.terrainShadingModes, viewer, 'terrainShading' ) );

			controls.push( this.addRange( 'terrain.opacity', viewer, 'terrainOpacity' ) );

			controls.push( this.addSelect( 'terrain.lightingmode', lightingModes, viewer, 'terrainLightingMode' ) );

			if ( ! viewer.hasRealTerrain ) {

				controls.push( this.addDownloadButton( 'terrain.downloadTileSet', viewer.terrainTileSet, 'tileSetEntry.json' ) );

			}

			this.addNumber( 'terrain.datum_shift_value', viewer, 'terrainDatumShiftValue' );
			this.addCheckbox( 'terrain.datum_shift', viewer, 'terrainDatumShift' );

			viewer.terrainAttributions.forEach( attribution => {

				this.addText( attribution );

			} );

		}

		_onChange( { name: 'terrain' } );

		this.onChange = _onChange;

		return this;

		function _onChange ( event ) {

			// change UI dynamicly to only display useful controls
			if ( event.name === 'terrain' ) {

				frame.setControlsVisibility( controls, viewer.terrain );

			}

		}

	}

}

export { SurfacePage };<|endoftext|>


<commit_before>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var tape = require( 'tape' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var abs = require( '@stdlib/math/base/special/abs' );
var EPSILON = require( '@stdlib/constants/math/float64-eps' );
var incrmhmean = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof incrmhmean, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if not provided a positive integer', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		-5.0,
		0.0,
		3.14,
		true,
		null,
		void 0,
		NaN,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			incrmhmean( value );
		};
	}
});

tape( 'the function returns an accumulator function', function test( t ) {
	t.equal( typeof incrmhmean( 3 ), 'function', 'returns a function' );
	t.end();
});

tape( 'the accumulator function computes a moving harmonic mean incrementally', function test( t ) {
	var expected;
	var actual;
	var delta;
	var data;
	var tol;
	var acc;
	var N;
	var i;

	data = [ 2.0, 3.0, 2.0, 4.0, 3.0, 4.0 ];
	N = data.length;

	acc = incrmhmean( 3 );

	actual = new Array( N );
	for ( i = 0; i < N; i++ ) {
		actual[ i ] = acc( data[ i ] );
	}
	expected = [
		2.0,
		2.4,
		2.25,
		2.7692307692307696,
		2.7692307692307696,
		3.6
	];

	for ( i = 0; i < N; i++ ) {
		if ( actual[ i ] === expected[ i ] ) {
			t.equal( actual[ i ], expected[ i ], 'returns expected value' );
		} else {
			delta = abs( expected[ i ] - actual[ i ] );
			tol = EPSILON * abs( expected[ i ] );
			t.equal( delta <= tol, true, 'within tolerance. Expected: '+expected[ i ]+'. Actual: '+actual[ i ]+'. Delta: '+delta+'. Tol: '+tol+'.' );
		}
	}
	t.end();
});

tape( 'if not provided an input value, the accumulator function returns the current harmonic mean', function test( t ) {
	var expected;
	var actual;
	var delta;
	var data;
	var acc;
	var tol;
	var i;

	data = [ 2.0, 3.0, 5.0 ];
	acc = incrmhmean( 2 );
	for ( i = 0; i < data.length; i++ ) {
		acc( data[ i ] );
	}
	actual = acc();
	expected = 3.75;
	delta = abs( expected - actual );
	tol = 1.1 * EPSILON * abs( expected );
	t.equal( delta <= tol, true, 'within tolerance. Expected: '+expected+'. Actual: '+actual+'. Delta: '+delta+'. Tol: '+tol+'.' );
	t.end();
});

tape( 'if data has yet to be provided, the accumulator function returns `null`', function test( t ) {
	var acc = incrmhmean( 3 );
	t.equal( acc(), null, 'returns null' );
	t.end();
});

tape( 'if provided `NaN`, the accumulated value is `NaN` for at least `W` invocations', function test( t ) {
	var expected;
	var data;
	var acc;
	var v;
	var i;

	acc = incrmhmean( 3 );

	data = [
		NaN,  // NaN
		3.14, // NaN, 3.14
		3.14, // NaN, 3.14, 3.14
		NaN,  // 3.14, 3.14, NaN
		3.14, // 3.14, NaN, 3.14
		3.14, // NaN, 3.14, 3.14
		3.14, // 3.14, 3.14, 3.14
		NaN,  // 3.14, 3.14, NaN
		3.14, // 3.14, NaN, 3.14
		3.14, // NaN, 3.14, 3.14
		3.14, // 3.14, 3.14, 3.14
		NaN,  // 3.14, 3.14, NaN
		3.14, // 3.14, NaN, 3.14
		3.14, // NaN, 3.14, 3.14
		NaN,  // 3.14, 3.14, NaN
		NaN,  // 3.14, NaN, NaN
		NaN,  // NaN, NaN, NaN
		NaN,  // NaN, NaN, NaN
		3.14  // NaN, NaN, 3.14
	];
	expected = [
		NaN,
		NaN,
		NaN,
		NaN,
		NaN,
		NaN,
		3.14,
		NaN,
		NaN,
		NaN,
		3.14,
		NaN,
		NaN,
		NaN,
		NaN,
		NaN,
		NaN,
		NaN,
		NaN
	];
	for ( i = 0; i < data.length; i++ ) {
		v = acc( data[ i ] );
		if ( isnan( expected[ i ] ) ) {
			t.equal( isnan( v ), true, 'returns expected value for window '+i );
		} else {
			t.equal( v, expected[ i ], 'returns expected value for window '+i );
		}
	}
	t.end();
});
<commit_msg>Add comments<commit_after>/**
* @license Apache-2.0
*
* Copyright (c) 2018 The Stdlib Authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*    http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

'use strict';

// MODULES //

var tape = require( 'tape' );
var isnan = require( '@stdlib/math/base/assert/is-nan' );
var abs = require( '@stdlib/math/base/special/abs' );
var EPSILON = require( '@stdlib/constants/math/float64-eps' );
var incrmhmean = require( './../lib' );

// TESTS //

tape( 'main export is a function', function test( t ) {
	t.ok( true, __filename );
	t.equal( typeof incrmhmean, 'function', 'main export is a function' );
	t.end();
});

tape( 'the function throws an error if not provided a positive integer', function test( t ) {
	var values;
	var i;

	values = [
		'5',
		-5.0,
		0.0,
		3.14,
		true,
		null,
		void 0,
		NaN,
		[],
		{},
		function noop() {}
	];

	for ( i = 0; i < values.length; i++ ) {
		t.throws( badValue( values[i] ), TypeError, 'throws an error when provided '+values[i] );
	}
	t.end();

	function badValue( value ) {
		return function badValue() {
			incrmhmean( value );
		};
	}
});

tape( 'the function returns an accumulator function', function test( t ) {
	t.equal( typeof incrmhmean( 3 ), 'function', 'returns a function' );
	t.end();
});

tape( 'the accumulator function computes a moving harmonic mean incrementally', function test( t ) {
	var expected;
	var actual;
	var delta;
	var data;
	var tol;
	var acc;
	var N;
	var i;

	data = [ 2.0, 3.0, 2.0, 4.0, 3.0, 4.0 ];
	N = data.length;

	acc = incrmhmean( 3 );

	actual = new Array( N );
	for ( i = 0; i < N; i++ ) {
		actual[ i ] = acc( data[ i ] );
	}
	// Note: computed by hand using textbook formula:
	expected = [
		2.0,
		2.4,
		2.25,
		2.7692307692307696,
		2.7692307692307696,
		3.6
	];

	for ( i = 0; i < N; i++ ) {
		if ( actual[ i ] === expected[ i ] ) {
			t.equal( actual[ i ], expected[ i ], 'returns expected value' );
		} else {
			delta = abs( expected[ i ] - actual[ i ] );
			tol = EPSILON * abs( expected[ i ] );
			t.equal( delta <= tol, true, 'within tolerance. Expected: '+expected[ i ]+'. Actual: '+actual[ i ]+'. Delta: '+delta+'. Tol: '+tol+'.' );
		}
	}
	t.end();
});

tape( 'if not provided an input value, the accumulator function returns the current harmonic mean', function test( t ) {
	var expected;
	var actual;
	var delta;
	var data;
	var acc;
	var tol;
	var i;

	data = [ 2.0, 3.0, 5.0 ];
	acc = incrmhmean( 2 );
	for ( i = 0; i < data.length; i++ ) {
		acc( data[ i ] );
	}
	actual = acc();
	expected = 3.75; // Note: computed by hand using textbook formula
	delta = abs( expected - actual );
	tol = 1.1 * EPSILON * abs( expected );
	t.equal( delta <= tol, true, 'within tolerance. Expected: '+expected+'. Actual: '+actual+'. Delta: '+delta+'. Tol: '+tol+'.' );
	t.end();
});

tape( 'if data has yet to be provided, the accumulator function returns `null`', function test( t ) {
	var acc = incrmhmean( 3 );
	t.equal( acc(), null, 'returns null' );
	t.end();
});

tape( 'if provided `NaN`, the accumulated value is `NaN` for at least `W` invocations', function test( t ) {
	var expected;
	var data;
	var acc;
	var v;
	var i;

	acc = incrmhmean( 3 );

	data = [
		NaN,  // NaN
		3.14, // NaN, 3.14
		3.14, // NaN, 3.14, 3.14
		NaN,  // 3.14, 3.14, NaN
		3.14, // 3.14, NaN, 3.14
		3.14, // NaN, 3.14, 3.14
		3.14, // 3.14, 3.14, 3.14
		NaN,  // 3.14, 3.14, NaN
		3.14, // 3.14, NaN, 3.14
		3.14, // NaN, 3.14, 3.14
		3.14, // 3.14, 3.14, 3.14
		NaN,  // 3.14, 3.14, NaN
		3.14, // 3.14, NaN, 3.14
		3.14, // NaN, 3.14, 3.14
		NaN,  // 3.14, 3.14, NaN
		NaN,  // 3.14, NaN, NaN
		NaN,  // NaN, NaN, NaN
		NaN,  // NaN, NaN, NaN
		3.14  // NaN, NaN, 3.14
	];
	expected = [
		NaN,
		NaN,
		NaN,
		NaN,
		NaN,
		NaN,
		3.14,
		NaN,
		NaN,
		NaN,
		3.14,
		NaN,
		NaN,
		NaN,
		NaN,
		NaN,
		NaN,
		NaN,
		NaN
	];
	for ( i = 0; i < data.length; i++ ) {
		v = acc( data[ i ] );
		if ( isnan( expected[ i ] ) ) {
			t.equal( isnan( v ), true, 'returns expected value for window '+i );
		} else {
			t.equal( v, expected[ i ], 'returns expected value for window '+i );
		}
	}
	t.end();
});
<|endoftext|>