<commit_before>const gulp = require('gulp');
const gulpLoadPlugins = require('gulp-load-plugins');
const del = require('del');
const $ = gulpLoadPlugins();
const bower = require('./bower.json');
const fs = require('fs');
const ssri = require('ssri');

// ===============================================================
// PLUGIN SETTINGS SHARED ACCROSS MULTIPLE TASKS
// ===============================================================
const revManifestsBase = '.tmp/rev-manifests';

// ===============================================================
// ENVIROMENT VARIABLES
// ===============================================================
let ENV = 'dist';
let DEST = 'dist';

const setEnvDev = () => new Promise((resolve, reject) => {
							ENV = 'dev';
							resolve();
						});

const setDestDev = () => new Promise((resolve, reject) => {
							DEST = 'dev';
							resolve();
						});

// ===============================================================
// CLEAN
// ===============================================================
// Empty directories to start fresh.
const clean = () => del(['.tmp', 'dev', 'dist']);

// ===============================================================
// SCSS -> CSS
// ===============================================================
const sass = () => gulp.src('src/assets/scss/*.scss')
					.pipe($.plumber())
					.pipe($.sass({
						includePaths: ['src/assets/scss', 'bower_components'],
						precision: 6
					}).on('error', $.sass.logError))
					.pipe(gulp.dest('.tmp/css/compiled'));

// ===============================================================
// CONCAT CSS
// ===============================================================
// Source should be compiled CSS (.tmp/css/copmiled), resp. vendor CSS (bower_components resp. src/assets/vendor/css).
const concatCSS = () => gulp.src([
							'bower_components/normalize.css/normalize.css',
							'.tmp/css/compiled/main.css'
						])
						.pipe($.concat('main.css'))
						.pipe(gulp.dest('.tmp/css/concated'));

// ===============================================================
// CSS PROCESSING
// ===============================================================
const processCSS = () => {
	var stream = gulp.src('.tmp/css/concated/**/*.css')
		.pipe($.autoprefixer());

	if ( ENV == 'dist' ) {
		return stream
			.pipe($.combineMq())
			.pipe($.cleanCss())
			.pipe($.rev())
			.pipe(gulp.dest(DEST + '/assets/css'))
			.pipe($.rev.manifest(revManifestsBase + '/css.json', {
				base: revManifestsBase
			}))
			.pipe(gulp.dest(revManifestsBase));
	}
	else {
		return stream
			.pipe($.combineMq())
			.pipe(gulp.dest(DEST + '/assets/css'))
			.pipe($.connect.reload());
	}
};

// ===============================================================
// MAIN CSS TASK
// ===============================================================
const css = gulp.series(sass, concatCSS, processCSS);

// ===============================================================
// CONCAT JS
// ===============================================================
const concatJSMain = () => gulp.src([
								'src/assets/js/plugins.js',
								'src/assets/js/main.js'
							])
							.pipe($.concat('main.js'))
							.pipe(gulp.dest('.tmp/js/concated'));

const concatJS = gulp.series(
	concatJSMain
);

// ===============================================================
// JS PROCESSING
// ===============================================================
const processJS = () => {
	var stream = gulp.src('.tmp/js/concated/**/*.js');

	if ( ENV == 'dist' ) {
		return stream
			.pipe($.uglify())
			.pipe($.rev())
			.pipe(gulp.dest(DEST + '/assets/js'))
			.pipe($.rev.manifest(revManifestsBase + '/js.json', {
				base: revManifestsBase
			}))
			.pipe(gulp.dest(revManifestsBase));
	}
	else {
		return stream
			.pipe(gulp.dest(DEST + '/assets/js'))
			.pipe($.connect.reload());
	}
};

// ===============================================================
// MAIN JS TASK
// ===============================================================
const js = gulp.series(concatJS, processJS);

// ===============================================================
// IMAGE PROCESSING
// ===============================================================
const img = () => gulp.src([
						'src/assets/img/**/*.{gif,jpg,png,svg}'
					])
					.pipe($.if(ENV == 'dist', $.imagemin()))
					.pipe(gulp.dest(DEST + '/assets/img'))
					.pipe($.connect.reload());

// ===============================================================
// COPY FILES
// ===============================================================
const copyMisc = () => gulp.src([
							'src/robots.txt',
							'src/browserconfig.xml',
							'src/*.{ico,png,svg}', // icons
							'src/assets/font/**/*.{woff,woff2}',
							'!src/assets/font/original/**/*'
						], {
							base: 'src'
						})
						.pipe(gulp.dest(DEST))
						.pipe($.connect.reload());

const copyModules = () => gulp.src([
								'node_modules/apache-server-configs/dist/.htaccess'
							])
							.pipe(gulp.dest(DEST));

const copyJQuery = () => gulp.src([
								'bower_components/jquery/dist/jquery.min.js'
							])
							.pipe($.rename('jquery-'+bower.dependencies.jquery+'.min.js'))
							.pipe(gulp.dest(DEST + '/assets/js/vendor'));

const copy = gulp.parallel(
	copyMisc,
	copyModules,
	copyJQuery
);

// ===============================================================
// HTML PROCESSING
// ===============================================================
const html = () => {
	var manifests = gulp.src(revManifestsBase + '/*.json'),
		jquerySRIHash = ssri.fromData(
			fs.readFileSync('bower_components/jquery/dist/jquery.min.js'),
			{ algorithms: ['sha256'] }
		);

	return gulp.src('src/templates/pages/**/*.twig')
		.pipe($.twig({
			data: {
				jquery: {
					version: bower.dependencies.jquery,
					sri_hash: jquerySRIHash
				}
			},
			errorLogToConsole: true,
			extname: '.html'
		}))
		.pipe($.if(ENV == 'dist', $.revReplace({
			canonicalUris: false,
			replaceInExtensions: ['.html'],
			manifest: manifests
		})))
		.pipe($.if(ENV == 'dist', $.htmlmin({
			processConditionalComments: true,
			removeComments: true,
			removeCommentsFromCDATA: true,
			removeCDATASectionsFromCDATA: true,
			collapseWhitespace: true,
			conservativeCollapse: true,
			collapseInlineTagWhitespace: true,
			collapseBooleanAttributes: true,
			removeTagWhitespace: true,
			removeAttributeQuotes: true,
			removeRedundantAttributes: true,
			useShortDoctype: true,
			removeEmptyAttributes: true,
			removeScriptTypeAttributes: true,
			removeOptionalTags: true,
			decodeEntities: true,
			minifyJS: true,
			minifyCSS: true,
			quoteCharacter: '"'
		})))
		.pipe(gulp.dest(DEST))
		.pipe($.connect.reload());
};

// ===============================================================
// SERVER
// ===============================================================
// Run a local server at http://localhost:8000.
const connect = () => new Promise((resolve, reject) => {
	$.connect.server({
		root: DEST,
		port: 8000,
		livereload: true
	});
	resolve();
});

// ===============================================================
// BUILD
// ===============================================================
const build = gulp.series(
	clean,
	gulp.parallel(
		// process HTML after CSS & JS are revisioned
		gulp.series(
			gulp.parallel(css, js),
			html
		),
		img,
		copy
	)
);

// ===============================================================
// SERVE
// ===============================================================
const serve = gulp.series(build, connect);

// ===============================================================
// DEVELOPMENT TASKS
// ===============================================================
const watchFiles = () => new Promise((resolve, reject) => {
	gulp.watch('src/assets/scss/**/*.scss', css);
	gulp.watch('src/assets/js/**/*.js', js);
	gulp.watch(['src/assets/img/**/*.{gif,jpg,png,svg}'], img);
	gulp.watch(['src/assets/font/**/*.{woff,woff2}', '!src/assets/font/original/**/*'], copy);
	gulp.watch('src/templates/**/*.twig', html);
	resolve();
});

const defaultTasks = gulp.series(
	setEnvDev,
	setDestDev,
	clean,
	gulp.parallel(css, js, img, copy, html),
	connect,
	watchFiles
);

// ===============================================================
// EXPORT TASKS FOR CLI
// ===============================================================
module.exports = {
	build: build,
	connect: connect,
	serve: serve,
	default: defaultTasks
};
<commit_msg>`var` -> `const` & `let`<commit_after>const gulp = require('gulp');
const gulpLoadPlugins = require('gulp-load-plugins');
const del = require('del');
const $ = gulpLoadPlugins();
const bower = require('./bower.json');
const fs = require('fs');
const ssri = require('ssri');

// ===============================================================
// PLUGIN SETTINGS SHARED ACCROSS MULTIPLE TASKS
// ===============================================================
const revManifestsBase = '.tmp/rev-manifests';

// ===============================================================
// ENVIROMENT VARIABLES
// ===============================================================
let ENV = 'dist';
let DEST = 'dist';

const setEnvDev = () => new Promise((resolve, reject) => {
							ENV = 'dev';
							resolve();
						});

const setDestDev = () => new Promise((resolve, reject) => {
							DEST = 'dev';
							resolve();
						});

// ===============================================================
// CLEAN
// ===============================================================
// Empty directories to start fresh.
const clean = () => del(['.tmp', 'dev', 'dist']);

// ===============================================================
// SCSS -> CSS
// ===============================================================
const sass = () => gulp.src('src/assets/scss/*.scss')
					.pipe($.plumber())
					.pipe($.sass({
						includePaths: ['src/assets/scss', 'bower_components'],
						precision: 6
					}).on('error', $.sass.logError))
					.pipe(gulp.dest('.tmp/css/compiled'));

// ===============================================================
// CONCAT CSS
// ===============================================================
// Source should be compiled CSS (.tmp/css/copmiled), resp. vendor CSS (bower_components resp. src/assets/vendor/css).
const concatCSS = () => gulp.src([
							'bower_components/normalize.css/normalize.css',
							'.tmp/css/compiled/main.css'
						])
						.pipe($.concat('main.css'))
						.pipe(gulp.dest('.tmp/css/concated'));

// ===============================================================
// CSS PROCESSING
// ===============================================================
const processCSS = () => {
	const stream = gulp.src('.tmp/css/concated/**/*.css')
		.pipe($.autoprefixer());

	if ( ENV == 'dist' ) {
		return stream
			.pipe($.combineMq())
			.pipe($.cleanCss())
			.pipe($.rev())
			.pipe(gulp.dest(DEST + '/assets/css'))
			.pipe($.rev.manifest(revManifestsBase + '/css.json', {
				base: revManifestsBase
			}))
			.pipe(gulp.dest(revManifestsBase));
	}
	else {
		return stream
			.pipe($.combineMq())
			.pipe(gulp.dest(DEST + '/assets/css'))
			.pipe($.connect.reload());
	}
};

// ===============================================================
// MAIN CSS TASK
// ===============================================================
const css = gulp.series(sass, concatCSS, processCSS);

// ===============================================================
// CONCAT JS
// ===============================================================
const concatJSMain = () => gulp.src([
								'src/assets/js/plugins.js',
								'src/assets/js/main.js'
							])
							.pipe($.concat('main.js'))
							.pipe(gulp.dest('.tmp/js/concated'));

const concatJS = gulp.series(
	concatJSMain
);

// ===============================================================
// JS PROCESSING
// ===============================================================
const processJS = () => {
	const stream = gulp.src('.tmp/js/concated/**/*.js');

	if ( ENV == 'dist' ) {
		return stream
			.pipe($.uglify())
			.pipe($.rev())
			.pipe(gulp.dest(DEST + '/assets/js'))
			.pipe($.rev.manifest(revManifestsBase + '/js.json', {
				base: revManifestsBase
			}))
			.pipe(gulp.dest(revManifestsBase));
	}
	else {
		return stream
			.pipe(gulp.dest(DEST + '/assets/js'))
			.pipe($.connect.reload());
	}
};

// ===============================================================
// MAIN JS TASK
// ===============================================================
const js = gulp.series(concatJS, processJS);

// ===============================================================
// IMAGE PROCESSING
// ===============================================================
const img = () => gulp.src([
						'src/assets/img/**/*.{gif,jpg,png,svg}'
					])
					.pipe($.if(ENV == 'dist', $.imagemin()))
					.pipe(gulp.dest(DEST + '/assets/img'))
					.pipe($.connect.reload());

// ===============================================================
// COPY FILES
// ===============================================================
const copyMisc = () => gulp.src([
							'src/robots.txt',
							'src/browserconfig.xml',
							'src/*.{ico,png,svg}', // icons
							'src/assets/font/**/*.{woff,woff2}',
							'!src/assets/font/original/**/*'
						], {
							base: 'src'
						})
						.pipe(gulp.dest(DEST))
						.pipe($.connect.reload());

const copyModules = () => gulp.src([
								'node_modules/apache-server-configs/dist/.htaccess'
							])
							.pipe(gulp.dest(DEST));

const copyJQuery = () => gulp.src([
								'bower_components/jquery/dist/jquery.min.js'
							])
							.pipe($.rename('jquery-'+bower.dependencies.jquery+'.min.js'))
							.pipe(gulp.dest(DEST + '/assets/js/vendor'));

const copy = gulp.parallel(
	copyMisc,
	copyModules,
	copyJQuery
);

// ===============================================================
// HTML PROCESSING
// ===============================================================
const html = () => {
	const manifests = gulp.src(revManifestsBase + '/*.json');
	const jquerySRIHash = ssri.fromData(
			fs.readFileSync('bower_components/jquery/dist/jquery.min.js'),
			{ algorithms: ['sha256'] }
		);

	return gulp.src('src/templates/pages/**/*.twig')
		.pipe($.twig({
			data: {
				jquery: {
					version: bower.dependencies.jquery,
					sri_hash: jquerySRIHash
				}
			},
			errorLogToConsole: true,
			extname: '.html'
		}))
		.pipe($.if(ENV == 'dist', $.revReplace({
			canonicalUris: false,
			replaceInExtensions: ['.html'],
			manifest: manifests
		})))
		.pipe($.if(ENV == 'dist', $.htmlmin({
			processConditionalComments: true,
			removeComments: true,
			removeCommentsFromCDATA: true,
			removeCDATASectionsFromCDATA: true,
			collapseWhitespace: true,
			conservativeCollapse: true,
			collapseInlineTagWhitespace: true,
			collapseBooleanAttributes: true,
			removeTagWhitespace: true,
			removeAttributeQuotes: true,
			removeRedundantAttributes: true,
			useShortDoctype: true,
			removeEmptyAttributes: true,
			removeScriptTypeAttributes: true,
			removeOptionalTags: true,
			decodeEntities: true,
			minifyJS: true,
			minifyCSS: true,
			quoteCharacter: '"'
		})))
		.pipe(gulp.dest(DEST))
		.pipe($.connect.reload());
};

// ===============================================================
// SERVER
// ===============================================================
// Run a local server at http://localhost:8000.
const connect = () => new Promise((resolve, reject) => {
	$.connect.server({
		root: DEST,
		port: 8000,
		livereload: true
	});
	resolve();
});

// ===============================================================
// BUILD
// ===============================================================
const build = gulp.series(
	clean,
	gulp.parallel(
		// process HTML after CSS & JS are revisioned
		gulp.series(
			gulp.parallel(css, js),
			html
		),
		img,
		copy
	)
);

// ===============================================================
// SERVE
// ===============================================================
const serve = gulp.series(build, connect);

// ===============================================================
// DEVELOPMENT TASKS
// ===============================================================
const watchFiles = () => new Promise((resolve, reject) => {
	gulp.watch('src/assets/scss/**/*.scss', css);
	gulp.watch('src/assets/js/**/*.js', js);
	gulp.watch(['src/assets/img/**/*.{gif,jpg,png,svg}'], img);
	gulp.watch(['src/assets/font/**/*.{woff,woff2}', '!src/assets/font/original/**/*'], copy);
	gulp.watch('src/templates/**/*.twig', html);
	resolve();
});

const defaultTasks = gulp.series(
	setEnvDev,
	setDestDev,
	clean,
	gulp.parallel(css, js, img, copy, html),
	connect,
	watchFiles
);

// ===============================================================
// EXPORT TASKS FOR CLI
// ===============================================================
module.exports = {
	build: build,
	connect: connect,
	serve: serve,
	default: defaultTasks
};
<|endoftext|>


<commit_before>var dns = require( 'dns' )
var DKIM = require( './dkim' )

/**
 * Retrieve a domain key
 * @memberOf DKIM
 * @todo DNS seems to FORMERR on unregistered / expired domains,
 * which maybe should be a TEMPFAIL (?)
 * @todo make this `public_key = dkim_find_key(q_val, d_val, s_val)`,
 * where `*_val` are the signature's attribute values
 * @todo Throw error if the public key is not a Buffer
 * @param {String} domain
 * @param {String} [selector]
 * @param {Function} callback
 */
function getKey( domain, selector, callback ) {

  if( typeof selector === 'function' ) {
    callback = selector
    selector = null
  } else {
    domain = selector + '._domainkey.' + domain
  }

  dns.resolve( domain, 'TXT', function( error, records ) {

    var key = null

    if( error == null ) {

      var keys = records.map(( record ) => record.join( '' ))

      if( !keys.length ) {
        error = new Error( 'No key for signature' )
        error.code = DKIM.PERMFAIL
        return void callback( error, key )
      }

      if( keys.length > 1 ) {
        return callback( new Error( 'Ambigous key selection' ) )
      }

      // If the result returned from the query does not adhere to the
      // format defined in this specification, the Verifier MUST ignore
      // the key record and return PERMFAIL (key syntax error).
      try {
        key = DKIM.Key.parse( keys[0] )
        if( !Buffer.isBuffer( key.key ) ) {
          throw new Error( 'No public key found' )
        }
      } catch( e ) {
        error = new Error( 'Key syntax error' )
        error.code = DKIM.PERMFAIL
      }

    } else {
      switch( error.code ) {
        // If the query for the public key fails because the corresponding
        // key record does not exist, the Verifier MUST immediately return
        // PERMFAIL (no key for signature).
        case dns.NOTFOUND:
        case dns.NODATA:
        case dns.FORMERR:
        case dns.REFUSED:
          error.code = DKIM.PERMFAIL
          break
        // If the query for the public key fails to respond, the Verifier
        // MAY seek a later verification attempt by returning TEMPFAIL
        // (key unavailable).
        default:
          error.code = DKIM.TEMPFAIL
          break
      }
    }

    callback( error, key )

  })

}

module.exports = getKey
<commit_msg>feat(lib): TEMPFAIL on ambiguous key selection<commit_after>var dns = require( 'dns' )
var DKIM = require( './dkim' )

/**
 * Retrieve a domain key
 * @memberOf DKIM
 * @todo DNS seems to FORMERR on unregistered / expired domains,
 * which maybe should be a TEMPFAIL (?)
 * @todo make this `public_key = dkim_find_key(q_val, d_val, s_val)`,
 * where `*_val` are the signature's attribute values
 * @todo Throw error if the public key is not a Buffer
 * @param {String} domain
 * @param {String} [selector]
 * @param {Function} callback
 */
function getKey( domain, selector, callback ) {

  if( typeof selector === 'function' ) {
    callback = selector
    selector = null
  } else {
    domain = selector + '._domainkey.' + domain
  }

  dns.resolve( domain, 'TXT', function( error, records ) {

    var key = null

    if( error == null ) {

      var keys = records.map(( record ) => record.join( '' ))

      if( !keys.length ) {
        error = new Error( 'No key for signature' )
        error.code = DKIM.PERMFAIL
        return void callback( error, key )
      }

      if( keys.length > 1 ) {
        error = new Error( 'Ambiguous key selection' )
        error.code = DKIM.TEMPFAIL
        return void callback( error, key )
      }

      // If the result returned from the query does not adhere to the
      // format defined in this specification, the Verifier MUST ignore
      // the key record and return PERMFAIL (key syntax error).
      try {
        key = DKIM.Key.parse( keys[0] )
        if( !Buffer.isBuffer( key.key ) ) {
          throw new Error( 'No public key found' )
        }
      } catch( e ) {
        error = new Error( 'Key syntax error' )
        error.code = DKIM.PERMFAIL
      }

    } else {
      switch( error.code ) {
        // If the query for the public key fails because the corresponding
        // key record does not exist, the Verifier MUST immediately return
        // PERMFAIL (no key for signature).
        case dns.NOTFOUND:
        case dns.NODATA:
        case dns.FORMERR:
        case dns.REFUSED:
          error.code = DKIM.PERMFAIL
          break
        // If the query for the public key fails to respond, the Verifier
        // MAY seek a later verification attempt by returning TEMPFAIL
        // (key unavailable).
        default:
          error.code = DKIM.TEMPFAIL
          break
      }
    }

    callback( error, key )

  })

}

module.exports = getKey
<|endoftext|>


<commit_before><commit_msg>#249 Always bind mouse events since touch detecting return false positives in some cases<commit_after><|endoftext|>


<commit_before>/*
 *   User ship
 */
if(typeof(require) !== 'undefined'){
	var helpers = require("./helpers").helpers;
	var entity = require("./entity").entity;
	var explosion = require("./explosion").explosion;
	var colors;
	var sys = require("sys");
	for(var s in colors){
		sys.puts(s);
	};
	var laserbeam = require("./laserbeam").laserbeam;
	// AI
	var engine = require("./engine").engine;
	require('./ai/heuristic.js');
	require('./ai/prioritizing.js');
}

var ship = function(config){
	helpers.apply(config, this);
	this.type = this.type || 'player'; // player, computer
	this.laserState = 300; // 10 = ready, 0 = charging
	this.direction = this.direction || 1;
	this.colors = colors ? colors : require("./rules").colors;
	this.color = this.colors[this.colorIndex] || this.color || "#FFF";
	this.speed = 3;
	this.colorLoop = 0;
	this.invulerability = 1000;
	this.audioDone = false;
	this.name = this.name || 'ship';
	this.position = this.position || {x:0, y:0};
	this.gunOffset =  {x:40, y: 0};
	this.collisionRect = {x: -15, y: -10, w: 30,h: 20};
	this.modelIndex = 0;
	this.rectsRight = [
		{x: -20, y: -15, w: 20, h: 10},
		{x: -10, y: -5, w: 30, h: 10},
		{x: -20, y: 5, w: 20, h: 10}
	];
	this.rectsLeft = [
		{x: 0, y: -15, w: 20, h: 10},
		{x: -20, y: -5, w: 30, h: 10},
		{x: 0, y: 5, w: 20, h: 10}
	];
};

ship.prototype = new entity();

ship.prototype.getTimeDelta = function(){
	if(!this.lastTimeCalled){
		this.lastTimeCalled = time;
	}
	var timeDelta = time - this.lastTimeCalled;
	this.lastTimeCalled = time;
	return timeDelta;
};

ship.prototype.update = function(time){
	var timeDelta = this.getTimeDelta();
	if(this.engine.mode !== 'client'){
		if(this.invulerability){
			this.invulerability -= timeDelta;
			if(this.invulerability < 0){
				this.invulerability = 0;
			}
		}
//		if(!this.engine.gameState.gameOver && (this.collisions && this.collisions.length)){
//			for(var i = 0; i < this.collisions.length; i++){
//				if(this.collisions[i].owner != this && !(this.invulerability && this.collisions[i] == this.spawnStar)){
//					if(!this.finished && this.collisions[i].owner == this.engine.gameState.player1Ship && this == this.engine.gameState.player2Ship){
//						this.engine.gameState.player1Score++;
//					}
//					if(!this.finished && this.collisions[i].owner == this.engine.gameState.player2Ship && this == this.engine.gameState.player1Ship){
//						this.engine.gameState.player2Score++;
//					}
//					this.finished = true;
//				}
//			}
//		}
		if(this.collisions && this.collisions.length){
			for(var i = 0; i < this.collisions.length; i++){
				var collider = this.collisions[i];
				if(collider.owner != this && !(this.invulerability && collider == this.spawnStar)){
					if(collider.parent && collider.type === 'star' && collider.color !== this.color){
						collider.finished = true;
					}
					this.finished = true;
					break;
				}
			}
		}
		this.updateControllerState();
	}
	this.move(timeDelta);
	if(this.engine.mode !== 'client'){
		this.updateLaser(timeDelta);
	}
};

ship.prototype.onRemove = function(){
	if(this.engine.mode !== 'server'){
		// The server does not care about the explosion as it is just a visual
		this.engine.add(new explosion({
			position: this.position
		}));
	}
};

ship.prototype.move = function(timeDelta){
	var previousPosition = this.position;
	this.position = this.calculateMovement(this.position, this.mousePosition, 10, timeDelta);
	if(this.position.x > previousPosition.x){
		this.direction = 1;
	}
	else if(this.position.x < previousPosition.x){
		this.direction = -1;
	}
	this.classicModel = this.direction === 1 ? this.rectsRight : this.rectsLeft;
};

ship.prototype.updateLaser = function(timeDelta){
	if(this.shoot && this.laserState >= 300){
		this.laserState = 0;
		this.gunOffset.x = this.direction === 1 ? 40 : -40;
		this.engine.add(new laserbeam({
			position: {x:this.position.x + this.gunOffset.x, y:this.position.y + this.gunOffset.y},
			direction: this.direction,
			owner: this
		}));
	}
	else if(this.laserState < 300){
		this.laserState = this.laserState + timeDelta;
	}
	else{
		this.laserState = 300;
	}
};

ship.prototype.updateControllerState = function(){
	// This will determine, for every ship, the state of the related controller
	// Specifically it will set the 'shoot' and 'mousePosition' values.
	this.shoot = false;
	if(this.type != 'computer'){
		// If the player is a human, get the controller values from the engine
		// This works the same for the server and the stand-alone modes.
		if(this.engine.mode == 'standalone' || (this.name == "Player 1" && this.engine.player1)){
			this.shoot = this.engine.buttonDown;
			this.mousePosition = this.correctMousePosition( this.engine.mousePosition, this.engine.absoluteController );

		}
		else if(this.name == "Player 2" && this.engine.player2){
			this.shoot = this.engine.buttonDown2;
			this.mousePosition = this.engine.mousePosition2;
		}
	}
	else if(this.type == 'computer'){
		// In the case of AI the active AI will set the controller
		var controls;
		if(this.name === 'Player 1'){
			controls = engine.ai[engine.player1ai].call(this);
		}
		else {
			controls = engine.ai[engine.player2ai].call(this);
		}
		this.mousePosition = controls.mousePosition;
		this.shoot = controls.shoot;
	}
};

ship.prototype.correctMousePosition = function(newPosition, absolute){
	if(absolute){
		return newPosition;
	}
	else {
		return {
			x: newPosition.x + this.position.x,
			y: newPosition.y + this.position.y
		};
	}
};

ship.prototype.calculateMovement = function(currentPosition, mousePosition, speedLimit, timeDelta){
	var deltaX = mousePosition.x - currentPosition.x;
	var deltaY = mousePosition.y - currentPosition.y;
	var distance = helpers.distance(currentPosition, mousePosition);
	var f = 0.25;
	var speed = speedLimit * (timeDelta / 35);
	if(distance > speed){
		f = speed / distance;
	}
	return {
		x: this.position.x + (deltaX * f),
		y: this.position.y + (deltaY * f)
	};
};

ship.prototype.render = function(){
	if(!this.audioDone){
		this.audioDone = true;
		try{
		if(audio){
			audio.appearAudio.play();
		}}catch(ex){}
	}
};

ship.prototype.getRemoteData = function(){
	if(this.mousePosition){
		var mouseX = Math.ceil(this.mousePosition.x);
		var mouseY = Math.ceil(this.mousePosition.y);
		if(!this.previousMousePosition || mouseX !== this.previousMousePosition.x || mouseY !== this.previousMousePosition.y){
			this.previousMousePosition = {
				x: mouseX,
				y: mouseY
			};
			var result = "0," + Math.ceil(this.position.x) + "," +
			              Math.ceil(this.position.y) + "," +
			              this.colorIndex + "," +
		        		  mouseX + "," +
			              mouseY;
		}
	}
	return result;
};

ship.prototype.renderRemoteData = function(remoteData, offset){
	this.classicModel = this.direction === 1  ? this.rectsRight : this.rectsLeft;
	this.position = {x:parseInt(remoteData[offset + 1]), y: parseInt(remoteData[offset + 2])};
	this.mousePosition = {x:parseInt(remoteData[offset + 4]), y: parseInt(remoteData[offset + 5])};
	this.colorIndex = parseInt(remoteData[offset + 3]);
	this.color = this.colors[this.colorIndex];
	return offset + 6;
};

if(typeof(exports) !== 'undefined'){
	exports.ship = ship;
}
<commit_msg>Prevent space ships from flying of the screen<commit_after>/*
 *   User ship
 */
if(typeof(require) !== 'undefined'){
	var helpers = require("./helpers").helpers;
	var entity = require("./entity").entity;
	var explosion = require("./explosion").explosion;
	var colors;
	var sys = require("sys");
	for(var s in colors){
		sys.puts(s);
	};
	var laserbeam = require("./laserbeam").laserbeam;
	// AI
	var engine = require("./engine").engine;
	require('./ai/heuristic.js');
	require('./ai/prioritizing.js');
}

var ship = function(config){
	helpers.apply(config, this);
	this.type = this.type || 'player'; // player, computer
	this.laserState = 300; // 10 = ready, 0 = charging
	this.direction = this.direction || 1;
	this.colors = colors ? colors : require("./rules").colors;
	this.color = this.colors[this.colorIndex] || this.color || "#FFF";
	this.speed = 3;
	this.colorLoop = 0;
	this.invulerability = 1000;
	this.audioDone = false;
	this.name = this.name || 'ship';
	this.position = this.position || {x:0, y:0};
	this.gunOffset =  {x:40, y: 0};
	this.collisionRect = {x: -15, y: -10, w: 30,h: 20};
	this.modelIndex = 0;
	this.rectsRight = [
		{x: -20, y: -15, w: 20, h: 10},
		{x: -10, y: -5, w: 30, h: 10},
		{x: -20, y: 5, w: 20, h: 10}
	];
	this.rectsLeft = [
		{x: 0, y: -15, w: 20, h: 10},
		{x: -20, y: -5, w: 30, h: 10},
		{x: 0, y: 5, w: 20, h: 10}
	];
};

ship.prototype = new entity();

ship.prototype.getTimeDelta = function(){
	if(!this.lastTimeCalled){
		this.lastTimeCalled = time;
	}
	var timeDelta = time - this.lastTimeCalled;
	this.lastTimeCalled = time;
	return timeDelta;
};

ship.prototype.update = function(time){
	var timeDelta = this.getTimeDelta();
	if(this.engine.mode !== 'client'){
		if(this.invulerability){
			this.invulerability -= timeDelta;
			if(this.invulerability < 0){
				this.invulerability = 0;
			}
		}
//		if(!this.engine.gameState.gameOver && (this.collisions && this.collisions.length)){
//			for(var i = 0; i < this.collisions.length; i++){
//				if(this.collisions[i].owner != this && !(this.invulerability && this.collisions[i] == this.spawnStar)){
//					if(!this.finished && this.collisions[i].owner == this.engine.gameState.player1Ship && this == this.engine.gameState.player2Ship){
//						this.engine.gameState.player1Score++;
//					}
//					if(!this.finished && this.collisions[i].owner == this.engine.gameState.player2Ship && this == this.engine.gameState.player1Ship){
//						this.engine.gameState.player2Score++;
//					}
//					this.finished = true;
//				}
//			}
//		}
		if(this.collisions && this.collisions.length){
			for(var i = 0; i < this.collisions.length; i++){
				var collider = this.collisions[i];
				if(collider.owner != this && !(this.invulerability && collider == this.spawnStar)){
					if(collider.parent && collider.type === 'star' && collider.color !== this.color){
						collider.finished = true;
					}
					this.finished = true;
					break;
				}
			}
		}
		this.updateControllerState();
	}
	this.move(timeDelta);
	if(this.engine.mode !== 'client'){
		this.updateLaser(timeDelta);
	}
};

ship.prototype.onRemove = function(){
	if(this.engine.mode !== 'server'){
		// The server does not care about the explosion as it is just a visual
		this.engine.add(new explosion({
			position: this.position
		}));
	}
};

ship.prototype.move = function(timeDelta){
	var previousPosition = this.position;
	this.position = this.calculateMovement(this.position, this.mousePosition, 10, timeDelta);
	if(this.position.x > previousPosition.x){
		this.direction = 1;
	}
	else if(this.position.x < previousPosition.x){
		this.direction = -1;
	}
	this.classicModel = this.direction === 1 ? this.rectsRight : this.rectsLeft;
};

ship.prototype.updateLaser = function(timeDelta){
	if(this.shoot && this.laserState >= 300){
		this.laserState = 0;
		this.gunOffset.x = this.direction === 1 ? 40 : -40;
		this.engine.add(new laserbeam({
			position: {x:this.position.x + this.gunOffset.x, y:this.position.y + this.gunOffset.y},
			direction: this.direction,
			owner: this
		}));
	}
	else if(this.laserState < 300){
		this.laserState = this.laserState + timeDelta;
	}
	else{
		this.laserState = 300;
	}
};

ship.prototype.updateControllerState = function(){
	// This will determine, for every ship, the state of the related controller
	// Specifically it will set the 'shoot' and 'mousePosition' values.
	this.shoot = false;
	if(this.type != 'computer'){
		// If the player is a human, get the controller values from the engine
		// This works the same for the server and the stand-alone modes.
		if(this.engine.mode == 'standalone' || (this.name == "Player 1" && this.engine.player1)){
			this.shoot = this.engine.buttonDown;
			this.mousePosition = this.correctMousePosition( this.engine.mousePosition, this.engine.absoluteController );

		}
		else if(this.name == "Player 2" && this.engine.player2){
			this.shoot = this.engine.buttonDown2;
			this.mousePosition = this.engine.mousePosition2;
		}
	}
	else if(this.type == 'computer'){
		// In the case of AI the active AI will set the controller
		var controls;
		if(this.name === 'Player 1'){
			controls = engine.ai[engine.player1ai].call(this);
		}
		else {
			controls = engine.ai[engine.player2ai].call(this);
		}
		this.mousePosition = controls.mousePosition;
		this.shoot = controls.shoot;
	}
};

ship.prototype.correctMousePosition = function(newPosition, absolute){
	if(absolute){
		return newPosition;
	}
	else {
		return {
			x: newPosition.x + this.position.x,
			y: newPosition.y + this.position.y
		};
	}
};

ship.prototype.calculateMovement = function(currentPosition, mousePosition, speedLimit, timeDelta){
	var deltaX = mousePosition.x - currentPosition.x;
	var deltaY = mousePosition.y - currentPosition.y;
	var distance = helpers.distance(currentPosition, mousePosition);
	var f = 0.25;
	var speed = speedLimit * (timeDelta / 35);
	if(distance > speed){
		f = speed / distance;
	}
	var newX = this.position.x + (deltaX * f);
	var newY = this.position.y + (deltaY * f);
	if(newX < 0){
		newX = 0;
	}
	if(newX > this.engine.width){
		newX = this.engine.width;
	}
	if(newY < 0){
		newY = 0;
	}
	if(newY > this.engine.height){
		newY = this.engine.height;
	}
	return {
		x: newX,
		y: newY
	};
};

ship.prototype.render = function(){
	if(!this.audioDone){
		this.audioDone = true;
		try{
		if(audio){
			audio.appearAudio.play();
		}}catch(ex){}
	}
};

ship.prototype.getRemoteData = function(){
	if(this.mousePosition){
		var mouseX = Math.ceil(this.mousePosition.x);
		var mouseY = Math.ceil(this.mousePosition.y);
		if(!this.previousMousePosition || mouseX !== this.previousMousePosition.x || mouseY !== this.previousMousePosition.y){
			this.previousMousePosition = {
				x: mouseX,
				y: mouseY
			};
			var result = "0," + Math.ceil(this.position.x) + "," +
			              Math.ceil(this.position.y) + "," +
			              this.colorIndex + "," +
		        		  mouseX + "," +
			              mouseY;
		}
	}
	return result;
};

ship.prototype.renderRemoteData = function(remoteData, offset){
	this.classicModel = this.direction === 1  ? this.rectsRight : this.rectsLeft;
	this.position = {x:parseInt(remoteData[offset + 1]), y: parseInt(remoteData[offset + 2])};
	this.mousePosition = {x:parseInt(remoteData[offset + 4]), y: parseInt(remoteData[offset + 5])};
	this.colorIndex = parseInt(remoteData[offset + 3]);
	this.color = this.colors[this.colorIndex];
	return offset + 6;
};

if(typeof(exports) !== 'undefined'){
	exports.ship = ship;
}
<|endoftext|>


<commit_before>// maybe we could do a grid of moves and their genres?
// like a matrix
// http://codepen.io/bishopsmove/pen/AlHmc

TimeLineVis = function(_parentElement, _session) {
    var self = this;

     self.timelineVisKeys = [
        'Title',
        'Year',
        'imdbRating',
        'tomatoRating',
        'tomatoUserRating'
    ]

    self.parentElement = _parentElement;

    //Link movie data to timelineVis 'data'
    self.data = nanToZero(
        _session.get('actorMovies'),
        self.timelineVisKeys
    );

    self.displayData = [];
    self.initVis();
};

TimeLineVis.prototype.initVis = function () {

    //copy global data to be visible to this function
    var self = this;

    //define some canvas variables
    var width = 960;
    var height = 500;
    var margin = {top: 30, right: 10, bottom: 10, left: 140},
        width = width - margin.left - margin.right,
        height = height - margin.top - margin.bottom;

    //define x, y variables
    var x = d3.time.scale()

    //For axes code: http://12devsofxmas.co.uk/2012/01/data-visualisation/
    var xRange = d3.scale.linear().range ([margin.left, width - margin.right]).domain([0, 300]);
    var yRange = d3.scale.linear().range ([height - margin.top, margin.bottom]).domain([0, 300]);

    var xAxis = d3.svg.axis()       // generate an axis
            .scale(xRange)          // set the range of the axis
            .orient("bottom")       // have the text lables below axis
            .tickSize(5)            // height of the ticks
            .tickSubdivide(true);   // display ticks between text labels
            //.tickFormat(d3.time.format("%B"));
            //.ticks(d3.time.years)

    var yAxis = d3.svg.axis()       // generate an axis
            .scale(yRange)          // set the range of the axis
            .tickSize(5)            // width of the ticks
            .orient("left")         // have the text labels on the left hand side
            .tickSubdivide(true);   // display ticks between text labels

    self.dimensions = self.setDimensions(height);

   //
   var background;
   var foreground;

    //Add an svg to the timelineVis div in results.html
    self.svg = self.parentElement.append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
      .append("g")  //add group tag
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    function update () {
        var rects = self.svg.selectAll("rect").data(randomData(), function (d) { return d.id; });
        rects.enter()
            .insert("svg:rect")
            .attr("height", function (d) { return xRange (__Number_movies_in_bin__) })
            .attr("width", 20)
            .style("fill", "steelblue");

        rects.transition().duration(500).ease("exp-in-out")
            .attr("height", function (d) { return xRange(__Number_of_films_in_timerange__); })
            .attr("width", 20);

        rects.exit ()
            .transition().duration(1000).ease("exp-in-out")
            .attr("width", 0)
            .remove ();

        setTimeout (update, 2000)
    } //end function update

//==================================================
//      Pseudo code for bar chart creation
//==================================================
// 1) read in actorMovies
        // var minDate = d3.min(actorMovies)

// };  // end TimeLineVis.prototype.initVis

// Keys to use:   decade --> size bars based on number of films
//                       --> Shade baded on average rating?
//                 Individual years ->  Size on releases?

// Probably  won't need these

TimeLineVis.prototype.wrangleData = function (_filterFunction) {
    var self = this;

    // displayData should hold the data which is visualized
    self.displayData = self.filterAndAggregate(_filterFunction);
};

TimeLineVis.prototype.updateVis = function () {
    var self = this;
};

TimeLineVis.prototype.onSelectionChange = function (selectionStart, selectionEnd) {
    var self = this;

    self.wrangleData(function (data) {
        return (data.time <= selectionEnd && data.time >= selectionStart);
    });

    self.updateVis();
};

TimeLineVis.prototype.filterAndAggregate = function (_filter) {
    var self = this;

    // Set filter to a function that accepts all items
    // ONLY if the parameter _filter is NOT null use this parameter
    var filter = function(){return true;};
    if (_filter !== null){
        filter = _filter;
    }

    var prio = d3.range(0, 16).map(function () {
        return 0;
    });

    // Implement the function that filters the data and sums the values
    self.data.filter(filter).forEach(function (datum) {
        d3.range(0, 16).forEach(function (index) {
            prio[index] += datum.prios[index];
        });
    });

    return prio;
};

TimeLineVis.prototype.getDateRange = function(actorMovies) {
    var self = this;

    self.minDate = d3.min(data, function(d) { return d.year;} );
    self.maxDate = d3.max(data, function(d) { return d.year;} );
}<commit_msg>did nothing to help<commit_after>// maybe we could do a grid of moves and their genres?
// like a matrix
// http://codepen.io/bishopsmove/pen/AlHmc

TimeLineVis = function(_parentElement, _session) {
    var self = this;

     self.timelineVisKeys = [
        'Title',
        'Year',
        'imdbRating',
        'tomatoRating',
        'tomatoUserRating'
    ]

    self.parentElement = _parentElement;

    //Link movie data to timelineVis 'data'
    self.data = nanToZero(
        _session.get('actorMovies'),
        self.timelineVisKeys
    );

    self.displayData = [];
    self.initVis();
};

TimeLineVis.prototype.initVis = function () {

    //copy global data to be visible to this function
    var self = this;

    //define some canvas variables
    var width = 960;
    var height = 500;
    var margin = {top: 30, right: 10, bottom: 10, left: 140},
        width = width - margin.left - margin.right,
        height = height - margin.top - margin.bottom;

    //define x, y variables
    var x = d3.time.scale()

    //For axes code: http://12devsofxmas.co.uk/2012/01/data-visualisation/
    var xRange = d3.scale.linear().range ([margin.left, width - margin.right]).domain([0, 300]);
    var yRange = d3.scale.linear().range ([height - margin.top, margin.bottom]).domain([0, 300]);

    var xAxis = d3.svg.axis()       // generate an axis
            .scale(xRange)          // set the range of the axis
            .orient("bottom")       // have the text lables below axis
            .tickSize(5)            // height of the ticks
            .tickSubdivide(true);   // display ticks between text labels
            //.tickFormat(d3.time.format("%B"));
            //.ticks(d3.time.years)

    var yAxis = d3.svg.axis()       // generate an axis
            .scale(yRange)          // set the range of the axis
            .tickSize(5)            // width of the ticks
            .orient("left")         // have the text labels on the left hand side
            .tickSubdivide(true);   // display ticks between text labels

    self.dimensions = self.setDimensions(height);

   //
   var background;
   var foreground;

    //Add an svg to the timelineVis div in results.html
    self.svg = self.parentElement.append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
      .append("g")  //add group tag
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    function update () {
        var rects = self.svg.selectAll("rect").data(randomData(), function (d) { return d.id; });
        rects.enter()
            .insert("svg:rect")
            .attr("height", function (d) { return xRange (__Number_movies_in_bin__) })
            .attr("width", 20)
            .style("fill", "steelblue");

        rects.transition().duration(500).ease("exp-in-out")
            .attr("height", function (d) { return xRange(__Number_of_films_in_timerange__); })
            .attr("width", 20);

        rects.exit ()
            .transition().duration(1000).ease("exp-in-out")
            .attr("width", 0)
            .remove ();

        setTimeout (update, 2000)
    } //end function update

//==================================================
//      Pseudo code for bar chart creation
//==================================================
// 1) read in actorMovies
        // var minDate = d3.min(actorMovies)

// };  // end TimeLineVis.prototype.initVis

// Keys to use:   decade --> size bars based on number of films
//                       --> Shade baded on average rating?
//                 Individual years ->  Size on releases?

// Probably  won't need these

TimeLineVis.prototype.wrangleData = function (_filterFunction) {
    var self = this;

    // displayData should hold the data which is visualized
    self.displayData = self.filterAndAggregate(_filterFunction);
};

TimeLineVis.prototype.updateVis = function () {
    var self = this;
};

TimeLineVis.prototype.onSelectionChange = function (selectionStart, selectionEnd) {
    var self = this;

    self.wrangleData(function (data) {
        return (data.time <= selectionEnd && data.time >= selectionStart);
    });

    self.updateVis();
};

TimeLineVis.prototype.filterAndAggregate = function (_filter) {
    var self = this;

    // Set filter to a function that accepts all items
    // ONLY if the parameter _filter is NOT null use this parameter
    var filter = function(){return true;};
    if (_filter !== null){
        filter = _filter;
    }

    var prio = d3.range(0, 16).map(function () {
        return 0;
    });

    // Implement the function that filters the data and sums the values
    self.data.filter(filter).forEach(function (datum) {
        d3.range(0, 16).forEach(function (index) {
            prio[index] += datum.prios[index];
        });
    });

    return prio;
};

TimeLineVis.prototype.getDateRange = function(actorMovies) {
    var self = this;

    self.minDate = d3.min(data, function(d) { return d.year;} );
    self.maxDate = d3.max(data, function(d) { return d.year;} );
};<|endoftext|>


<commit_before>'use strict';

var gulp = require('gulp');
var chalk = require('chalk');
var bowerFiles = require('main-bower-files');
var $ = require('gulp-load-plugins')();

//$.util.log = $.util.noop;

process.env.NODE_ENV = $.util.env.env || 'development';

var config = require('./server/config/environment');

var toInject = [
  'client/app.js',
  'client/directives/**/*.js', '!client/directives/**/*.spec.js',
  'client/filters/**/*.js', '!client/filters/**/*.spec.js',
  'client/services/**/*.js', '!client/services/**/*.spec.js',
  'client/views/**/*.js', '!client/views/**/*.spec.js',
  'client/styles/css/app.css'
];

/**
 * Log. With options.
 *
 * @param {String} msg
 * @param {Object} options
 */
function log (msg, options) {
  options = options || {};
  console.log(
    (options.padding ? '\n' : '') +
    chalk.yellow(' > ' + msg) +
    (options.padding ? '\n' : '')
  );
}

/**
 * Compile sass
 */
gulp.task('sass', function () {
  return gulp.src('client/styles/app.scss')
    .pipe($.plumber())
    .pipe($.sass())
    .pipe(gulp.dest('client/styles/css'));
});

/**
 * Inject css/js files in index.html
 */
gulp.task('inject', function () {
  var sources = gulp.src(toInject, { read: false });

  return gulp.src('client/index.html')
    .pipe($.inject(gulp.src(bowerFiles(), { read: false }), {
      name: 'bower',
      relative: 'true'
    }))
    .pipe($.inject(sources, { relative: true }))
    .pipe(gulp.dest('client'));
});

/**
 * Watch files and reload page.
 * Recompile scss if needed.
 * Reinject files
 */
gulp.task('watch', ['inject'], function () {

  $.livereload.listen();

  $.watch('client/styles/**/*.scss', function () {
    gulp.src('client/styles/app.scss')
      .pipe($.plumber())
      .pipe($.sass())
      .pipe(gulp.dest('client/styles/css'))
      .pipe($.livereload());
  });

  $.watch([
    'client/index.html',
    'client/app.js'
  ]).pipe($.livereload());

  $.watch([
    'client/views',
    'client/views/**/*.html',
    'client/views/**/*.js',
    '!client/views/**/*.spec.js',
    'client/directives',
    'client/directives/**/*.html',
    'client/directives/**/*.js',
    '!client/directives/**/*.spec.js',
    'client/services',
    'client/services/**/*.js',
    '!client/services/**/*.spec.js',
    'client/filters',
    'client/filters/**/*.js',
    '!client/filters/**/*.spec.js'
  ], function (ev, done) {
    gulp.src('client/index.html')
      .pipe($.inject(gulp.src(toInject), { relative: true }))
      .pipe(gulp.dest('client'));
    done();
  });

  $.watch('bower.json', function () {
    gulp.src('client/index.html')
      .pipe($.inject(gulp.src(bowerFiles(), { read: false }), {
        name: 'bower',
        relative: 'true'
      }))
      .pipe(gulp.dest('client'));
  });

});

/**
 * Control things
 */
gulp.task('control', function () {
  return gulp.src([
    'client/**/**/*.js',
    'server/**/**/*.js',
    '!client/bower_components/**',
  ])
    .pipe($.jshint())
    .pipe($.jshint.reporter('default'));
});

/**
 * Tests
 */
function testServer (done) {

  log('Running server test...', { padding: true });

  gulp.src('server/**/*.spec.js', { read: false })
    .pipe($.plumber())
    .pipe($.mocha({ reporter: 'spec' }))
    .once('end', function () {
      done();
    });

}

function testClient (done) {

  log('Running client test...', { padding: true });

  gulp.src([
    'client/bower_components/angular/angular.js',
    'client/bower_components/angular-mocks/angular-mocks.js',
    'client/bower_components/angular-route/angular-route.js',
    'client/app.js',
    'client/views/**/*.js',
    'client/services/**/*.js',
    'client/directives/**/*.js',
    'client/filters/**/*.js'
  ])
    .pipe($.karma({
      action: 'run',
      configFile: 'client/karma.conf.js'
    }))
    .on('error', function (err) {
      console.log(err);
      this.emit('end');
    })
    .once('end', function () {
      done();
    });

}

gulp.task('test', function (done) {
  process.env.NODE_ENV = 'test';
  var filter = process.argv[3] ? process.argv[3].substr(2) : false;
  if (filter === 'client') {
    return testClient(function () { done(); });
  } else if (filter === 'server') {
    return testServer(function () { done(); });
  } else if (filter === false) {
    return testClient(function () {
      testServer(function () {
        done();
      });
    });
  } else {
    console.log('Wrong parameter [%s], availables : --client, --server', filter);
  }
});

/**
 * Launch server
 */
gulp.task('serve', ['sass', 'inject', 'watch'], function () {
  var options = {
    url: 'http://localhost:' + config.port,
    app: 'chromium'
  };

  require('./server/server');
  return gulp.src('client/index.html').pipe($.open('', options));
});

gulp.task('default', ['serve']);
<commit_msg>fix(gulpfile): exit server tests<commit_after>'use strict';

var gulp = require('gulp');
var chalk = require('chalk');
var bowerFiles = require('main-bower-files');
var $ = require('gulp-load-plugins')();

//$.util.log = $.util.noop;

process.env.NODE_ENV = $.util.env.env || 'development';

var config = require('./server/config/environment');

var toInject = [
  'client/app.js',
  'client/directives/**/*.js', '!client/directives/**/*.spec.js',
  'client/filters/**/*.js', '!client/filters/**/*.spec.js',
  'client/services/**/*.js', '!client/services/**/*.spec.js',
  'client/views/**/*.js', '!client/views/**/*.spec.js',
  'client/styles/css/app.css'
];

/**
 * Log. With options.
 *
 * @param {String} msg
 * @param {Object} options
 */
function log (msg, options) {
  options = options || {};
  console.log(
    (options.padding ? '\n' : '') +
    chalk.yellow(' > ' + msg) +
    (options.padding ? '\n' : '')
  );
}

/**
 * Compile sass
 */
gulp.task('sass', function () {
  return gulp.src('client/styles/app.scss')
    .pipe($.plumber())
    .pipe($.sass())
    .pipe(gulp.dest('client/styles/css'));
});

/**
 * Inject css/js files in index.html
 */
gulp.task('inject', function () {
  var sources = gulp.src(toInject, { read: false });

  return gulp.src('client/index.html')
    .pipe($.inject(gulp.src(bowerFiles(), { read: false }), {
      name: 'bower',
      relative: 'true'
    }))
    .pipe($.inject(sources, { relative: true }))
    .pipe(gulp.dest('client'));
});

/**
 * Watch files and reload page.
 * Recompile scss if needed.
 * Reinject files
 */
gulp.task('watch', ['inject'], function () {

  $.livereload.listen();

  $.watch('client/styles/**/*.scss', function () {
    gulp.src('client/styles/app.scss')
      .pipe($.plumber())
      .pipe($.sass())
      .pipe(gulp.dest('client/styles/css'))
      .pipe($.livereload());
  });

  $.watch([
    'client/index.html',
    'client/app.js'
  ]).pipe($.livereload());

  $.watch([
    'client/views',
    'client/views/**/*.html',
    'client/views/**/*.js',
    '!client/views/**/*.spec.js',
    'client/directives',
    'client/directives/**/*.html',
    'client/directives/**/*.js',
    '!client/directives/**/*.spec.js',
    'client/services',
    'client/services/**/*.js',
    '!client/services/**/*.spec.js',
    'client/filters',
    'client/filters/**/*.js',
    '!client/filters/**/*.spec.js'
  ], function (ev, done) {
    gulp.src('client/index.html')
      .pipe($.inject(gulp.src(toInject), { relative: true }))
      .pipe(gulp.dest('client'));
    done();
  });

  $.watch('bower.json', function () {
    gulp.src('client/index.html')
      .pipe($.inject(gulp.src(bowerFiles(), { read: false }), {
        name: 'bower',
        relative: 'true'
      }))
      .pipe(gulp.dest('client'));
  });

});

/**
 * Control things
 */
gulp.task('control', function () {
  return gulp.src([
    'client/**/**/*.js',
    'server/**/**/*.js',
    '!client/bower_components/**',
  ])
    .pipe($.jshint())
    .pipe($.jshint.reporter('default'));
});

/**
 * Tests
 */
function testServer (done) {

  log('Running server test...', { padding: true });

  gulp.src('server/**/*.spec.js', { read: false })
    .pipe($.plumber())
    .pipe($.mocha({ reporter: 'spec' }))
    .once('end', function () {
      done();
    });

}

function testClient (done) {

  log('Running client test...', { padding: true });

  gulp.src([
    'client/bower_components/angular/angular.js',
    'client/bower_components/angular-mocks/angular-mocks.js',
    'client/bower_components/angular-route/angular-route.js',
    'client/app.js',
    'client/views/**/*.js',
    'client/services/**/*.js',
    'client/directives/**/*.js',
    'client/filters/**/*.js'
  ])
    .pipe($.karma({
      action: 'run',
      configFile: 'client/karma.conf.js'
    }))
    .on('error', function (err) {
      console.log(err);
      this.emit('end');
    })
    .once('end', function () {
      done();
    });

}

gulp.task('test', function (done) {
  process.env.NODE_ENV = 'test';
  var filter = process.argv[3] ? process.argv[3].substr(2) : false;
  if (filter === 'client') {
    return testClient(function () { process.exit(); done(); });
  } else if (filter === 'server') {
    return testServer(function () { process.exit(); done(); });
  } else if (filter === false) {
    return testClient(function () {
      testServer(function () {
        process.exit();
        done();
      });
    });
  } else {
    console.log('Wrong parameter [%s], availables : --client, --server', filter);
  }
});

/**
 * Launch server
 */
gulp.task('serve', ['sass', 'inject', 'watch'], function () {
  var options = {
    url: 'http://localhost:' + config.port,
    app: 'chromium'
  };

  require('./server/server');
  return gulp.src('client/index.html').pipe($.open('', options));
});

gulp.task('default', ['serve']);
<|endoftext|>


<commit_before>'use strict';

var get = require('lodash.get');
var plurals = require('./plurals');

module.exports = Gettext;

/**
 * Creates and returns a new Gettext instance.
 *
 * @constructor
 * @param  {Object}  options        A set of options
 * @param  {Boolean} options.debug  Whether to output debug info into the
 *                                  console.
 * @return {Object}  A Gettext instance
 */
function Gettext(options) {
    options = options || {};

    this.catalogs = {};
    this.locale = null;
    this.domain = 'messages';

    this.listeners = [];

    // Set debug flag
    if ('debug' in options) {
        this.debug = options.debug === true;
    }
    else if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV) {
        this.debug = process.env.NODE_ENV !== 'production';
    }
    else {
        this.debug = false;
    }
}

/**
 * Adds an event listener.
 *
 * @param  {String}   eventName  An event name
 * @param  {Function} callback   An event handler function
 */
Gettext.prototype.on = function(eventName, callback) {
    this.listeners.push({
        eventName: eventName,
        callback: callback
    });
};

/**
 * Removes an event listener.
 *
 * @param  {String}   eventName  An event name
 * @param  {Function} callback   A previously registered event handler function
 */
Gettext.prototype.off = function(eventName, callback) {
    this.listeners = this.listeners.filter(function(listener) {
        return (
            listener.eventName === eventName &&
            listener.callback === callback
        ) === false;
    });
};

/**
 * Emits an event to all registered event listener.
 *
 * @param  {String} eventName  An event name
 * @param  {any}    eventData  Data to pass to event listeners
 */
Gettext.prototype.emit = function(eventName, eventData) {
    for (var i = 0; i < this.listeners.length; i++) {
        var listener = this.listeners[i];
        if (listener.eventName === eventName) {
            listener.callback(eventData);
        }
    }
};

/**
 * Logs a warning to the console if debug mode is enabled.
 *
 * @ignore
 * @param  {String} message  A warning message
 */
Gettext.prototype.warn = function(message) {
    if (this.debug) {
        console.warn(message);
    }

    this.emit('error', message);
};

/**
 * Stores a set of translations in the set of gettext
 * catalogs.
 *
 * @example
 *     gt.addTranslations('sv-SE', 'messages', translationsObject)
 *
 * @param {String} locale        A locale string
 * @param {String} domain        A domain name
 * @param {Object} translations  An object of gettext-parser JSON shape
 */
Gettext.prototype.addTranslations = function(locale, domain, translations) {
    if (!this.catalogs[locale]) {
        this.catalogs[locale] = {};
    }

    this.catalogs[locale][domain] = translations;
};

/**
 * Sets the locale to get translated messages for.
 *
 * @example
 *     gt.setLocale('sv-SE')
 *
 * @param {String} locale  A locale
 */
Gettext.prototype.setLocale = function(locale) {
    if (!locale) {
        this.warn('You called setLocale() with an empty value, which makes little sense.');
        return;
    }

    if (!this.catalogs[locale]) {
        this.warn('You called setLocale() with "' + locale + '", but no translations for that locale has been added.');
        return;
    }

    this.locale = locale;
};

/**
 * Sets the default gettext domain.
 *
 * @example
 *     gt.setTextDomain('domainname')
 *
 * @param {String} domain  A gettext domain name
 */
Gettext.prototype.setTextDomain = function(domain) {
    if (!domain) {
        this.warn('You called setTextDomain() with an empty `domain` value, which is not allowed.');
        return;
    }

    this.domain = domain;
};

/**
 * Translates a string using the default textdomain
 *
 * @example
 *     gt.gettext('Some text')
 *
 * @param  {String} msgid  String to be translated
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.gettext = function(msgid) {
    return this.dnpgettext(this.domain, '', msgid);
};

/**
 * Translates a string using a specific domain
 *
 * @example
 *     gt.dgettext('domainname', 'Some text')
 *
 * @param  {String} domain  A gettext domain name
 * @param  {String} msgid   String to be translated
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.dgettext = function(domain, msgid) {
    return this.dnpgettext(domain, '', msgid);
};

/**
 * Translates a plural string using the default textdomain
 *
 * @example
 *     gt.ngettext('One thing', 'Many things', numberOfThings)
 *
 * @param  {String} msgid        String to be translated when count is not plural
 * @param  {String} msgidPlural  String to be translated when count is plural
 * @param  {Number} count        Number count for the plural
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.ngettext = function(msgid, msgidPlural, count) {
    return this.dnpgettext(this.domain, '', msgid, msgidPlural, count);
};

/**
 * Translates a plural string using a specific textdomain
 *
 * @example
 *     gt.dngettext('domainname', 'One thing', 'Many things', numberOfThings)
 *
 * @param  {String} domain       A gettext domain name
 * @param  {String} msgid        String to be translated when count is not plural
 * @param  {String} msgidPlural  String to be translated when count is plural
 * @param  {Number} count        Number count for the plural
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.dngettext = function(domain, msgid, msgidPlural, count) {
    return this.dnpgettext(domain, '', msgid, msgidPlural, count);
};

/**
 * Translates a string from a specific context using the default textdomain
 *
 * @example
 *    gt.pgettext('sports', 'Back')
 *
 * @param  {String} msgctxt  Translation context
 * @param  {String} msgid    String to be translated
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.pgettext = function(msgctxt, msgid) {
    return this.dnpgettext(this.domain, msgctxt, msgid);
};

/**
 * Translates a string from a specific context using s specific textdomain
 *
 * @example
 *     gt.dpgettext('domainname', 'sports', 'Back')
 *
 * @param  {String} domain   A gettext domain name
 * @param  {String} msgctxt  Translation context
 * @param  {String} msgid    String to be translated
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.dpgettext = function(domain, msgctxt, msgid) {
    return this.dnpgettext(domain, msgctxt, msgid);
};

/**
 * Translates a plural string from a specific context using the default textdomain
 *
 * @example
 *     gt.npgettext('sports', 'Back', '%d backs', numberOfBacks)
 *
 * @param  {String} msgctxt      Translation context
 * @param  {String} msgid        String to be translated when count is not plural
 * @param  {String} msgidPlural  String to be translated when count is plural
 * @param  {Number} count        Number count for the plural
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.npgettext = function(msgctxt, msgid, msgidPlural, count) {
    return this.dnpgettext(this.domain, msgctxt, msgid, msgidPlural, count);
};

/**
 * Translates a plural string from a specifi context using a specific textdomain
 *
 * @example
 *     gt.dnpgettext('domainname', 'sports', 'Back', '%d backs', numberOfBacks)
 *
 * @param  {String} domain       A gettext domain name
 * @param  {String} msgctxt      Translation context
 * @param  {String} msgid        String to be translated
 * @param  {String} msgidPlural  If no translation was found, return this on count!=1
 * @param  {Number} count        Number count for the plural
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.dnpgettext = function(domain, msgctxt, msgid, msgidPlural, count) {
    var defaultTranslation = msgid;
    var translation;
    var index;

    msgctxt = msgctxt || '';

    if (!isNaN(count) && count !== 1) {
        defaultTranslation = msgidPlural || msgid;
    }

    if (!this.locale) {
        this.warn('You need to set a locale using setLocale(locale) before getting translated messages.');
        return defaultTranslation;
    }

    translation = this._getTranslation(domain, msgctxt, msgid);

    if (translation) {
        if (typeof count === 'number') {
            var pluralsFunc = plurals[Gettext.getLanguageCode(this.locale)].pluralsFunc;
            index = pluralsFunc(count);
            if (typeof index === 'boolean') {
                index = index ? 1 : 0;
            }
        } else {
            index = 0;
        }

        return translation.msgstr[index] || defaultTranslation;
    }
    else {
        this.warn('No translation was found for msgid "' + msgid + '" in msgctxt "' + msgctxt + '" and domain "' + domain + '"');
    }

    return defaultTranslation;
};

/**
 * Retrieves comments object for a translation. The comments object
 * has the shape `{ translator, extracted, reference, flag, previous }`.
 *
 * @example
 *     const comment = gt.getComment('domainname', 'sports', 'Backs')
 *
 * @param  {String} domain   A gettext domain name
 * @param  {String} msgctxt  Translation context
 * @param  {String} msgid    String to be translated
 * @return {Object} Comments object or false if not found
 */
Gettext.prototype.getComment = function(domain, msgctxt, msgid) {
    var translation;

    translation = this._getTranslation(domain, msgctxt, msgid);
    if (translation) {
        return translation.comments || {};
    }

    return {};
};

/**
 * Retrieves translation object from the domain and context
 *
 * @private
 * @param  {String} domain   A gettext domain name
 * @param  {String} msgctxt  Translation context
 * @param  {String} msgid    String to be translated
 * @return {Object} Translation object or false if not found
 */
Gettext.prototype._getTranslation = function(domain, msgctxt, msgid) {
    msgctxt = msgctxt || '';

    return get(this.catalogs, [this.locale, domain, 'translations', msgctxt, msgid]);
};

/**
 * Returns the language code part of a locale
 *
 * @example
 *     Gettext.getLanguageCode('sv-SE')
 *     // -> "sv"
 *
 * @param {String} locale  A case-insensitive locale string
 * @returns {String} A language code
 */
Gettext.getLanguageCode = function(locale) {
    return locale.split(/[\-_]/)[0].toLowerCase();
};

/**
 * This function will be removed in the final 2.0.0 release.
 *
 * @deprecated
 */
Gettext.prototype.addTextdomain = function() {

    // TODO(alexanderwallin): Add instructions for file i/o
    console.error('addTextdomain() is deprecated.\n\n' +
        '* To add translations, use addTranslations()\n' +
        '* To set the default domain, use setTextDomain()');
};

/**
 * This function will be removed in the final 2.0.0 release.
 *
 * @deprecated
 */
Gettext.prototype.textdomain = function() {
    console.error('textdomain() is deprecated.\n\n' +
        '* To set the current locale, use setLocale()\n' +
        '* To set the default domain, use setTextDomain()');
};
<commit_msg>Adds links to the README's Migration section in deprecation errors<commit_after>'use strict';

var get = require('lodash.get');
var plurals = require('./plurals');

module.exports = Gettext;

/**
 * Creates and returns a new Gettext instance.
 *
 * @constructor
 * @param  {Object}  options        A set of options
 * @param  {Boolean} options.debug  Whether to output debug info into the
 *                                  console.
 * @return {Object}  A Gettext instance
 */
function Gettext(options) {
    options = options || {};

    this.catalogs = {};
    this.locale = null;
    this.domain = 'messages';

    this.listeners = [];

    // Set debug flag
    if ('debug' in options) {
        this.debug = options.debug === true;
    }
    else if (typeof process !== 'undefined' && process.env && process.env.NODE_ENV) {
        this.debug = process.env.NODE_ENV !== 'production';
    }
    else {
        this.debug = false;
    }
}

/**
 * Adds an event listener.
 *
 * @param  {String}   eventName  An event name
 * @param  {Function} callback   An event handler function
 */
Gettext.prototype.on = function(eventName, callback) {
    this.listeners.push({
        eventName: eventName,
        callback: callback
    });
};

/**
 * Removes an event listener.
 *
 * @param  {String}   eventName  An event name
 * @param  {Function} callback   A previously registered event handler function
 */
Gettext.prototype.off = function(eventName, callback) {
    this.listeners = this.listeners.filter(function(listener) {
        return (
            listener.eventName === eventName &&
            listener.callback === callback
        ) === false;
    });
};

/**
 * Emits an event to all registered event listener.
 *
 * @param  {String} eventName  An event name
 * @param  {any}    eventData  Data to pass to event listeners
 */
Gettext.prototype.emit = function(eventName, eventData) {
    for (var i = 0; i < this.listeners.length; i++) {
        var listener = this.listeners[i];
        if (listener.eventName === eventName) {
            listener.callback(eventData);
        }
    }
};

/**
 * Logs a warning to the console if debug mode is enabled.
 *
 * @ignore
 * @param  {String} message  A warning message
 */
Gettext.prototype.warn = function(message) {
    if (this.debug) {
        console.warn(message);
    }

    this.emit('error', message);
};

/**
 * Stores a set of translations in the set of gettext
 * catalogs.
 *
 * @example
 *     gt.addTranslations('sv-SE', 'messages', translationsObject)
 *
 * @param {String} locale        A locale string
 * @param {String} domain        A domain name
 * @param {Object} translations  An object of gettext-parser JSON shape
 */
Gettext.prototype.addTranslations = function(locale, domain, translations) {
    if (!this.catalogs[locale]) {
        this.catalogs[locale] = {};
    }

    this.catalogs[locale][domain] = translations;
};

/**
 * Sets the locale to get translated messages for.
 *
 * @example
 *     gt.setLocale('sv-SE')
 *
 * @param {String} locale  A locale
 */
Gettext.prototype.setLocale = function(locale) {
    if (!locale) {
        this.warn('You called setLocale() with an empty value, which makes little sense.');
        return;
    }

    if (!this.catalogs[locale]) {
        this.warn('You called setLocale() with "' + locale + '", but no translations for that locale has been added.');
        return;
    }

    this.locale = locale;
};

/**
 * Sets the default gettext domain.
 *
 * @example
 *     gt.setTextDomain('domainname')
 *
 * @param {String} domain  A gettext domain name
 */
Gettext.prototype.setTextDomain = function(domain) {
    if (!domain) {
        this.warn('You called setTextDomain() with an empty `domain` value, which is not allowed.');
        return;
    }

    this.domain = domain;
};

/**
 * Translates a string using the default textdomain
 *
 * @example
 *     gt.gettext('Some text')
 *
 * @param  {String} msgid  String to be translated
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.gettext = function(msgid) {
    return this.dnpgettext(this.domain, '', msgid);
};

/**
 * Translates a string using a specific domain
 *
 * @example
 *     gt.dgettext('domainname', 'Some text')
 *
 * @param  {String} domain  A gettext domain name
 * @param  {String} msgid   String to be translated
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.dgettext = function(domain, msgid) {
    return this.dnpgettext(domain, '', msgid);
};

/**
 * Translates a plural string using the default textdomain
 *
 * @example
 *     gt.ngettext('One thing', 'Many things', numberOfThings)
 *
 * @param  {String} msgid        String to be translated when count is not plural
 * @param  {String} msgidPlural  String to be translated when count is plural
 * @param  {Number} count        Number count for the plural
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.ngettext = function(msgid, msgidPlural, count) {
    return this.dnpgettext(this.domain, '', msgid, msgidPlural, count);
};

/**
 * Translates a plural string using a specific textdomain
 *
 * @example
 *     gt.dngettext('domainname', 'One thing', 'Many things', numberOfThings)
 *
 * @param  {String} domain       A gettext domain name
 * @param  {String} msgid        String to be translated when count is not plural
 * @param  {String} msgidPlural  String to be translated when count is plural
 * @param  {Number} count        Number count for the plural
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.dngettext = function(domain, msgid, msgidPlural, count) {
    return this.dnpgettext(domain, '', msgid, msgidPlural, count);
};

/**
 * Translates a string from a specific context using the default textdomain
 *
 * @example
 *    gt.pgettext('sports', 'Back')
 *
 * @param  {String} msgctxt  Translation context
 * @param  {String} msgid    String to be translated
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.pgettext = function(msgctxt, msgid) {
    return this.dnpgettext(this.domain, msgctxt, msgid);
};

/**
 * Translates a string from a specific context using s specific textdomain
 *
 * @example
 *     gt.dpgettext('domainname', 'sports', 'Back')
 *
 * @param  {String} domain   A gettext domain name
 * @param  {String} msgctxt  Translation context
 * @param  {String} msgid    String to be translated
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.dpgettext = function(domain, msgctxt, msgid) {
    return this.dnpgettext(domain, msgctxt, msgid);
};

/**
 * Translates a plural string from a specific context using the default textdomain
 *
 * @example
 *     gt.npgettext('sports', 'Back', '%d backs', numberOfBacks)
 *
 * @param  {String} msgctxt      Translation context
 * @param  {String} msgid        String to be translated when count is not plural
 * @param  {String} msgidPlural  String to be translated when count is plural
 * @param  {Number} count        Number count for the plural
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.npgettext = function(msgctxt, msgid, msgidPlural, count) {
    return this.dnpgettext(this.domain, msgctxt, msgid, msgidPlural, count);
};

/**
 * Translates a plural string from a specifi context using a specific textdomain
 *
 * @example
 *     gt.dnpgettext('domainname', 'sports', 'Back', '%d backs', numberOfBacks)
 *
 * @param  {String} domain       A gettext domain name
 * @param  {String} msgctxt      Translation context
 * @param  {String} msgid        String to be translated
 * @param  {String} msgidPlural  If no translation was found, return this on count!=1
 * @param  {Number} count        Number count for the plural
 * @return {String} Translation or the original string if no translation was found
 */
Gettext.prototype.dnpgettext = function(domain, msgctxt, msgid, msgidPlural, count) {
    var defaultTranslation = msgid;
    var translation;
    var index;

    msgctxt = msgctxt || '';

    if (!isNaN(count) && count !== 1) {
        defaultTranslation = msgidPlural || msgid;
    }

    if (!this.locale) {
        this.warn('You need to set a locale using setLocale(locale) before getting translated messages.');
        return defaultTranslation;
    }

    translation = this._getTranslation(domain, msgctxt, msgid);

    if (translation) {
        if (typeof count === 'number') {
            var pluralsFunc = plurals[Gettext.getLanguageCode(this.locale)].pluralsFunc;
            index = pluralsFunc(count);
            if (typeof index === 'boolean') {
                index = index ? 1 : 0;
            }
        } else {
            index = 0;
        }

        return translation.msgstr[index] || defaultTranslation;
    }
    else {
        this.warn('No translation was found for msgid "' + msgid + '" in msgctxt "' + msgctxt + '" and domain "' + domain + '"');
    }

    return defaultTranslation;
};

/**
 * Retrieves comments object for a translation. The comments object
 * has the shape `{ translator, extracted, reference, flag, previous }`.
 *
 * @example
 *     const comment = gt.getComment('domainname', 'sports', 'Backs')
 *
 * @param  {String} domain   A gettext domain name
 * @param  {String} msgctxt  Translation context
 * @param  {String} msgid    String to be translated
 * @return {Object} Comments object or false if not found
 */
Gettext.prototype.getComment = function(domain, msgctxt, msgid) {
    var translation;

    translation = this._getTranslation(domain, msgctxt, msgid);
    if (translation) {
        return translation.comments || {};
    }

    return {};
};

/**
 * Retrieves translation object from the domain and context
 *
 * @private
 * @param  {String} domain   A gettext domain name
 * @param  {String} msgctxt  Translation context
 * @param  {String} msgid    String to be translated
 * @return {Object} Translation object or false if not found
 */
Gettext.prototype._getTranslation = function(domain, msgctxt, msgid) {
    msgctxt = msgctxt || '';

    return get(this.catalogs, [this.locale, domain, 'translations', msgctxt, msgid]);
};

/**
 * Returns the language code part of a locale
 *
 * @example
 *     Gettext.getLanguageCode('sv-SE')
 *     // -> "sv"
 *
 * @param {String} locale  A case-insensitive locale string
 * @returns {String} A language code
 */
Gettext.getLanguageCode = function(locale) {
    return locale.split(/[\-_]/)[0].toLowerCase();
};

/**
 * This function will be removed in the final 2.0.0 release.
 *
 * @deprecated
 */
Gettext.prototype.addTextdomain = function() {

    // TODO(alexanderwallin): Add instructions for file i/o
    console.error('addTextdomain() is deprecated.\n\n' +
        '* To add translations, use addTranslations()\n' +
        '* To set the default domain, use setTextDomain()\n' +
        '\n' +
        'To read more about the migration from node-gettext v1 to v2, ' +
        'see https://github.com/alexanderwallin/node-gettext/#migrating-from-1x-to-2x');
};

/**
 * This function will be removed in the final 2.0.0 release.
 *
 * @deprecated
 */
Gettext.prototype.textdomain = function() {
    console.error('textdomain() is deprecated.\n\n' +
        '* To set the current locale, use setLocale()\n' +
        '* To set the default domain, use setTextDomain()\n' +
        '\n' +
        'To read more about the migration from node-gettext v1 to v2, ' +
        'see https://github.com/alexanderwallin/node-gettext/#migrating-from-1x-to-2x');
};
<|endoftext|>


<commit_before>import _      from 'lodash';
import Api    from './api';

function proxyUrl(url){
  return `api/canvas?url=${encodeURIComponent(url)}`;
}

function getNextUrl(link){
  if(link){
    const url = _.find(link.split(','), (l) => {
      return _.trim(l.split(";")[1]) == 'rel="next"';
    })
    if(url){
      return url.split(';')[0].replace(/[\<\>\s]/g, "");
    }
  }
}

export default class CanvasApi{

  static get(url, key, cb = null, payload = null, priority = false){

    Api.queuedGet(key, proxyUrl(url), payload, priority).then(
      (response) => {
        if(cb) {
          cb(response.body || JSON.parse(response.text));
        }
        if(response.header){
          const nextUrl = getNextUrl(response.headers['link']);
          if(nextUrl){
            CanvasApi.get(nextUrl, key, cb, payload, priority);
          }
        }
      },
      (error) => {
        console.log(error);
      }
    );

  }

  static post(url, body, key){
    return Api.post(key, proxyUrl(url), body);
  }

  static put(url, body, key){
    return Api.put(key, proxyUrl(url), body);
  }

}<commit_msg>Removes unused file<commit_after><|endoftext|>


<commit_before>!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("rbTree",[],e):"object"==typeof exports?exports.rbTree=e():t.rbTree=e()}(this,function(){return function(t){function e(l){if(r[l])return r[l].exports;var n=r[l]={i:l,l:!1,exports:{}};return t[l].call(n.exports,n,n.exports,e),n.l=!0,n.exports}var r={};return e.m=t,e.c=r,e.i=function(t){return t},e.d=function(t,e,r){Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var r=t&&t.__esModule?function(){return t["default"]}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=4)}([function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r={RED:0,BLACK:1};e["default"]=r,t.exports=e["default"]},function(t,e,r){"use strict";function l(t){return t&&t.__esModule?t:{"default":t}}function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0});var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var l=e[r];l.enumerable=l.enumerable||!1,l.configurable=!0,"value"in l&&(l.writable=!0),Object.defineProperty(t,l.key,l)}}return function(e,r,l){return r&&t(e.prototype,r),l&&t(e,l),e}}(),a=r(0),i=l(a),u=function(){function t(e,r){n(this,t),this.key=e,this.value=r,this.left=null,this.right=null,this.color=null,this.parent=null}return o(t,[{key:"isRed",value:function(){return this.color===i["default"].RED}}]),t}();e["default"]=u,t.exports=e["default"]},function(t,e,r){"use strict";function l(t){return t&&t.__esModule?t:{"default":t}}function n(t){var e=new a["default"](null,null);return e.color=u["default"].BLACK,e.parent=t,e}Object.defineProperty(e,"__esModule",{value:!0});var o=r(1),a=l(o),i=r(0),u=l(i);e["default"]=n,t.exports=e["default"]},function(t,e,r){"use strict";function l(t){return t&&t.__esModule?t:{"default":t}}function n(t,e){var r=new a["default"](t,e),l=new a["default"](null,null);l.color=u["default"].BLACK,l.left=null,l.right=null,l.parent=r;var n=new a["default"](null,null);return n.color=u["default"].BLACK,n.left=null,n.right=null,n.parent=r,r.left=l,r.right=n,r}Object.defineProperty(e,"__esModule",{value:!0});var o=r(1),a=l(o),i=r(0),u=l(i);e["default"]=n,t.exports=e["default"]},function(t,e,r){"use strict";function l(t){return t&&t.__esModule?t:{"default":t}}function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0});var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var l=e[r];l.enumerable=l.enumerable||!1,l.configurable=!0,"value"in l&&(l.writable=!0),Object.defineProperty(t,l.key,l)}}return function(e,r,l){return r&&t(e.prototype,r),l&&t(e,l),e}}(),a=r(1),i=l(a),u=r(0),f=l(u),c=r(3),p=l(c),s=r(2),d=l(s),h=function(){function t(){n(this,t),this.root=null}return o(t,[{key:"clone",value:function(t){return new i["default"](t.key,t.value,t.left,t.right,t.color,t.parent)}},{key:"find",value:function(t){for(var e=this.root;null!=e;)if(t<e.key)e=e.left;else{if(!(t>e.key))return e.value;e=e.right}return null}},{key:"isNilNode",value:function(t){return null==t||null==t.key&&null==t.value&&t.color==f["default"].BLACK&&null==t.left&&null==t.right}},{key:"findNode",value:function(t){for(var e=this.root;null!=e;)if(t<e.key)e=e.left;else{if(!(t>e.key))return t==e.key?e:null;e=e.right}return null}},{key:"rotateRight",value:function(t){var e=t.left;this.isNilNode(e.right)?t.left=(0,d["default"])(t):t.left=e.right,this.isNilNode(e.right)||(e.right.parent=t),e.parent=t.parent,this.isNilNode(t.parent)?this.root=e:t==t.parent.right?t.parent.right=e:t.parent.left=e,e.right=t,t.parent=e}},{key:"rotateLeft",value:function(t){var e=t.right;this.isNilNode(e.left)?t.right=(0,d["default"])(t):t.right=e.left,this.isNilNode(e.left)||(e.left.parent=t),e.parent=t.parent,this.isNilNode(t.parent)?this.root=e:t==t.parent.left?t.parent.left=e:t.parent.right=e,e.left=t,t.parent=e}},{key:"insert",value:function(t,e){var r=null,l=this.root,n=(0,p["default"])(t,e);if(null==this.root)this.root=n,n.color=f["default"].BLACK,n.parent=null;else{for(;!this.isNilNode(l);)r=l,l=n.key<l.key?l.left:l.right;n.parent=r,n.key<r.key?r.left=n:r.right=n,n.left=(0,d["default"])(n),n.right=(0,d["default"])(n),n.color=f["default"].RED,this.fixTree(n)}}},{key:"fixTree",value:function(t){for(;null!=t.parent&&t.parent.color==f["default"].RED;){var e=null;if(t.parent==t.parent.parent.left){if(e=t.parent.parent.right,null!=e&&e.color==f["default"].RED){t.parent.color=f["default"].BLACK,e.color=f["default"].BLACK,t.parent.parent.color=f["default"].RED,t=t.parent.parent;continue}t==t.parent.right&&(t=t.parent,this.rotateLeft(t)),t.parent.color=f["default"].BLACK,t.parent.parent.color=f["default"].RED,this.rotateRight(t.parent.parent)}else{if(e=t.parent.parent.left,null!=e&&e.color==f["default"].RED){t.parent.color=f["default"].BLACK,e.color=f["default"].BLACK,t.parent.parent.color=f["default"].RED,t=t.parent.parent;continue}t==t.parent.left&&(t=t.parent,this.rotateRight(t)),t.parent.color=f["default"].BLACK,t.parent.parent.color=f["default"].RED,this.rotateLeft(t.parent.parent)}}this.root.color=f["default"].BLACK}},{key:"findHeight",value:function(t){if(null==t)return-1;var e=this.findHeight(t.left),r=this.findHeight(t.right);return e>r?e+1:r+1}},{key:"print",value:function(){var t=this.findHeight(this.root)+1;this.printHelper(this.root,"___",t)}},{key:"printHelper",value:function(t,e,r){var l=r;null!=t&&(t==this.root&&console.log(t.key+" color: "+t.color),null!=t.left&&console.log(e+t.left.key+" color: "+t.left.color+" (parent node "+t.left.parent.key+")"),null!=t.right&&console.log(e+t.right.key+" color: "+t.right.color+" (parent node "+t.right.parent.key+")"),l-=1,this.printHelper(t.left,e+e,l),this.printHelper(t.right,e+e,l))}},{key:"emptyTree",value:function(){this.root=null}},{key:"min",value:function(t){if(null==t||void 0==t)return{};for(;!this.isNilNode(t.left);)t=t.left;return t}},{key:"transplant",value:function(t,e){null==t.parent?this.root=e:t==t.parent.left?t.parent.left=e:t.parent.right=e,e.parent=t.parent}},{key:"remove",value:function(t){var e=this.findNode(t);if(null!=e){var r=void 0,l=e,n=l.color;this.isNilNode(e.left)?(r=e.right,this.transplant(e,e.right)):this.isNilNode(e.right)?(r=e.left,this.transplant(e,e.left)):(l=this.min(e.right),n=l.color,r=l.right,l.parent==e?r.parent=l:(this.transplant(l,l.right),l.right=e.right,l.right.parent=l),this.transplant(e,l),l.left=e.left,l.left.parent=l,l.color=e.color),n==f["default"].BLACK&&this.removeFix(r)}}},{key:"removeFix",value:function(t){for(;t!=this.root&&t.color==f["default"].BLACK;)if(t==t.parent.left){var e=t.parent.right;if(e.color==f["default"].RED&&(e.color=f["default"].BLACK,t.parent.color=f["default"].RED,this.rotateLeft(t.parent),e=t.parent.right),e.left.color==f["default"].BLACK&&e.right.color==f["default"].BLACK){e.color=f["default"].RED,t=t.parent;continue}e.right.color==f["default"].BLACK&&(e.left.color=f["default"].BLACK,e.color=f["default"].RED,e=t.parent.right),e.right.color==f["default"].RED&&(e.color=t.parent.color,t.parent.color=f["default"].BLACK,e.right.color=f["default"].BLACK,this.rotateLeft(t.parent),t=this.root)}else{var r=t.parent.left;if(r.color==f["default"].RED&&(r.color=f["default"].BLACK,t.parent.color=f["default"].RED,this.rotateRight(t.parent),r=t.parent.left),r.right.color==f["default"].BLACK&&r.left.color==f["default"].BLACK){r.color=f["default"].RED,t=t.parent;continue}r.left.color==f["default"].BLACK&&(r.right.color=f["default"].BLACK,r.color=f["default"].RED,this.rotateLeft(r),r=t.parent.left),r.left.color==f["default"].RED&&(r.color=t.parent.color,t.parent.color=f["default"].BLACK,r.left.color=f["default"].BLACK,this.rotateRight(t.parent),t=this.root)}t.color=f["default"].BLACK}}]),t}();e["default"]=h,t.exports=e["default"]}])});<commit_msg>update compiled dist file<commit_after>!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("rbTree",[],e):"object"==typeof exports?exports.rbTree=e():t.rbTree=e()}(this,function(){return function(t){function e(l){if(r[l])return r[l].exports;var n=r[l]={i:l,l:!1,exports:{}};return t[l].call(n.exports,n,n.exports,e),n.l=!0,n.exports}var r={};return e.m=t,e.c=r,e.i=function(t){return t},e.d=function(t,e,r){Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},e.n=function(t){var r=t&&t.__esModule?function(){return t["default"]}:function(){return t};return e.d(r,"a",r),r},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=4)}([function(t,e){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r={RED:0,BLACK:1};e["default"]=r,t.exports=e["default"]},function(t,e,r){"use strict";function l(t){return t&&t.__esModule?t:{"default":t}}function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0});var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var l=e[r];l.enumerable=l.enumerable||!1,l.configurable=!0,"value"in l&&(l.writable=!0),Object.defineProperty(t,l.key,l)}}return function(e,r,l){return r&&t(e.prototype,r),l&&t(e,l),e}}(),i=r(0),a=l(i),u=function(){function t(e,r){n(this,t),this.key=e,this.value=r,this.left=null,this.right=null,this.color=null,this.parent=null}return o(t,[{key:"isRed",value:function(){return this.color===a["default"].RED}},{key:"getValue",value:function(){return{key:this.key,value:this.value}}}]),t}();e["default"]=u,t.exports=e["default"]},function(t,e,r){"use strict";function l(t){return t&&t.__esModule?t:{"default":t}}function n(t){var e=new i["default"](null,null);return e.color=u["default"].BLACK,e.parent=t,e}Object.defineProperty(e,"__esModule",{value:!0});var o=r(1),i=l(o),a=r(0),u=l(a);e["default"]=n,t.exports=e["default"]},function(t,e,r){"use strict";function l(t){return t&&t.__esModule?t:{"default":t}}function n(t,e){var r=new i["default"](t,e),l=new i["default"](null,null);l.color=u["default"].BLACK,l.left=null,l.right=null,l.parent=r;var n=new i["default"](null,null);return n.color=u["default"].BLACK,n.left=null,n.right=null,n.parent=r,r.left=l,r.right=n,r}Object.defineProperty(e,"__esModule",{value:!0});var o=r(1),i=l(o),a=r(0),u=l(a);e["default"]=n,t.exports=e["default"]},function(t,e,r){"use strict";function l(t){return t&&t.__esModule?t:{"default":t}}function n(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}Object.defineProperty(e,"__esModule",{value:!0});var o=function(){function t(t,e){for(var r=0;r<e.length;r++){var l=e[r];l.enumerable=l.enumerable||!1,l.configurable=!0,"value"in l&&(l.writable=!0),Object.defineProperty(t,l.key,l)}}return function(e,r,l){return r&&t(e.prototype,r),l&&t(e,l),e}}(),i=r(1),a=l(i),u=r(0),f=l(u),c=r(3),s=l(c),p=r(2),h=l(p),d=function(){function t(){n(this,t),this.root=null}return o(t,[{key:"clone",value:function(t){return new a["default"](t.key,t.value,t.left,t.right,t.color,t.parent)}},{key:"find",value:function(t){for(var e=this.root;null!=e;)if(t<e.key)e=e.left;else{if(!(t>e.key))return e.value;e=e.right}return null}},{key:"isNilNode",value:function(t){return null==t||null==t.key&&null==t.value&&t.color===f["default"].BLACK&&null==t.left&&null==t.right}},{key:"findNode",value:function(t){for(var e=this.root;null!=e;)if(t<e.key)e=e.left;else{if(!(t>e.key))return t===e.key?e:null;e=e.right}return null}},{key:"rotateRight",value:function(t){var e=t.left;this.isNilNode(e.right)?t.left=(0,h["default"])(t):t.left=e.right,this.isNilNode(e.right)||(e.right.parent=t),e.parent=t.parent,this.isNilNode(t.parent)?this.root=e:t===t.parent.right?t.parent.right=e:t.parent.left=e,e.right=t,t.parent=e}},{key:"rotateLeft",value:function(t){var e=t.right;this.isNilNode(e.left)?t.right=(0,h["default"])(t):t.right=e.left,this.isNilNode(e.left)||(e.left.parent=t),e.parent=t.parent,this.isNilNode(t.parent)?this.root=e:t===t.parent.left?t.parent.left=e:t.parent.right=e,e.left=t,t.parent=e}},{key:"insert",value:function(t,e){var r=null,l=this.root,n=(0,s["default"])(t,e);if(null==this.root)this.root=n,n.color=f["default"].BLACK,n.parent=null;else{for(;!this.isNilNode(l);)r=l,l=n.key<l.key?l.left:l.right;n.parent=r,n.key<r.key?r.left=n:r.right=n,n.left=(0,h["default"])(n),n.right=(0,h["default"])(n),n.color=f["default"].RED,this.fixTree(n)}}},{key:"fixTree",value:function(t){for(;null!=t.parent&&t.parent.color===f["default"].RED;){var e=null;if(t.parent===t.parent.parent.left){if(e=t.parent.parent.right,null!=e&&e.color===f["default"].RED){t.parent.color=f["default"].BLACK,e.color=f["default"].BLACK,t.parent.parent.color=f["default"].RED,t=t.parent.parent;continue}t===t.parent.right&&(t=t.parent,this.rotateLeft(t)),t.parent.color=f["default"].BLACK,t.parent.parent.color=f["default"].RED,this.rotateRight(t.parent.parent)}else{if(e=t.parent.parent.left,null!=e&&e.color===f["default"].RED){t.parent.color=f["default"].BLACK,e.color=f["default"].BLACK,t.parent.parent.color=f["default"].RED,t=t.parent.parent;continue}t===t.parent.left&&(t=t.parent,this.rotateRight(t)),t.parent.color=f["default"].BLACK,t.parent.parent.color=f["default"].RED,this.rotateLeft(t.parent.parent)}}this.root.color=f["default"].BLACK}},{key:"findHeight",value:function(t){if(null==t)return-1;var e=this.findHeight(t.left),r=this.findHeight(t.right);return e>r?e+1:r+1}},{key:"print",value:function(){var t=this.findHeight(this.root)+1;this.printHelper(this.root,"___",t)}},{key:"printHelper",value:function(t,e,r){var l=r;null!=t&&(t===this.root&&console.log(t.key+" color: "+t.color),null!=t.left&&console.log(e+t.left.key+" color: "+t.left.color+" (parent node "+t.left.parent.key+")"),null!=t.right&&console.log(e+t.right.key+" color: "+t.right.color+" (parent node "+t.right.parent.key+")"),l-=1,this.printHelper(t.left,e+e,l),this.printHelper(t.right,e+e,l))}},{key:"emptyTree",value:function(){this.root=null}},{key:"min",value:function(t){if(null==t||void 0===t)return{};for(;!this.isNilNode(t.left);)t=t.left;return t}},{key:"minNode",value:function(){for(var t=this.root;!this.isNilNode(t.left);)t=t.left;return t.getValue()}},{key:"maxNode",value:function(){for(var t=this.root;!this.isNilNode(t.right);)t=t.right;return t.getValue()}},{key:"transplant",value:function(t,e){null==t.parent?this.root=e:t===t.parent.left?t.parent.left=e:t.parent.right=e,e.parent=t.parent}},{key:"remove",value:function(t){var e=this.findNode(t);if(null!=e){var r=void 0,l=e,n=l.color;this.isNilNode(e.left)?(r=e.right,this.transplant(e,e.right)):this.isNilNode(e.right)?(r=e.left,this.transplant(e,e.left)):(l=this.min(e.right),n=l.color,r=l.right,l.parent===e?r.parent=l:(this.transplant(l,l.right),l.right=e.right,l.right.parent=l),this.transplant(e,l),l.left=e.left,l.left.parent=l,l.color=e.color),n===f["default"].BLACK&&this.removeFix(r)}}},{key:"removeFix",value:function(t){for(;t!==this.root&&t.color===f["default"].BLACK;)if(t===t.parent.left){var e=t.parent.right;if(e.color===f["default"].RED&&(e.color=f["default"].BLACK,t.parent.color=f["default"].RED,this.rotateLeft(t.parent),e=t.parent.right),e.left.color===f["default"].BLACK&&e.right.color===f["default"].BLACK){e.color=f["default"].RED,t=t.parent;continue}e.right.color===f["default"].BLACK&&(e.left.color=f["default"].BLACK,e.color=f["default"].RED,e=t.parent.right),e.right.color===f["default"].RED&&(e.color=t.parent.color,t.parent.color=f["default"].BLACK,e.right.color=f["default"].BLACK,this.rotateLeft(t.parent),t=this.root)}else{var r=t.parent.left;r.color===f["default"].RED&&(r.color=f["default"].BLACK,t.parent.color=f["default"].RED,this.rotateRight(t.parent),r=t.parent.left),r.right.color===f["default"].BLACK&&r.left.color===f["default"].BLACK?(r.color=f["default"].RED,t=t.parent):r.left.color===f["default"].BLACK&&(r.right.color=f["default"].BLACK,r.color=f["default"].RED,this.rotateLeft(r),r=t.parent.left),r.left.color===f["default"].RED&&(r.color=t.parent.color,t.parent.color=f["default"].BLACK,r.left.color=f["default"].BLACK,this.rotateRight(t.parent),t=this.root)}t.color=f["default"].BLACK}},{key:"toSortedArray",value:function(){var t=[];return this.inOrder(this.root,t),t}},{key:"inOrder",value:function(t,e){this.isNilNode(t)||(this.inOrder(t.left,e),e.push(t.getValue()),this.inOrder(t.right,e))}}]),t}();e["default"]=d,t.exports=e["default"]}])});<|endoftext|>