<commit_before>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */
'use strict';

function Call(config, test) {
  this.test = test;
  this.traceEvent = report.traceEventAsync('call');
  this.traceEvent({config: config});

  this.pc1 = new RTCPeerConnection(config);
  this.pc2 = new RTCPeerConnection(config);

  this.pc1.addEventListener('icecandidate', this.onIceCandidate_.bind(this,
      this.pc2));
  this.pc2.addEventListener('icecandidate', this.onIceCandidate_.bind(this,
      this.pc1));

  this.iceCandidateFilter_ = Call.noFilter;
}

Call.prototype = {
  establishConnection: function() {
    this.traceEvent({state: 'start'});
    this.pc1.createOffer(this.gotOffer_.bind(this),
        this.test.reportFatal.bind(this.test));
  },

  close: function() {
    this.traceEvent({state: 'end'});
    this.pc1.close();
    this.pc2.close();
  },

  setIceCandidateFilter: function(filter) {
    this.iceCandidateFilter_ = filter;
  },

  // Constraint max video bitrate by modifying the SDP when creating an answer.
  constrainVideoBitrate: function(maxVideoBitrateKbps) {
    this.constrainVideoBitrateKbps_ = maxVideoBitrateKbps;
  },

  // Remove video FEC if available on the offer.
  disableVideoFec: function() {
    this.constrainOfferToRemoveVideoFec_ = true;
  },

  // When the peerConnection is closed the statsCb is called once with an array
  // of gathered stats.
  gatherStats: function(peerConnection, statsCb, interval) {
    var stats = [];
    var statsCollectTime = [];
    getStats_();

    function getStats_() {
      if (peerConnection.signalingState === 'closed') {
        statsCb(stats, statsCollectTime);
        return;
      }
      // Work around for webrtc/testrtc#74
      if (typeof(mozRTCPeerConnection) !== 'undefined' &&
          peerConnection instanceof mozRTCPeerConnection) {
        setTimeout(getStats_, interval);
      } else {
        setTimeout(peerConnection.getStats.bind(peerConnection, gotStats_),
            interval);
      }
    }

    function gotStats_(response) {
      for (var index in response.result()) {
        stats.push(response.result()[index]);
        statsCollectTime.push(Date.now());
      }
      getStats_();
    }
  },

  gotOffer_: function(offer) {
    if (this.constrainOfferToRemoveVideoFec_) {
      offer.sdp = offer.sdp.replace(/(m=video 1 [^\r]+)(116 117)(\r\n)/g,
                                    '$1\r\n');
      offer.sdp = offer.sdp.replace(/a=rtpmap:116 red\/90000\r\n/g, '');
      offer.sdp = offer.sdp.replace(/a=rtpmap:117 ulpfec\/90000\r\n/g, '');
      offer.sdp = offer.sdp.replace(/a=rtpmap:98 rtx\/90000\r\n/g, '');
      offer.sdp = offer.sdp.replace(/a=fmtp:98 apt=116\r\n/g, '');
    }
    this.pc1.setLocalDescription(offer);
    this.pc2.setRemoteDescription(offer);
    this.pc2.createAnswer(this.gotAnswer_.bind(this),
        this.test.reportFatal.bind(this.test));
  },

  gotAnswer_: function(answer) {
    if (this.constrainVideoBitrateKbps_) {
      answer.sdp = answer.sdp.replace(
          /a=mid:video\r\n/g,
          'a=mid:video\r\nb=AS:' + this.constrainVideoBitrateKbps_ + '\r\n');
    }
    this.pc2.setLocalDescription(answer);
    this.pc1.setRemoteDescription(answer);
  },

  onIceCandidate_: function(otherPeer, event) {
    if (event.candidate) {
      var parsed = Call.parseCandidate(event.candidate.candidate);
      if (this.iceCandidateFilter_(parsed)) {
        otherPeer.addIceCandidate(event.candidate);
      }
    }
  }
};

Call.noFilter = function() {
  return true;
};

Call.isRelay = function(candidate) {
  return candidate.type === 'relay';
};

Call.isNotHostCandidate = function(candidate) {
  return candidate.type !== 'host';
};

Call.isReflexive = function(candidate) {
  return candidate.type === 'srflx';
};

Call.isHost = function(candidate) {
  return candidate.type === 'host';
};

Call.isIpv6 = function(candidate) {
  return candidate.address.indexOf(':') !== -1;
};

// Parse a 'candidate:' line into a JSON object.
Call.parseCandidate = function(text) {
  var candidateStr = 'candidate:';
  var pos = text.indexOf(candidateStr) + candidateStr.length;
  var fields = text.substr(pos).split(' ');
  return {
    'type': fields[7],
    'protocol': fields[2],
    'address': fields[4]
  };
};

// Get a TURN config, either from settings or from network traversal api.
Call.asyncCreateTurnConfig = function(onSuccess, onError) {
  var settings = currentTest.settings;
  if (typeof(settings.turnURI) === 'string' && settings.turnURI !== '') {
    var iceServer = {
      'username': settings.turnUsername || '',
      'credential': settings.turnCredential || '',
      'urls': settings.turnURI.split(',')
    };
    var config = {'iceServers': [iceServer]};
    report.traceEventInstant('turn-config', config);
    setTimeout(onSuccess.bind(null, config), 0);
  } else {
    Call.fetchTurnConfig_(function(response) {
      var config = {'iceServers': response.iceServers};
      report.traceEventInstant('turn-config', config);
      onSuccess(config);
    }, onError);
  }
};

// Get a STUN config, either from settings or from network traversal api.
Call.asyncCreateStunConfig = function(onSuccess, onError) {
  var settings = currentTest.settings;
  if (typeof(settings.stunURI) === 'string' && settings.stunURI !== '') {
    var iceServer = {
      'urls': settings.stunURI.split(',')
    };
    var config = {'iceServers': [iceServer]};
    report.traceEventInstant('stun-config', config);
    setTimeout(onSuccess.bind(null, config), 0);
  } else {
    Call.fetchTurnConfig_(function(response) {
      var config = {'iceServers': response.iceServers.urls};
      report.traceEventInstant('stun-config', config);
      onSuccess(config);
    }, onError);
  }
};

// Ask network traversal API to give us TURN server credentials and URLs.
Call.fetchTurnConfig_ = function(onSuccess, onError) {
  // Check if credentials exist or have expired (and subtract testRuntTIme so
  // that the test can finish if near the end of the lifetime duration).
  // lifetimeDuration is in seconds.
  var testRunTime = 240; // Time in seconds to allow a test run to complete.
  if (Call.origResponse_ && (Date.now() - Call.fetchTurnTime_) / 1000 <
        parseInt(Call.origResponse_.lifetimeDuration) - testRunTime) {
    report.traceEventInstant('fetch-ice-config', 'Using cached credentials.');
    onSuccess(Call.getCachedIceCredentials_());
    return;
  }

  var xhr = new XMLHttpRequest();
  function onResult() {
    if (xhr.readyState !== 4) {
      return;
    }

    if (xhr.status !== 200) {
      onError('TURN request failed');
      return;
    }

    var response = JSON.parse(xhr.responseText);
    Call.origResponse_ = response;
    Call.getCachedIceCredentials_ = function() {
      // Make a new object due to tests modifying the original response object.
      return JSON.parse(JSON.stringify(Call.origResponse_));
    };
    Call.fetchTurnTime_ = Date.now();
    report.traceEventInstant('fetch-ice-config', 'Fetching new credentials.');
    onSuccess(Call.getCachedIceCredentials_());
  }

  xhr.onreadystatechange = onResult;
  // API_KEY and TURN_URL is replaced with API_KEY environment variable via
  // Gruntfile.js during build time by uglifyJS.
  // jscs:disable
  /* jshint ignore:start */
  xhr.open('POST', TURN_URL + API_KEY, true);
  // jscs:enable
  /* jshint ignore:end */
  xhr.send();
};
<commit_msg>fix according to comments<commit_after>/*
 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree.
 */
'use strict';

function Call(config, test) {
  this.test = test;
  this.traceEvent = report.traceEventAsync('call');
  this.traceEvent({config: config});

  this.pc1 = new RTCPeerConnection(config);
  this.pc2 = new RTCPeerConnection(config);

  this.pc1.addEventListener('icecandidate', this.onIceCandidate_.bind(this,
      this.pc2));
  this.pc2.addEventListener('icecandidate', this.onIceCandidate_.bind(this,
      this.pc1));

  this.iceCandidateFilter_ = Call.noFilter;
}

Call.prototype = {
  establishConnection: function() {
    this.traceEvent({state: 'start'});
    this.pc1.createOffer(this.gotOffer_.bind(this),
        this.test.reportFatal.bind(this.test));
  },

  close: function() {
    this.traceEvent({state: 'end'});
    this.pc1.close();
    this.pc2.close();
  },

  setIceCandidateFilter: function(filter) {
    this.iceCandidateFilter_ = filter;
  },

  // Constraint max video bitrate by modifying the SDP when creating an answer.
  constrainVideoBitrate: function(maxVideoBitrateKbps) {
    this.constrainVideoBitrateKbps_ = maxVideoBitrateKbps;
  },

  // Remove video FEC if available on the offer.
  disableVideoFec: function() {
    this.constrainOfferToRemoveVideoFec_ = true;
  },

  // When the peerConnection is closed the statsCb is called once with an array
  // of gathered stats.
  gatherStats: function(peerConnection, statsCb, interval) {
    var stats = [];
    var statsCollectTime = [];
    getStats_();

    function getStats_() {
      if (peerConnection.signalingState === 'closed') {
        statsCb(stats, statsCollectTime);
        return;
      }
      // Work around for webrtc/testrtc#74
      if (typeof(mozRTCPeerConnection) !== 'undefined' &&
          peerConnection instanceof mozRTCPeerConnection) {
        setTimeout(getStats_, interval);
      } else {
        setTimeout(peerConnection.getStats.bind(peerConnection, gotStats_),
            interval);
      }
    }

    function gotStats_(response) {
      for (var index in response.result()) {
        stats.push(response.result()[index]);
        statsCollectTime.push(Date.now());
      }
      getStats_();
    }
  },

  gotOffer_: function(offer) {
    if (this.constrainOfferToRemoveVideoFec_) {
      offer.sdp = offer.sdp.replace(/(m=video 1 [^\r]+)(116 117)(\r\n)/g,
                                    '$1\r\n');
      offer.sdp = offer.sdp.replace(/a=rtpmap:116 red\/90000\r\n/g, '');
      offer.sdp = offer.sdp.replace(/a=rtpmap:117 ulpfec\/90000\r\n/g, '');
      offer.sdp = offer.sdp.replace(/a=rtpmap:98 rtx\/90000\r\n/g, '');
      offer.sdp = offer.sdp.replace(/a=fmtp:98 apt=116\r\n/g, '');
    }
    this.pc1.setLocalDescription(offer);
    this.pc2.setRemoteDescription(offer);
    this.pc2.createAnswer(this.gotAnswer_.bind(this),
        this.test.reportFatal.bind(this.test));
  },

  gotAnswer_: function(answer) {
    if (this.constrainVideoBitrateKbps_) {
      answer.sdp = answer.sdp.replace(
          /a=mid:video\r\n/g,
          'a=mid:video\r\nb=AS:' + this.constrainVideoBitrateKbps_ + '\r\n');
    }
    this.pc2.setLocalDescription(answer);
    this.pc1.setRemoteDescription(answer);
  },

  onIceCandidate_: function(otherPeer, event) {
    if (event.candidate) {
      var parsed = Call.parseCandidate(event.candidate.candidate);
      if (this.iceCandidateFilter_(parsed)) {
        otherPeer.addIceCandidate(event.candidate);
      }
    }
  }
};

Call.noFilter = function() {
  return true;
};

Call.isRelay = function(candidate) {
  return candidate.type === 'relay';
};

Call.isNotHostCandidate = function(candidate) {
  return candidate.type !== 'host';
};

Call.isReflexive = function(candidate) {
  return candidate.type === 'srflx';
};

Call.isHost = function(candidate) {
  return candidate.type === 'host';
};

Call.isIpv6 = function(candidate) {
  return candidate.address.indexOf(':') !== -1;
};

// Parse a 'candidate:' line into a JSON object.
Call.parseCandidate = function(text) {
  var candidateStr = 'candidate:';
  var pos = text.indexOf(candidateStr) + candidateStr.length;
  var fields = text.substr(pos).split(' ');
  return {
    'type': fields[7],
    'protocol': fields[2],
    'address': fields[4]
  };
};

// Store the ICE server response from the network traversal server.
Call.cachedIceServers_ = null;

// Get a TURN config, either from settings or from network traversal server.
Call.asyncCreateTurnConfig = function(onSuccess, onError) {
  var settings = currentTest.settings;
  if (typeof(settings.turnURI) === 'string' && settings.turnURI !== '') {
    var iceServer = {
      'username': settings.turnUsername || '',
      'credential': settings.turnCredential || '',
      'urls': settings.turnURI.split(',')
    };
    var config = {'iceServers': [iceServer]};
    report.traceEventInstant('turn-config', config);
    setTimeout(onSuccess.bind(null, config), 0);
  } else {
    Call.fetchTurnConfig_(function(response) {
      var config = {'iceServers': response.iceServers};
      report.traceEventInstant('turn-config', config);
      onSuccess(config);
    }, onError);
  }
};

// Get a STUN config, either from settings or from network traversal server.
Call.asyncCreateStunConfig = function(onSuccess, onError) {
  var settings = currentTest.settings;
  if (typeof(settings.stunURI) === 'string' && settings.stunURI !== '') {
    var iceServer = {
      'urls': settings.stunURI.split(',')
    };
    var config = {'iceServers': [iceServer]};
    report.traceEventInstant('stun-config', config);
    setTimeout(onSuccess.bind(null, config), 0);
  } else {
    Call.fetchTurnConfig_(function(response) {
      var config = {'iceServers': response.iceServers.urls};
      report.traceEventInstant('stun-config', config);
      onSuccess(config);
    }, onError);
  }
};

// Ask network traversal API to give us TURN server credentials and URLs.
Call.fetchTurnConfig_ = function(onSuccess, onError) {
  // Check if credentials exist or have expired (and subtract testRuntTIme so
  // that the test can finish if near the end of the lifetime duration).
  // lifetimeDuration is in seconds.
  var testRunTime = 240; // Time in seconds to allow a test run to complete.
  if (Call.cachedIceServers_ && (Date.now() - Call.fetchTurnTime_) / 1000 <
        parseInt(Call.cachedIceServers_.lifetimeDuration) - testRunTime) {
    report.traceEventInstant('fetch-ice-config', 'Using cached credentials.');
    onSuccess(Call.getCachedIceCredentials_());
    return;
  }

  var xhr = new XMLHttpRequest();
  function onResult() {
    if (xhr.readyState !== 4) {
      return;
    }

    if (xhr.status !== 200) {
      onError('TURN request failed');
      return;
    }

    var response = JSON.parse(xhr.responseText);
    Call.cachedIceServers_ = response;
    Call.getCachedIceCredentials_ = function() {
      // Make a new object due to tests modifying the original response object.
      return JSON.parse(JSON.stringify(Call.cachedIceServers_));
    };
    Call.fetchTurnTime_ = Date.now();
    report.traceEventInstant('fetch-ice-config', 'Fetching new credentials.');
    onSuccess(Call.getCachedIceCredentials_());
  }

  xhr.onreadystatechange = onResult;
  // API_KEY and TURN_URL is replaced with API_KEY environment variable via
  // Gruntfile.js during build time by uglifyJS.
  // jscs:disable
  /* jshint ignore:start */
  xhr.open('POST', TURN_URL + API_KEY, true);
  // jscs:enable
  /* jshint ignore:end */
  xhr.send();
};
<|endoftext|>


<commit_before>var blockType = {
	STATIC: "STATIC",
	MOVEABLE: "MOVEABLE"
}

GameStates.Game = function (game) {
	this.player;
	this.level;
	this.block = [];
	this.teleporter;
	this.map;
	this.graphics;
	this.originPointer;
	this.mapGrain = 40;	// size of map blocks
	this.worldBottomPadding = 300;
	this.playerCollisionGroup;
	this.blockCollisionGroup;
	this.timer;

	// layers
	this.blockLayer;

	// constants
	this.GRAVITY = 1000;
	this.FALL_BUFFER = 200;
};

GameStates.Game.prototype = {
	create: function () {
		// reset variables
		this.player = null;
		this.level = 0;

		// enable physics
		game.physics.startSystem(Phaser.Physics.P2JS);
		game.physics.p2.defaultRestitution = 1;
		game.physics.p2.gravity.y = this.GRAVITY;
		game.physics.p2.damping = 1;

		// turn on collision callbacks
		game.physics.p2.setImpactEvents(true);
		this.playerCollisionGroup = game.physics.p2.createCollisionGroup();
		this.blockCollisionGroup = game.physics.p2.createCollisionGroup();

		// get json
		this.map = JSON.parse(JSON.stringify(game.cache.getJSON('map')));

		// create a layer for moveable blocks to live on
		this.blockLayer = game.add.group();

		// add graphics layer
		this.graphics = game.add.graphics(0, 0);
		this.graphics.alpha = 0.5;

		// make level
		this.makeLevel(this.level);

		// camera
		game.camera.follow(this.player.sprite);

		// place a block on click
		game.input.mouse.capture = true;

		// set up jump event for player scope callback function to player
		this.player.sprite.body.collides(this.blockCollisionGroup, this.player.checkJump, this.player);

		// set up gameplay timer
		this.timer = new Timer(game, game.width - 60, 20);

	},
	update: function () {
		this.player.update();

		// incremement timer
		this.timer.update(game.time.elapsed);

		// place blocks if mouse is down
		if(game.input.activePointer.leftButton.isDown) {
			this.placeBlock(game.input);
		}

		// clear graphics before potential drawing
		this.graphics.clear();

		if(game.input.activePointer.rightButton.isDown) {
			// Set the origin of the net
			if(this.originPointer == null) {
				this.originPointer = {
					x: game.input.x,
					y: game.input.y
				};
			}
			this.drawNet(game.input);
		}
		else {
			if(this.originPointer != null) {
				// create hitbox from net this handles dragging the box in any direction
				var a = { x: null, y: null };
				var b = { x: null, y: null };

				if( this.originPointer.x < game.input.x ) {
					a.x = this.originPointer.x;
					b.x = game.input.x;
				}
				else {
					a.x = game.input.x;
					b.x = this.originPointer.x;
				}

				if( this.originPointer.y < game.input.y ) {
					a.y = this.originPointer.y;
					b.y = game.input.y;
				}
				else {
					a.y = game.input.y;
					b.y = this.originPointer.y;
				}

				var hitbox = new Phaser.Rectangle(a.x, a.y, b.x - a.x, b.y - a.y);

				var toSplice = [];

				// remove blocks that overlap
				for(var i = 0, len = this.block.length; i < len; i++) {
					if(this.block[i] != null
					   && this.player.inventory.count < this.player.inventory.CAP
					   && this.block[i].type == blockType.MOVEABLE
					   && Phaser.Rectangle.intersects(this.block[i].sprite.getBounds(), hitbox)) {
						this.block[i].sprite.destroy();
						this.block[i] = null;
						this.player.inventory.change(1);
					}
				}
			}
			this.originPointer = null;
		}

		// check for collision with teleporter
		if(Phaser.Rectangle.intersects(this.player.sprite.getBounds(), this.teleporter.sprite.getBounds())) {
			// go to next level
			if(this.map.level[this.level + 1]) {
				this.makeLevel(this.level++);
				this.player.canMove = false;
			}
			else {
				game.state.start('GameOver');
			}
		}

		// check if player falls too far to reset level
		if(this.player.sprite.body.y > game.world.height + this.worldBottomPadding + this.player.sprite.height) {
			this.makeLevel(this.level);
		}

	},
	preRender: function () {
		this.player.preRender();
	},
	placeBlock: function (pointer) {
		// get a pointer relative to camera
		var truePointer = {
			x: Math.floor(((pointer.x + game.camera.x) / this.mapGrain)),
			y: Math.floor(((pointer.y + game.camera.y) / this.mapGrain))
		};

		// check if there is a block at pointer location
		for(var i = 0, len = this.block.length; i < len; i++) {
			if(this.block[i] != null
			   && this.block[i].x == (truePointer.x + 0.5) * this.mapGrain
			   && this.block[i].y == (truePointer.y + 0.5) * this.mapGrain) {
				return;
			}
		}

		// place block if inventory allows
		if(this.player.inventory.count > 0) {
			var newBlock = new Block(this, truePointer.x, truePointer.y, this.mapGrain, blockType.MOVEABLE);
			this.block.push(newBlock);
			this.blockLayer.add(newBlock.sprite);
			this.player.inventory.change(-1);
		}
	},
	drawNet: function (pointer) {
		this.graphics.beginFill(0xff0000);
		this.graphics.drawRect(this.camera.x + this.originPointer.x, this.camera.y + this.originPointer.y, pointer.x - this.originPointer.x, pointer.y - this.originPointer.y);
	},
	makeLevel: function () {
		// clear block array
		this.block.forEach(function (block) {
			if(block != null){
				block.sprite.destroy();
			}
		});
		this.block = [];

		// clear teleporter
		if(this.teleporter) {
			this.teleporter.sprite.destroy();
		}

		// create player
		if(this.player) {
			this.player.moveToStart(this.map.level[this.level].start.x * this.mapGrain + 0.5, this.map.level[this.level].start.y * this.mapGrain + 0.5);
		}
		else {
			this.player = new Player(this, this.map.level[this.level].start.x * this.mapGrain + 0.5, this.map.level[this.level].start.y * this.mapGrain + 0.5);
		}

		this.player.inventory.clear();

		// create map
		for(var i = 0, len = this.map.level[this.level].block.length; i < len; i++) {
			this.block.push(new Block(this,
									  this.map.level[this.level].block[i].x,
									  this.map.level[this.level].block[i].y,
									  this.mapGrain,
									  this.map.level[this.level].block[i].type));
		}

		// create teleporter for this level
		this.teleporter = new Teleporter(this.map.level[this.level].teleporter.x,
										 this.map.level[this.level].teleporter.y,
										 this.mapGrain);

		//  find the greatest x and y position of blocks
		var greatestX = 0;
		var greatestY = 0;

		for(var i = 0, len = this.block.length; i < len; i++) {
			if(this.block[i].x > greatestX) {
				greatestX = this.block[i].x;
			}

			if(this.block[i].y > greatestY) {
				greatestY = this.block[i].y;
			}

		}

		// check for small values
		if (greatestX < game.width) {
			greatestX = game.width;
		}

		if (greatestY < game.height) {
			greatestY = game.height;
		}

		// set the world bounds based on level
		// added a little to the game height so the camera follows the player a little before allowing the player to fall off screen and reset
		// add a half of a block to the width because the blocks are centered on position
		game.world.setBounds(0, 0, greatestX + this.mapGrain / 2, greatestY + this.FALL_BUFFER);
	}
};
<commit_msg>Fixed twitch in net Fixes #6<commit_after>var blockType = {
	STATIC: "STATIC",
	MOVEABLE: "MOVEABLE"
}

GameStates.Game = function (game) {
	this.player;
	this.level;
	this.block = [];
	this.teleporter;
	this.map;
	this.graphics;
	this.originPointer;
	this.mapGrain = 40;	// size of map blocks
	this.worldBottomPadding = 300;
	this.playerCollisionGroup;
	this.blockCollisionGroup;
	this.timer;

	// layers
	this.blockLayer;

	// constants
	this.GRAVITY = 1000;
	this.FALL_BUFFER = 200;
};

GameStates.Game.prototype = {
	create: function () {
		// reset variables
		this.player = null;
		this.level = 0;

		// enable physics
		game.physics.startSystem(Phaser.Physics.P2JS);
		game.physics.p2.defaultRestitution = 1;
		game.physics.p2.gravity.y = this.GRAVITY;
		game.physics.p2.damping = 1;

		// turn on collision callbacks
		game.physics.p2.setImpactEvents(true);
		this.playerCollisionGroup = game.physics.p2.createCollisionGroup();
		this.blockCollisionGroup = game.physics.p2.createCollisionGroup();

		// get json
		this.map = JSON.parse(JSON.stringify(game.cache.getJSON('map')));

		// create a layer for moveable blocks to live on
		this.blockLayer = game.add.group();

		// add graphics layer
		this.graphics = game.add.graphics(0, 0);
		this.graphics.alpha = 0.5;

		// make level
		this.makeLevel(this.level);

		// camera
		game.camera.follow(this.player.sprite);

		// place a block on click
		game.input.mouse.capture = true;

		// set up jump event for player scope callback function to player
		this.player.sprite.body.collides(this.blockCollisionGroup, this.player.checkJump, this.player);

		// set up gameplay timer
		this.timer = new Timer(game, game.width - 60, 20);

	},
	update: function () {
		this.player.update();

		// incremement timer
		this.timer.update(game.time.elapsed);

		// place blocks if mouse is down
		if(game.input.activePointer.leftButton.isDown) {
			this.placeBlock(game.input);
		}

		// check for collision with teleporter
		if(Phaser.Rectangle.intersects(this.player.sprite.getBounds(), this.teleporter.sprite.getBounds())) {
			// go to next level
			if(this.map.level[this.level + 1]) {
				this.makeLevel(this.level++);
				this.player.canMove = false;
			}
			else {
				game.state.start('GameOver');
			}
		}

		// check if player falls too far to reset level
		if(this.player.sprite.body.y > game.world.height + this.worldBottomPadding + this.player.sprite.height) {
			this.makeLevel(this.level);
		}

	},
	preRender: function () {
		this.player.preRender();

		// clear graphics before potential drawing
		this.graphics.clear();

        if(game.input.activePointer.rightButton.isDown) {
			// Set the origin of the net
			if(this.originPointer == null) {
				this.originPointer = {
					x: game.input.x,
					y: game.input.y
				};
			}
			this.drawNet(game.input);
		}
		else {
			if(this.originPointer != null) {
				// create hitbox from net this handles dragging the box in any direction
				var a = { x: null, y: null };
				var b = { x: null, y: null };

				if( this.originPointer.x < game.input.x ) {
					a.x = this.originPointer.x;
					b.x = game.input.x;
				}
				else {
					a.x = game.input.x;
					b.x = this.originPointer.x;
				}

				if( this.originPointer.y < game.input.y ) {
					a.y = this.originPointer.y;
					b.y = game.input.y;
				}
				else {
					a.y = game.input.y;
					b.y = this.originPointer.y;
				}

				var hitbox = new Phaser.Rectangle(a.x, a.y, b.x - a.x, b.y - a.y);

				var toSplice = [];

				// remove blocks that overlap
				for(var i = 0, len = this.block.length; i < len; i++) {
					if(this.block[i] != null
					   && this.player.inventory.count < this.player.inventory.CAP
					   && this.block[i].type == blockType.MOVEABLE
					   && Phaser.Rectangle.intersects(this.block[i].sprite.getBounds(), hitbox)) {
						this.block[i].sprite.destroy();
						this.block[i] = null;
						this.player.inventory.change(1);
					}
				}
			}
			this.originPointer = null;
		}
	},
	placeBlock: function (pointer) {
		// get a pointer relative to camera
		var truePointer = {
			x: Math.floor(((pointer.x + game.camera.x) / this.mapGrain)),
			y: Math.floor(((pointer.y + game.camera.y) / this.mapGrain))
		};

		// check if there is a block at pointer location
		for(var i = 0, len = this.block.length; i < len; i++) {
			if(this.block[i] != null
			   && this.block[i].x == (truePointer.x + 0.5) * this.mapGrain
			   && this.block[i].y == (truePointer.y + 0.5) * this.mapGrain) {
				return;
			}
		}

		// place block if inventory allows
		if(this.player.inventory.count > 0) {
			var newBlock = new Block(this, truePointer.x, truePointer.y, this.mapGrain, blockType.MOVEABLE);
			this.block.push(newBlock);
			this.blockLayer.add(newBlock.sprite);
			this.player.inventory.change(-1);
		}
	},
	drawNet: function (pointer) {
		this.graphics.beginFill(0xff0000);
		this.graphics.drawRect(this.camera.x + this.originPointer.x, this.camera.y + this.originPointer.y, pointer.x - this.originPointer.x, pointer.y - this.originPointer.y);
	},
	makeLevel: function () {
		// clear block array
		this.block.forEach(function (block) {
			if(block != null){
				block.sprite.destroy();
			}
		});
		this.block = [];

		// clear teleporter
		if(this.teleporter) {
			this.teleporter.sprite.destroy();
		}

		// create player
		if(this.player) {
			this.player.moveToStart(this.map.level[this.level].start.x * this.mapGrain + 0.5, this.map.level[this.level].start.y * this.mapGrain + 0.5);
		}
		else {
			this.player = new Player(this, this.map.level[this.level].start.x * this.mapGrain + 0.5, this.map.level[this.level].start.y * this.mapGrain + 0.5);
		}

		this.player.inventory.clear();

		// create map
		for(var i = 0, len = this.map.level[this.level].block.length; i < len; i++) {
			this.block.push(new Block(this,
									  this.map.level[this.level].block[i].x,
									  this.map.level[this.level].block[i].y,
									  this.mapGrain,
									  this.map.level[this.level].block[i].type));
		}

		// create teleporter for this level
		this.teleporter = new Teleporter(this.map.level[this.level].teleporter.x,
										 this.map.level[this.level].teleporter.y,
										 this.mapGrain);

		//  find the greatest x and y position of blocks
		var greatestX = 0;
		var greatestY = 0;

		for(var i = 0, len = this.block.length; i < len; i++) {
			if(this.block[i].x > greatestX) {
				greatestX = this.block[i].x;
			}

			if(this.block[i].y > greatestY) {
				greatestY = this.block[i].y;
			}

		}

		// check for small values
		if (greatestX < game.width) {
			greatestX = game.width;
		}

		if (greatestY < game.height) {
			greatestY = game.height;
		}

		// set the world bounds based on level
		// added a little to the game height so the camera follows the player a little before allowing the player to fall off screen and reset
		// add a half of a block to the width because the blocks are centered on position
		game.world.setBounds(0, 0, greatestX + this.mapGrain / 2, greatestY + this.FALL_BUFFER);
	}
};
<|endoftext|>


<commit_before>
(function($) {

  App.Grid = function(device) {
    this.init(device);
  };

  App.Grid.Cell = {
    WIDTH:  140,
    HEIGHT: 140,
    MARGIN: 10
  };

  App.Grid.MOVE_THRESHOLD = 10;
  App.Grid.SCROLL_BIAS = 40;

  App.Grid.Margin = {
    Portrait: {
      TOP: 20,
      LEFT: 15,
      RIGHT: 15
    },
    Landscape: {
      TOP: 40,
      LEFT: 64,
      RIGHT: 64
    }
  };

  jQuery.extend(App.Grid.prototype, {

    init: function(device) {
      var self = this;
      self.device = device;
      self.identifier = '#list-games';
      self.element = $(self.identifier);
      self.content = $('#list-games-content');

      self.pageControl = $('#list-games-page-control');
      self.pageItems = [];

      self.count = 0;
      self.rows = 0;
      self.width = 0;
      self.pageWidth = 0;
      self.page = 0;

      self.dataSource = {
        'count' : function() { return 0; },
        'titleForIndex': function(index) { return ''; }
      };

      self.delegate = {
        'didSelectItemForRow': function(index) {}
      };

      self.touchListener = new App.TouchListener(self.identifier, self);
      self.touchStart = { x: 0, y: 0};
      self.touchStartTimestamp = 0;
      self.touchDidMove = false;
      self.touchCount = 0;

      self.gestureRecognizer = new App.GestureRecognizer();
      self.touchListener.addRecognizer(self.gestureRecognizer);

      self.updateLayout();
      $(window).resize(function() {
        self.updateLayout();
      });

    },

    // Return the margin for the current orientation.
    margin: function() {
      var self = this;
      if (self.device.orientation === App.Device.Orientation.PORTRAIT) {
        return App.Grid.Margin.Portrait;
      } else {
        return App.Grid.Margin.Landscape;
      }
    },

    reloadData: function() {
      var self = this;

      self.count = 0;
      self.content.html("");
      for (var i=0; i<self.dataSource.count(); i++) {
        var title = self.dataSource.titleForIndex(i);
        var thumbnail = self.dataSource.thumbnailForIndex(i);
        var offline = self.dataSource.availableOffline(i);
        self.add(i, title, thumbnail, offline);
      }

      self.updatePageControl();
      self.updatePageItems();
    },

    updateLayout: function() {
      var self = this;

      var cellHeight = App.Grid.Cell.HEIGHT + App.Grid.Cell.MARGIN;
      var cellWidth = App.Grid.Cell.WIDTH + App.Grid.Cell.MARGIN;

      var controlWidth = self.element.width() + App.Grid.Cell.MARGIN;
      var controlHeight = self.element.height() + App.Grid.Cell.MARGIN;

      var rows = Math.floor(controlHeight / cellHeight);
      var width =  Math.floor(controlWidth / cellWidth);
      // Relayout if required.
      if ((rows != self.rows) || (width != self.width)) {
        self.rows = rows;
        self.width = width;
        self.pageWidth = (self.width * (App.Grid.Cell.WIDTH + App.Grid.Cell.MARGIN)) + self.margin().LEFT + self.margin().RIGHT;
        self.page = 0;
        self.content.css('left', 0);
        self.reloadData();
      }

    },

    updatePageControl: function() {
      var self = this;

      self.pageControl.html("");
      self.pageItems = [];

      if (self.count === 0) {
        return;
      }

      for (var i=self.minPage(); i <= self.maxPage(); i++) {
        var item = $('
');
        self.pageControl.append(item);
        self.pageItems.push(item);
      }
    },

    updatePageItems: function() {
      var self = this;

      if (self.count === 0) {
        return;
      }

      for (var i = 0; i < self.pageItems.length; i++) {
        var item = self.pageItems[i];
        if (i === self.page) {
          item.addClass("active");
        } else {
          item.removeClass("active");
        }
      }
    },

    add: function(index, title, thumbnail, offline) {
      var self = this;

      var row = self.count % self.rows;
      var col = Math.floor(self.count / self.rows);

      var itemsPerPage = self.width * self.rows;

      var page = Math.floor(self.count / itemsPerPage);

      var game = $('
');
      game.css('top', self.margin().TOP + ((App.Grid.Cell.HEIGHT + App.Grid.Cell.MARGIN) * row));
      game.css('left', self.margin().LEFT + ((self.margin().LEFT + self.margin().RIGHT) * page) + ((App.Grid.Cell.WIDTH + App.Grid.Cell.MARGIN) * col));
      game.css('height', App.Grid.Cell.HEIGHT);
      game.css('width', App.Grid.Cell.WIDTH);

      var gameTitle = $('
');
      gameTitle.html(title);
      game.append(gameTitle);

      if (thumbnail !== undefined) {
        var img = $('');
        img.attr("src", thumbnail);
        game.append(img);
      }

      // Grey out ROMs which are only available online.
      if (offline === false) {
        game.css("opacity", "0.5");
      }

      self.content.append(game);
      self.count += 1;

    },

    // Convert a position in container coordinates to content coordinates.
    contentPosition: function(position) {
      var self = this;
      var contentPosition = {
        x: position.x + (self.pageWidth * self.page),
        y: position.y
      };
      return contentPosition;
    },

    // Determine with which item a touch position intersects.
    // undefined if the touch does not intersect an item.
    itemForPosition: function(position) {
      var self = this;

      // Work out which item it is.
      var contentPosition = self.contentPosition(position);
      var x = Math.floor(contentPosition.x / (App.Grid.Cell.WIDTH + App.Grid.Cell.MARGIN));
      var y = Math.floor((contentPosition.y - self.margin().TOP) / (App.Grid.Cell.HEIGHT + App.Grid.Cell.MARGIN));

      var index = (x * self.rows) + y;
      if (index < self.count) {
        self.delegate.didSelectItemForRow(index);
      }

    },

    minPage: function() {
      var self = this;
      return 0;
    },

    maxPage: function() {
      var self = this;
      var max = Math.floor(self.count / (self.rows * self.width));
      return max;
    },

    // Animate transition to a given page.
    animate: function(page) {
      var self = this;
      self.content.animate({
        'left': -1 * (page * self.pageWidth)
      }, 300, function() {
        self.updatePageItems();
      });
    },

    setPage: function(page) {
      var self = this;
      if (self.page !== page) {
        self.page = page;
        self.animate(self.page);
      }
    },

    // Returns the distance between two points.
    distance: function(a, b) {
      var self = this;
      var x = a.x - b.x;
      var y = a.y - b.y;
      return Math.sqrt(x*x + y*y);
    },

    // Returns the horizontal distance between two points.
    distanceX: function(a, b) {
      var self = this;
      return b.x - a.x;
    },

    // Returns the vertical distance between two points.
    distanceY: function(a, b) {
      var self = this;
      return b.y - a.y;
    },

    // Returns true if the touch event represents a move from the
    // original touchStart position.
    touchIsMove: function(position) {
      var self = this;
      var distance = Math.abs(self.distanceX(self.touchStart, position));
      return (distance >= App.Grid.MOVE_THRESHOLD);
    },

    updateContentPosition: function(position) {
      var self = this;

      var distance = position.x - self.touchStart.x;

      // Scale the offset if necessary.
      var left = distance;
      if (self.page == self.minPage() &&
          left > 0) {
        left = distance / 2;
      } else if (self.page == self.maxPage() &&
                 left < 0) {
        left = distance / 2;
      }

      // Update the position.
      self.content.offset({
        'left': self.offset.left + left,
        'top': self.offset.top
      });

    },

    onTouchEvent: function(state, position, timestamp) {
      var self = this;

      if (state === App.Control.Touch.START) {

        self.offset = self.content.offset();
        self.touchStart = position;
        self.touchDidMove = false;
        self.touchCount = 1;

      } else if (state === App.Control.Touch.MOVE) {
        if (self.touchCount > 0) {

          // Update the move status.
          self.touchDidMove = self.touchDidMove | self.touchIsMove(position);
          if (self.touchDidMove) {
            self.updateContentPosition(position);
          }

        }
      } else if (state === App.Control.Touch.END) {
        if (self.touchCount > 0) {

          // Update the move status.
          self.touchDidMove = self.touchDidMove | self.touchIsMove(position);

          if (self.touchDidMove) {
            // Update the position.
            self.updateContentPosition(position);

            // Work out if we are moving forwards or backwards.
            var page = self.page;
            var distance = self.distanceX(self.touchStart, position);
            if (Math.abs(distance) > ((self.pageWidth / 2) - App.Grid.SCROLL_BIAS)) {
              if (distance > 0) {
                page = page - 1;
              } else {
                page = page + 1;
              }
            }

            // If the user has not made a large enough movement to change the page,
            // check to see if we've matched a swipe gesture before giving up and
            // resetting back to the current the page.
            if (page === self.page) {
              if (self.gestureRecognizer.state === App.GestureRecognizer.State.RECOGNIZED) {
                if (self.gestureRecognizer.direction === App.GestureRecognizer.Direction.RIGHT) {
                  page = page - 1;
                } else if (self.gestureRecognizer.direction === App.GestureRecognizer.Direction.LEFT) {
                  page = page + 1;
                }
              }
            }

            // Animate back to the current page or move to the new page.
            if (page === self.page ||
                page < self.minPage() ||
                page > self.maxPage()) {
              self.animate(self.page);
            } else {
              self.setPage(page);
            }

            // Reset the gesture recognizer.
            self.gestureRecognizer.reset();

          } else {

            self.item = self.itemForPosition(position);

          }

          self.touchCount = 0;
        }
      }

    },

  });

})(jQuery);
<commit_msg>Only greying out games when the device is offline.<commit_after>
(function($) {

  App.Grid = function(device) {
    this.init(device);
  };

  App.Grid.Cell = {
    WIDTH:  140,
    HEIGHT: 140,
    MARGIN: 10
  };

  App.Grid.MOVE_THRESHOLD = 10;
  App.Grid.SCROLL_BIAS = 40;

  App.Grid.Margin = {
    Portrait: {
      TOP: 20,
      LEFT: 15,
      RIGHT: 15
    },
    Landscape: {
      TOP: 40,
      LEFT: 64,
      RIGHT: 64
    }
  };

  jQuery.extend(App.Grid.prototype, {

    init: function(device) {
      var self = this;
      self.device = device;
      self.identifier = '#list-games';
      self.element = $(self.identifier);
      self.content = $('#list-games-content');

      self.pageControl = $('#list-games-page-control');
      self.pageItems = [];

      self.count = 0;
      self.rows = 0;
      self.width = 0;
      self.pageWidth = 0;
      self.page = 0;

      self.dataSource = {
        'count' : function() { return 0; },
        'titleForIndex': function(index) { return ''; }
      };

      self.delegate = {
        'didSelectItemForRow': function(index) {}
      };

      self.touchListener = new App.TouchListener(self.identifier, self);
      self.touchStart = { x: 0, y: 0};
      self.touchStartTimestamp = 0;
      self.touchDidMove = false;
      self.touchCount = 0;

      self.gestureRecognizer = new App.GestureRecognizer();
      self.touchListener.addRecognizer(self.gestureRecognizer);

      self.updateLayout();
      $(window).resize(function() {
        self.updateLayout();
      });

    },

    // Return the margin for the current orientation.
    margin: function() {
      var self = this;
      if (self.device.orientation === App.Device.Orientation.PORTRAIT) {
        return App.Grid.Margin.Portrait;
      } else {
        return App.Grid.Margin.Landscape;
      }
    },

    reloadData: function() {
      var self = this;

      self.count = 0;
      self.content.html("");
      for (var i=0; i<self.dataSource.count(); i++) {
        var title = self.dataSource.titleForIndex(i);
        var thumbnail = self.dataSource.thumbnailForIndex(i);
        var offline = self.dataSource.availableOffline(i);
        self.add(i, title, thumbnail, offline);
      }

      self.updatePageControl();
      self.updatePageItems();
    },

    updateLayout: function() {
      var self = this;

      var cellHeight = App.Grid.Cell.HEIGHT + App.Grid.Cell.MARGIN;
      var cellWidth = App.Grid.Cell.WIDTH + App.Grid.Cell.MARGIN;

      var controlWidth = self.element.width() + App.Grid.Cell.MARGIN;
      var controlHeight = self.element.height() + App.Grid.Cell.MARGIN;

      var rows = Math.floor(controlHeight / cellHeight);
      var width =  Math.floor(controlWidth / cellWidth);
      // Relayout if required.
      if ((rows != self.rows) || (width != self.width)) {
        self.rows = rows;
        self.width = width;
        self.pageWidth = (self.width * (App.Grid.Cell.WIDTH + App.Grid.Cell.MARGIN)) + self.margin().LEFT + self.margin().RIGHT;
        self.page = 0;
        self.content.css('left', 0);
        self.reloadData();
      }

    },

    updatePageControl: function() {
      var self = this;

      self.pageControl.html("");
      self.pageItems = [];

      if (self.count === 0) {
        return;
      }

      for (var i=self.minPage(); i <= self.maxPage(); i++) {
        var item = $('
');
        self.pageControl.append(item);
        self.pageItems.push(item);
      }
    },

    updatePageItems: function() {
      var self = this;

      if (self.count === 0) {
        return;
      }

      for (var i = 0; i < self.pageItems.length; i++) {
        var item = self.pageItems[i];
        if (i === self.page) {
          item.addClass("active");
        } else {
          item.removeClass("active");
        }
      }
    },

    add: function(index, title, thumbnail, offline) {
      var self = this;

      var row = self.count % self.rows;
      var col = Math.floor(self.count / self.rows);

      var itemsPerPage = self.width * self.rows;

      var page = Math.floor(self.count / itemsPerPage);

      var game = $('
');
      game.css('top', self.margin().TOP + ((App.Grid.Cell.HEIGHT + App.Grid.Cell.MARGIN) * row));
      game.css('left', self.margin().LEFT + ((self.margin().LEFT + self.margin().RIGHT) * page) + ((App.Grid.Cell.WIDTH + App.Grid.Cell.MARGIN) * col));
      game.css('height', App.Grid.Cell.HEIGHT);
      game.css('width', App.Grid.Cell.WIDTH);

      var gameTitle = $('
');
      gameTitle.html(title);
      game.append(gameTitle);

      if (thumbnail !== undefined) {
        var img = $('');
        img.attr("src", thumbnail);
        game.append(img);
      }

      // Grey out ROMs which are only available online.
      if (window.navigator.onLine === false && offline === false) {
        game.css("opacity", "0.5");
      }

      self.content.append(game);
      self.count += 1;

    },

    // Convert a position in container coordinates to content coordinates.
    contentPosition: function(position) {
      var self = this;
      var contentPosition = {
        x: position.x + (self.pageWidth * self.page),
        y: position.y
      };
      return contentPosition;
    },

    // Determine with which item a touch position intersects.
    // undefined if the touch does not intersect an item.
    itemForPosition: function(position) {
      var self = this;

      // Work out which item it is.
      var contentPosition = self.contentPosition(position);
      var x = Math.floor(contentPosition.x / (App.Grid.Cell.WIDTH + App.Grid.Cell.MARGIN));
      var y = Math.floor((contentPosition.y - self.margin().TOP) / (App.Grid.Cell.HEIGHT + App.Grid.Cell.MARGIN));

      var index = (x * self.rows) + y;
      if (index < self.count) {
        self.delegate.didSelectItemForRow(index);
      }

    },

    minPage: function() {
      var self = this;
      return 0;
    },

    maxPage: function() {
      var self = this;
      var max = Math.floor(self.count / (self.rows * self.width));
      return max;
    },

    // Animate transition to a given page.
    animate: function(page) {
      var self = this;
      self.content.animate({
        'left': -1 * (page * self.pageWidth)
      }, 300, function() {
        self.updatePageItems();
      });
    },

    setPage: function(page) {
      var self = this;
      if (self.page !== page) {
        self.page = page;
        self.animate(self.page);
      }
    },

    // Returns the distance between two points.
    distance: function(a, b) {
      var self = this;
      var x = a.x - b.x;
      var y = a.y - b.y;
      return Math.sqrt(x*x + y*y);
    },

    // Returns the horizontal distance between two points.
    distanceX: function(a, b) {
      var self = this;
      return b.x - a.x;
    },

    // Returns the vertical distance between two points.
    distanceY: function(a, b) {
      var self = this;
      return b.y - a.y;
    },

    // Returns true if the touch event represents a move from the
    // original touchStart position.
    touchIsMove: function(position) {
      var self = this;
      var distance = Math.abs(self.distanceX(self.touchStart, position));
      return (distance >= App.Grid.MOVE_THRESHOLD);
    },

    updateContentPosition: function(position) {
      var self = this;

      var distance = position.x - self.touchStart.x;

      // Scale the offset if necessary.
      var left = distance;
      if (self.page == self.minPage() &&
          left > 0) {
        left = distance / 2;
      } else if (self.page == self.maxPage() &&
                 left < 0) {
        left = distance / 2;
      }

      // Update the position.
      self.content.offset({
        'left': self.offset.left + left,
        'top': self.offset.top
      });

    },

    onTouchEvent: function(state, position, timestamp) {
      var self = this;

      if (state === App.Control.Touch.START) {

        self.offset = self.content.offset();
        self.touchStart = position;
        self.touchDidMove = false;
        self.touchCount = 1;

      } else if (state === App.Control.Touch.MOVE) {
        if (self.touchCount > 0) {

          // Update the move status.
          self.touchDidMove = self.touchDidMove | self.touchIsMove(position);
          if (self.touchDidMove) {
            self.updateContentPosition(position);
          }

        }
      } else if (state === App.Control.Touch.END) {
        if (self.touchCount > 0) {

          // Update the move status.
          self.touchDidMove = self.touchDidMove | self.touchIsMove(position);

          if (self.touchDidMove) {
            // Update the position.
            self.updateContentPosition(position);

            // Work out if we are moving forwards or backwards.
            var page = self.page;
            var distance = self.distanceX(self.touchStart, position);
            if (Math.abs(distance) > ((self.pageWidth / 2) - App.Grid.SCROLL_BIAS)) {
              if (distance > 0) {
                page = page - 1;
              } else {
                page = page + 1;
              }
            }

            // If the user has not made a large enough movement to change the page,
            // check to see if we've matched a swipe gesture before giving up and
            // resetting back to the current the page.
            if (page === self.page) {
              if (self.gestureRecognizer.state === App.GestureRecognizer.State.RECOGNIZED) {
                if (self.gestureRecognizer.direction === App.GestureRecognizer.Direction.RIGHT) {
                  page = page - 1;
                } else if (self.gestureRecognizer.direction === App.GestureRecognizer.Direction.LEFT) {
                  page = page + 1;
                }
              }
            }

            // Animate back to the current page or move to the new page.
            if (page === self.page ||
                page < self.minPage() ||
                page > self.maxPage()) {
              self.animate(self.page);
            } else {
              self.setPage(page);
            }

            // Reset the gesture recognizer.
            self.gestureRecognizer.reset();

          } else {

            self.item = self.itemForPosition(position);

          }

          self.touchCount = 0;
        }
      }

    },

  });

})(jQuery);
<|endoftext|>


<commit_before>//import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
//`Root` set up our application with `react-redux` and `react-router`
import Root from './components/root'
//We can import css from javascript with webpack `style-loader`
import '../css/style.css'
import '../css/flag-icon-css/flag-icon.min.css'
//Our app will be embeded in `index.html`; webpack file loader allows this
//kind of import to mark this 'dependence': `index.html` will be automatically
//copy in the `dist` directory during the build process.
import 'file?name=[name].[ext]!../index.html'

ReactDOM.render(
  <Root/>,
  document.getElementById('base')); <commit_msg>Add missing babel polyfill<commit_after>import 'babel-polyfill';
import React from 'react';
import ReactDOM from 'react-dom';
//`Root` set up our application with `react-redux` and `react-router`
import Root from './components/root'
//We can import css from javascript with webpack `style-loader`
import '../css/style.css'
import '../css/flag-icon-css/flag-icon.min.css'
//Our app will be embeded in `index.html`; webpack file loader allows this
//kind of import to mark this 'dependence': `index.html` will be automatically
//copy in the `dist` directory during the build process.
import 'file?name=[name].[ext]!../index.html'

ReactDOM.render(
  <Root/>,
  document.getElementById('base')); <|endoftext|>


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

/* global NGSI, StyledElements */

(function () {

    "use strict";

    var DataViewer = function DataViewer() {

        /* Context */
        MashupPlatform.widget.context.registerCallback(function (newValues) {
            if (this.layout && ("heightInPixels" in newValues || "widthInPixels" in newValues)) {
                this.layout.repaint();
            }
        }.bind(this));

        /* Preferences */
        MashupPlatform.prefs.registerCallback(this.updateNGSIConnection.bind(this));

        this.layout = null;
        this.table = null;
    };

    DataViewer.prototype.init = function init() {
        createNGSISource.call(this);
        this.updateNGSIConnection();

        this.layout = new StyledElements.BorderLayout();
        createTable.call(this);

        this.layout.getCenterContainer().addClassName('loading');
        this.layout.insertInto(document.body);
        this.layout.repaint();
    };

    DataViewer.prototype.updateNGSIConnection = function updateNGSIConnection() {

        this.ngsi_server = MashupPlatform.prefs.get('ngsi_server');
        this.ngsi_proxy = MashupPlatform.prefs.get('ngsi_proxy');
        this.ngsi_connection = new NGSI.Connection(this.ngsi_server, {
            use_user_fiware_token: MashupPlatform.prefs.get('use_user_fiware_token'),
            ngsi_proxy_url: this.ngsi_proxy
        });
    };

    /**************************************************************************/
    /****************************** HANDLERS **********************************/
    /**************************************************************************/

    var onRowClick = function onRowClick(row) {
        MashupPlatform.wiring.pushEvent('selection', JSON.stringify(row));
    };

    var onNGSIQuerySuccess = function onNGSIQuerySuccess(next, page, data, details) {
        for (var i = 0; i < data.length; i++) {
            if (Array.isArray(data[i].attributes)) {
                data[i].attributes = data[i].attributes.join(', ');
            } else {
                data[i].attributes = '';
            }
        }

        var search_info = {
            'resources': data,
            'current_page': page,
            'total_count': details.count
        };

        next(data, search_info);
    };

    var createNGSISource = function createNGSISource() {
        this.ngsi_source = new StyledElements.PaginatedSource({
            'pageSize': 30,
            'requestFunc': function (page, options, onSuccess, onError) {
                if (this.ngsi_connection !== null) {
                    this.ngsi_connection.getAvailableTypes({
                        limit: options.pageSize,
                        offset: (page - 1) * options.pageSize,
                        onSuccess: onNGSIQuerySuccess.bind(null, onSuccess, page),
                        onFailure: onError
                    });
                } else {
                    onSuccess([], {resources: [], total_count: 0, current_page: 0});
                }
            }.bind(this)
        });
        this.ngsi_source.addEventListener('requestStart', function () {
            this.layout.getCenterContainer().disable();
        }.bind(this));
        this.ngsi_source.addEventListener('requestEnd', function () {
            this.layout.getCenterContainer().enable();
        }.bind(this));
    };

    var createTable = function createTable() {
        var fields;

        // Create the table
        fields = [
            {field: 'name', label: 'Type', sortable: true, width: "20%"},
            {field: 'attributes', label: 'Attributes', sortable: false}
        ];
        this.table = new StyledElements.ModelTable(fields, {id: 'id', pageSize: 30, source: this.ngsi_source, 'class': 'table-striped'});
        this.table.addEventListener("click", onRowClick);
        this.table.reload();
        this.layout.center.clear();
        this.layout.center.appendChild(this.table);
    };

    var data_viewer = new DataViewer();
    window.addEventListener("DOMContentLoaded", data_viewer.init.bind(data_viewer), false);

})();
<commit_msg>Orion doesn't allow sort results by type<commit_after>/*
 * Copyright (c) 2015 CoNWeT Lab., Universidad Politécnica de Madrid
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/* global NGSI, StyledElements */

(function () {

    "use strict";

    var DataViewer = function DataViewer() {

        /* Context */
        MashupPlatform.widget.context.registerCallback(function (newValues) {
            if (this.layout && ("heightInPixels" in newValues || "widthInPixels" in newValues)) {
                this.layout.repaint();
            }
        }.bind(this));

        /* Preferences */
        MashupPlatform.prefs.registerCallback(this.updateNGSIConnection.bind(this));

        this.layout = null;
        this.table = null;
    };

    DataViewer.prototype.init = function init() {
        createNGSISource.call(this);
        this.updateNGSIConnection();

        this.layout = new StyledElements.BorderLayout();
        createTable.call(this);

        this.layout.getCenterContainer().addClassName('loading');
        this.layout.insertInto(document.body);
        this.layout.repaint();
    };

    DataViewer.prototype.updateNGSIConnection = function updateNGSIConnection() {

        this.ngsi_server = MashupPlatform.prefs.get('ngsi_server');
        this.ngsi_proxy = MashupPlatform.prefs.get('ngsi_proxy');
        this.ngsi_connection = new NGSI.Connection(this.ngsi_server, {
            use_user_fiware_token: MashupPlatform.prefs.get('use_user_fiware_token'),
            ngsi_proxy_url: this.ngsi_proxy
        });
    };

    /**************************************************************************/
    /****************************** HANDLERS **********************************/
    /**************************************************************************/

    var onRowClick = function onRowClick(row) {
        MashupPlatform.wiring.pushEvent('selection', JSON.stringify(row));
    };

    var onNGSIQuerySuccess = function onNGSIQuerySuccess(next, page, data, details) {
        for (var i = 0; i < data.length; i++) {
            if (Array.isArray(data[i].attributes)) {
                data[i].attributes = data[i].attributes.join(', ');
            } else {
                data[i].attributes = '';
            }
        }

        var search_info = {
            'resources': data,
            'current_page': page,
            'total_count': details.count
        };

        next(data, search_info);
    };

    var createNGSISource = function createNGSISource() {
        this.ngsi_source = new StyledElements.PaginatedSource({
            'pageSize': 30,
            'requestFunc': function (page, options, onSuccess, onError) {
                if (this.ngsi_connection !== null) {
                    this.ngsi_connection.getAvailableTypes({
                        limit: options.pageSize,
                        offset: (page - 1) * options.pageSize,
                        onSuccess: onNGSIQuerySuccess.bind(null, onSuccess, page),
                        onFailure: onError
                    });
                } else {
                    onSuccess([], {resources: [], total_count: 0, current_page: 0});
                }
            }.bind(this)
        });
        this.ngsi_source.addEventListener('requestStart', function () {
            this.layout.getCenterContainer().disable();
        }.bind(this));
        this.ngsi_source.addEventListener('requestEnd', function () {
            this.layout.getCenterContainer().enable();
        }.bind(this));
    };

    var createTable = function createTable() {
        var fields;

        // Create the table
        fields = [
            {field: 'name', label: 'Type', sortable: false, width: "20%"},
            {field: 'attributes', label: 'Attributes', sortable: false}
        ];
        this.table = new StyledElements.ModelTable(fields, {id: 'id', pageSize: 30, source: this.ngsi_source, 'class': 'table-striped'});
        this.table.addEventListener("click", onRowClick);
        this.table.reload();
        this.layout.center.clear();
        this.layout.center.appendChild(this.table);
    };

    var data_viewer = new DataViewer();
    window.addEventListener("DOMContentLoaded", data_viewer.init.bind(data_viewer), false);

})();
<|endoftext|>


<commit_before>require.config({
  baseUrl: '/js',
  noGlobal: true,

  paths: {
    'underscore': '../bower_components/underscore/underscore',
    'underscore.string': '../bower_components/underscore.string/lib/underscore.string',
    'jquery': '../bower_components/jquery/dist/jquery',
    'backbone': '../bower_components/backbone/backbone',
    'backbone.babysitter': '../bower_components/backbone.babysitter/lib/backbone.babysitter',
    'backbone.wreqr': '../bower_components/backbone.wreqr/lib/backbone.wreqr',
    'backbone.localstorage': '../bower_components/backbone.localstorage/backbone.localStorage',
    'backbone.validation': '../bower_components/backbone-validation/dist/backbone-validation-amd',
    'marionette': '../bower_components/marionette/lib/core/amd/backbone.marionette',
    'bootstrap': '../bower_components/bootstrap/dist/js/bootstrap',
    'jade': '../bower_components/jade/runtime',
    'moment': '../bower_components/moment/min/moment-with-langs',
    'd3': '../bower_components/d3/d3',
    'crypto': '../bower_components/cryptojslib/rollups/hmac-sha256',
    'monetary': '../bower_components/monetary/dist/monetary.full',
    'parse': '../bower_components/parse-js-sdk/lib/parse',

    'validators': 'lib/validators'
  },

  shim: {
    'underscore': {
      exports: '_'
    },
    'underscore.string': {
      deps: ['underscore']
    },
    'backbone': {
      exports: 'Backbone',
      deps: ['underscore', 'jquery']
    },
    'bootstrap': {
      deps: ['jquery']
    },
    'crypto': {
      exports: 'CryptoJS'
    },
    parse: {
      deps: ['jquery', 'underscore'],
      exports: 'Parse'
    }
  }
});

require(['parse', 'app'], function (Parse, app) {
  Parse.initialize(
    'TTkLNPMw8KOMzJUcjumW2aOb340MFbWZhfphVr0w',
    'l1AEye0vXbDUFQeoVnqT97hVGE08tzeaPqbvhzI5');

  app.start();
});
<commit_msg>Fix reference to renamed moment file<commit_after>require.config({
  baseUrl: '/js',
  noGlobal: true,

  paths: {
    'underscore': '../bower_components/underscore/underscore',
    'underscore.string': '../bower_components/underscore.string/lib/underscore.string',
    'jquery': '../bower_components/jquery/dist/jquery',
    'backbone': '../bower_components/backbone/backbone',
    'backbone.babysitter': '../bower_components/backbone.babysitter/lib/backbone.babysitter',
    'backbone.wreqr': '../bower_components/backbone.wreqr/lib/backbone.wreqr',
    'backbone.localstorage': '../bower_components/backbone.localstorage/backbone.localStorage',
    'backbone.validation': '../bower_components/backbone-validation/dist/backbone-validation-amd',
    'marionette': '../bower_components/marionette/lib/core/amd/backbone.marionette',
    'bootstrap': '../bower_components/bootstrap/dist/js/bootstrap',
    'jade': '../bower_components/jade/runtime',
    'moment': '../bower_components/moment/min/moment-with-locales',
    'd3': '../bower_components/d3/d3',
    'crypto': '../bower_components/cryptojslib/rollups/hmac-sha256',
    'monetary': '../bower_components/monetary/dist/monetary.full',
    'parse': '../bower_components/parse-js-sdk/lib/parse',

    'validators': 'lib/validators'
  },

  shim: {
    'underscore': {
      exports: '_'
    },
    'underscore.string': {
      deps: ['underscore']
    },
    'backbone': {
      exports: 'Backbone',
      deps: ['underscore', 'jquery']
    },
    'bootstrap': {
      deps: ['jquery']
    },
    'crypto': {
      exports: 'CryptoJS'
    },
    parse: {
      deps: ['jquery', 'underscore'],
      exports: 'Parse'
    }
  }
});

require(['parse', 'app'], function (Parse, app) {
  Parse.initialize(
    'TTkLNPMw8KOMzJUcjumW2aOb340MFbWZhfphVr0w',
    'l1AEye0vXbDUFQeoVnqT97hVGE08tzeaPqbvhzI5');

  app.start();
});
<|endoftext|>


<commit_before>//########################################################
//###############   STATE OBJECT and CONSTANTS  ##########
//########################################################
const state = {
  guns: []
}

var template = '';

//const rootURL = 'http://localhost:8080/guns';

const rootURL = 'https://firearmbase.herokuapp.com/guns';

//#########################################################
//#################  STATE MODIFICATION METHODS  ##########
//#########################################################

function getAllGuns() {
  return new Promise(function (res, rej) {
    $.ajax({
      url: rootURL,
      type: "GET",
      headers: {
        "accept": "application/jsonp;odata=verbose",
      },
      success: function(gundata) {
        var num=0;
        gundata.forEach( gun => {
          //state.guns[gun.fullName] = gun;
          state.guns[num] = gun;
          num++;
        });
        //console.log('StateObject: ',state.guns);
        console.log('first promise hit');
        res();
      },
      error: function(error){
        console.log('error: ',error);
      }
    })
  })
  return state;
}

function outputGunsReport() {
  // return new Promise( (res, rej) => {
    template = '
'
    state.guns.forEach( gun => {
      console.log('THREE: ', typeof gun)
      template += '
'+gun.fullName+'
'
    })
    template += '
'
    console.log('2nd promise--template: ', template);
    $("#output").html(template);
  // });
}

// getAllGuns()
// .then(function () {
//   template = '
'
//   state.guns.forEach( gun => {
//     console.log('THREE: ', typeof gun)
//     template += '
'+gun.fullName+'
'
//   })
//   template += '
'
//   console.log('template: ', template);
//   return outputGuns(template);
// })
// .then(function(res) {
//     //$("#output").html(res);
//     outputGuns(res);
// })
//
// console.log('ONE:  State object: ', state.guns)

getAllGuns()
.then(outputGunsReport);

//#########################################################
//#################  DOM MODIFICATION METHODS  ############
//#########################################################

// function outputGuns(template){
//   $("#output").html(template);
// }

//var content = outputGuns();
//console.log('Content: ', template)

// $("#output").html(template);

//#########################################################
//#################  PROGRAM CONTROL FLOW  ################
//#########################################################
<commit_msg>starting to create some functionality for the top page with crud buttons<commit_after>//########################################################
//###############   STATE OBJECT and CONSTANTS  ##########
//########################################################
const state = {
  guns: []
}

//var template = '';

const rootURL = 'http://localhost:8080/guns';

//const rootURL = 'https://firearmbase.herokuapp.com/guns';

//#########################################################
//#################  STATE MODIFICATION METHODS  ##########
//#########################################################

function getAllGuns() {
  return new Promise(function (res, rej) {
    $.ajax({
      url: rootURL,
      type: "GET",
      headers: {
        "accept": "application/jsonp;odata=verbose",
      },
      success: function(gundata) {
        var num=0;
        gundata.forEach( gun => {
          //state.guns[gun.fullName] = gun;
          state.guns[num] = gun;
          num++;
        });
        //console.log('StateObject: ',state.guns);
        console.log('first promise hit');
        res();
      },
      error: function(error){
        console.log('error: ',error);
      }
    })
  })
  return state;
}

// getAllGuns()
// .then(function () {
//   template = '
'
//   state.guns.forEach( gun => {
//     console.log('THREE: ', typeof gun)
//     template += '
'+gun.fullName+'
'
//   })
//   template += '
'
//   console.log('template: ', template);
//   return outputGuns(template);
// })
// .then(function(res) {
//     //$("#output").html(res);
//     outputGuns(res);
// })
//
// console.log('ONE:  State object: ', state.guns)

getAllGuns()
.then(outputGunsReport);

//#########################################################
//#################  DOM MODIFICATION METHODS  ############
//#########################################################

function outputGunsReport() {
  // return new Promise( (res, rej) => {
    var template = '
'
    state.guns.forEach( gun => {
      console.log('ONE: ', typeof gun)
      template += '
'+gun.fullName+'
'
    })
    template += '
'
    console.log('outputGunsReport template: ', template);
    $("#output").html(template);
  // });
}

//#########################################################
//#################  PROGRAM CONTROL FLOW  ################
//#########################################################

//This function shows the opening menu
function showMenu(){
  var template = ''
}
<|endoftext|>


<commit_before>/*global QUnit:false, module:false, test:false, asyncTest:false, expect:false*/
/*global start:false, stop:false ok:false, equal:false, notEqual:false, deepEqual:false*/
/*global notDeepEqual:false, strictEqual:false, notStrictEqual:false, raises:false*/
(function($) {

  /*
    ======== A Handy Little QUnit Reference ========
    http://docs.jquery.com/QUnit

    Test methods:
      expect(numAssertions)
      stop(increment)
      start(decrement)
    Test assertions:
      ok(value, [message])
      equal(actual, expected, [message])
      notEqual(actual, expected, [message])
      deepEqual(actual, expected, [message])
      notDeepEqual(actual, expected, [message])
      strictEqual(actual, expected, [message])
      notStrictEqual(actual, expected, [message])
      raises(block, [expected], [message])
  */

  function clearBody() {
      var irisGeneratedCode = $("#start_iris").nextAll();
      if (irisGeneratedCode !== undefined) {
          irisGeneratedCode.remove();
      }
  }

  module('Module Event', {
      setup: function() {
          iris.notify("iris-reset");
      },
      teardown: function () {
          clearBody();
      }
  });

  test("Notify An Undefined Event", function () {
      expect(1);

      raises(function () {
          iris.notify(undefined);

      },
      "[notify] event name parameter is not defined",
      "Thrown an exception when notify an undefined event");
  });

  test("Notify An Event Without Callbacks Test", function () {
      expect(1);

      iris.notify("test-event");

      window.ok(true, "No errors when notify a undefined event without callbacks");
  });

  test("On & Off Test", function () {
      expect(1);

      iris.on("test-event", onEvent);
      iris.notify("test-event"); // +1

      iris.off("test-event", onEvent);
      iris.notify("test-event"); // 0

  });

  test("Manage Multiple Event Types Test", function () {
      expect(8);

      iris.on("event-type-1", onEvent);
      iris.notify("event-type-1"); // +1

      iris.on("event-type-2", onEvent);
      iris.notify("event-type-2"); // +1

      iris.on("event-type-1", onEvent2);
      iris.notify("event-type-1"); // +2

      iris.on("event-type-2", onEvent2);
      iris.notify("event-type-2"); // +2

      iris.off("event-type-1", onEvent);
      iris.notify("event-type-1"); // +1

      iris.off("event-type-2", onEvent);
      iris.notify("event-type-2"); // +1

      iris.off("event-type-1", onEvent2);
      iris.notify("event-type-1"); // 0

      iris.off("event-type-2", onEvent2);
      iris.notify("event-type-2"); // 0
  });

  test("Duplicated Event Test", function () {
      expect(1);

      iris.on("duplicated-event", onEvent);
      iris.on("duplicated-event", onEvent);
      iris.on("duplicated-event", onEvent);

      iris.notify("duplicated-event");

  });

  test("Off all functions Test", function () {
      expect(3);

      iris.on("off-all-functions", onEvent);
      iris.on("off-all-functions", onEvent2);

      iris.notify("off-all-functions"); // +2

      iris.off("off-all-functions");

      iris.notify("off-all-functions"); // 0

      iris.on("off-all-functions", onEvent);
      iris.notify("off-all-functions"); // +1
  });

  test("Invalid functions", function () {
      expect(7);

      raises(function () {
          iris.on("test", undefined);
      },
      "invalid function",
      "Thrown an exception when callback is undefined");

      raises(function () {
          iris.on("test", new Date());
      },
      "invalid function",
      "Thrown an exception when callback is Date");

      raises(function () {
          iris.on("test", 'function');
      },
      "invalid function",
      "Thrown an exception when callback is 'function'");

      raises(function () {
          iris.on("test", null);
      },
      "invalid function",
      "Thrown an exception when callback is null");

      iris.on("test", function () {}); // first create test callback array before test iris.off

      raises(function () {
          iris.off("test", new Date());
      },
      "invalid function",
      "Thrown an exception when callback is Date");

      raises(function () {
          iris.off("test", 'function');
      },
      "invalid function",
      "Thrown an exception when callback is 'function'");

      raises(function () {
          iris.off("test", null);
      },
      "invalid function",
      "Thrown an exception when callback is null");
  });

  function onEvent () {
    window.ok(true, "On event callback");
  }

  function onEvent2 () {
    window.ok(true, "On event2 callback");
  }

}(jQuery));<commit_msg>Improved iris.Event.off() tests<commit_after>/*global QUnit:false, module:false, test:false, asyncTest:false, expect:false*/
/*global start:false, stop:false ok:false, equal:false, notEqual:false, deepEqual:false*/
/*global notDeepEqual:false, strictEqual:false, notStrictEqual:false, raises:false*/
(function($) {

  /*
    ======== A Handy Little QUnit Reference ========
    http://docs.jquery.com/QUnit

    Test methods:
      expect(numAssertions)
      stop(increment)
      start(decrement)
    Test assertions:
      ok(value, [message])
      equal(actual, expected, [message])
      notEqual(actual, expected, [message])
      deepEqual(actual, expected, [message])
      notDeepEqual(actual, expected, [message])
      strictEqual(actual, expected, [message])
      notStrictEqual(actual, expected, [message])
      raises(block, [expected], [message])
  */

  function clearBody() {
      var irisGeneratedCode = $("#start_iris").nextAll();
      if (irisGeneratedCode !== undefined) {
          irisGeneratedCode.remove();
      }
  }

  module('Module Event', {
      setup: function() {
          iris.notify("iris-reset");
      },
      teardown: function () {
          clearBody();
      }
  });

  test("Notify An Undefined Event", function () {
      expect(1);

      raises(function () {
          iris.notify(undefined);

      },
      "[notify] event name parameter is not defined",
      "Thrown an exception when notify an undefined event");
  });

  test("Notify An Event Without Callbacks Test", function () {
      expect(1);

      iris.notify("test-event");

      window.ok(true, "No errors when notify a undefined event without callbacks");
  });

  test("On & Off Test", function () {
      expect(1);

      iris.on("test-event", onEvent);
      iris.notify("test-event"); // +1

      iris.off("test-event", onEvent);
      iris.notify("test-event"); // 0

  });

  test("Manage Multiple Event Types Test", function () {
      expect(8);

      iris.on("event-type-1", onEvent);
      iris.notify("event-type-1"); // +1

      iris.on("event-type-2", onEvent);
      iris.notify("event-type-2"); // +1

      iris.on("event-type-1", onEvent2);
      iris.notify("event-type-1"); // +2

      iris.on("event-type-2", onEvent2);
      iris.notify("event-type-2"); // +2

      iris.off("event-type-1", onEvent);
      iris.notify("event-type-1"); // +1

      iris.off("event-type-2", onEvent);
      iris.notify("event-type-2"); // +1

      iris.off("event-type-1", onEvent2);
      iris.notify("event-type-1"); // 0

      iris.off("event-type-2", onEvent2);
      iris.notify("event-type-2"); // 0
  });

  test("Duplicated Event Test", function () {
      expect(1);

      iris.on("duplicated-event", onEvent);
      iris.on("duplicated-event", onEvent);
      iris.on("duplicated-event", onEvent);

      iris.notify("duplicated-event");

  });

  test("Off all functions Test", function () {
      expect(3);

      iris.on("off-all-functions", onEvent);
      iris.on("off-all-functions", onEvent2);

      iris.notify("off-all-functions"); // +2

      iris.off("off-all-functions");

      iris.notify("off-all-functions"); // 0

      iris.on("off-all-functions", onEvent);
      iris.notify("off-all-functions"); // +1
  });

  test("Invalid functions", function () {
      expect(7);

      raises(function () {
          iris.on("test", undefined);
      },
      "invalid function",
      "Thrown an exception when callback is undefined");

      raises(function () {
          iris.on("test", new Date());
      },
      "invalid function",
      "Thrown an exception when callback is Date");

      raises(function () {
          iris.on("test", 'function');
      },
      "invalid function",
      "Thrown an exception when callback is 'function'");

      raises(function () {
          iris.on("test", null);
      },
      "invalid function",
      "Thrown an exception when callback is null");

      iris.on("test", function () {}); // first create test callback array before test iris.off

      raises(function () {
          iris.off("test", new Date());
      },
      "invalid function",
      "Thrown an exception when callback is Date");

      raises(function () {
          iris.off("test", 'function');
      },
      "invalid function",
      "Thrown an exception when callback is 'function'");

      raises(function () {
          iris.off("test", null);
      },
      "invalid function",
      "Thrown an exception when callback is null");
  });

  function onEvent () {
    window.ok(true, "On event callback");
  }

  function onEvent2 () {
    window.ok(true, "On event2 callback");
  }

  // Test component event functions

  module('Module Event in Components', {
      setup: function() {
          iris.notify("iris-reset");
          iris.path = {
              welcome : "test/event/welcome.js",
              welcome_tmpl : "test/event/welcome.html"
          };
      },
      teardown: function () {
          clearBody();
      }
  });

  asyncTest("Execute self.on event defined whitin screen", function() {

    expect(1);

    iris.welcome(iris.path.welcome);

    iris.on(iris.AFTER_NAVIGATION, function () {
      iris.off(iris.AFTER_NAVIGATION);
      iris.notify('test-event');

      start();
    });
  });

  asyncTest("Execute self.off event defined within screen", function() {

    expect(1);

    iris.welcome(iris.path.welcome);

    iris.on(iris.AFTER_NAVIGATION, function () {
      iris.off(iris.AFTER_NAVIGATION);
      iris.notify('remove-test-event');

      start();
    });
  });

  asyncTest("Execute self.off event (without callback) defined within screen", function() {

    expect(1);

    iris.welcome(iris.path.welcome);

    iris.on(iris.AFTER_NAVIGATION, function () {
      iris.off(iris.AFTER_NAVIGATION);
      iris.notify('remove-all-test-event');

      start();
    });
  });

}(jQuery));<|endoftext|>


<commit_before>/* jslint node: true */
'use strict';

//  ENiGMA½
const setClientTheme    = require('./theme.js').setClientTheme;
const clientConnections = require('./client_connections.js').clientConnections;
const StatLog           = require('./stat_log.js');
const logger            = require('./logger.js');
const Events            = require('./events.js');
const Config            = require('./config.js').get;
const {
    Errors,
    ErrorReasons
}                       = require('./enig_error.js');
const UserProps         = require('./user_property.js');
const SysProps          = require('./system_property.js');
const SystemLogKeys     = require('./system_log.js');
const User              = require('./user.js');

//  deps
const async             = require('async');
const _                 = require('lodash');
const assert            = require('assert');

exports.userLogin             = userLogin;
exports.recordLogin           = recordLogin;
exports.transformLoginError   = transformLoginError;

function userLogin(client, username, password, options, cb) {
    if(!cb && _.isFunction(options)) {
        cb = options;
        options = {};
    }

    const config = Config();

    if(config.users.badUserNames.includes(username.toLowerCase())) {
        client.log.info( { username, ip : client.remoteAddress }, 'Attempt to login with banned username');

        //  slow down a bit to thwart brute force attacks
        return setTimeout( () => {
            return cb(Errors.BadLogin('Disallowed username', ErrorReasons.NotAllowed));
        }, 2000);
    }

    const authInfo = {
        username,
        password,
    };

    authInfo.type   = options.authType || User.AuthFactor1Types.Password;
    authInfo.pubKey = options.ctx;

    client.user.authenticateFactor1(authInfo, err => {
        if(err) {
            return cb(transformLoginError(err, client, username));
        }

        const user = client.user;

        //  Good login; reset any failed attempts
        delete client.sessionFailedLoginAttempts;

        //
        //  Ensure this user is not already logged in.
        //
        const existingClientConnection = clientConnections.find(cc => {
            return user !== cc.user &&          //  not current connection
                user.userId === cc.user.userId; //  ...but same user
        });

        if(existingClientConnection) {
            client.log.info(
                {
                    existingClientId    : existingClientConnection.session.id,
                    username            : user.username,
                    userId              : user.userId
                },
                'Already logged in'
            );

            return cb(Errors.BadLogin(
                `User ${user.username} already logged in.`,
                ErrorReasons.AlreadyLoggedIn
            ));
        }

        //  update client logger with addition of username
        client.log = logger.log.child(
            {
                clientId    : client.log.fields.clientId,
                sessionId   : client.log.fields.sessionId,
                username    : user.username,
            }
        );
        client.log.info('Successful login');

        //  User's unique session identifier is the same as the connection itself
        user.sessionId = client.session.uniqueId;   //  convenience

        Events.emit(Events.getSystemEvents().UserLogin, { user } );

        setClientTheme(client, user.properties[UserProps.ThemeId]);
        if(user.authenticated) {
            return recordLogin(client, cb);
        }

        //  recordLogin() must happen after 2FA!
        return cb(null);
    });
}

function recordLogin(client, cb) {
    assert(client.user.authenticated);  //  don't get in situations where this isn't true

    const user = client.user;
    async.parallel(
        [
            (callback) => {
                StatLog.incrementNonPersistentSystemStat(SysProps.LoginsToday, 1);
                return StatLog.incrementSystemStat(SysProps.LoginCount, 1, callback);
            },
            (callback) => {
                return StatLog.setUserStat(user, UserProps.LastLoginTs, StatLog.now, callback);
            },
            (callback) => {
                return StatLog.incrementUserStat(user, UserProps.LoginCount, 1, callback);
            },
            (callback) => {
                const loginHistoryMax = Config().statLog.systemEvents.loginHistoryMax;
                const historyItem = JSON.stringify({
                    userId      : user.userId,
                    sessionId   : user.sessionId,
                });

                return StatLog.appendSystemLogEntry(
                    SystemLogKeys.UserLoginHistory,
                    historyItem,
                    loginHistoryMax,
                    StatLog.KeepType.Max,
                    callback
                );
            }
        ],
        err => {
            return cb(err);
        }
    );
}

function transformLoginError(err, client, username) {
    client.sessionFailedLoginAttempts = _.get(client, 'sessionFailedLoginAttempts', 0) + 1;
    const disconnect = Config().users.failedLogin.disconnect;
    if(disconnect > 0 && client.sessionFailedLoginAttempts >= disconnect) {
        err = Errors.BadLogin('To many failed login attempts', ErrorReasons.TooMany);
    }

    client.log.info( { username, ip : client.remoteAddress, reason : err.message }, 'Failed login attempt');
    return err;
}<commit_msg>Clean up defualt mesage/file conf/areas at login if user no longer has read access<commit_after>/* jslint node: true */
'use strict';

//  ENiGMA½
const setClientTheme    = require('./theme.js').setClientTheme;
const clientConnections = require('./client_connections.js').clientConnections;
const StatLog           = require('./stat_log.js');
const logger            = require('./logger.js');
const Events            = require('./events.js');
const Config            = require('./config.js').get;
const {
    Errors,
    ErrorReasons
}                       = require('./enig_error.js');
const UserProps         = require('./user_property.js');
const SysProps          = require('./system_property.js');
const SystemLogKeys     = require('./system_log.js');
const User              = require('./user.js');
const {
    getMessageConferenceByTag,
    getMessageAreaByTag,
    getDefaultMessageConferenceTag,
    getDefaultMessageAreaTagByConfTag,
}                       = require('./message_area.js');
const {
    getFileAreaByTag,
    getDefaultFileAreaTag,
}                       = require('./file_base_area.js');

//  deps
const async             = require('async');
const _                 = require('lodash');
const assert            = require('assert');

exports.userLogin             = userLogin;
exports.recordLogin           = recordLogin;
exports.transformLoginError   = transformLoginError;

function userLogin(client, username, password, options, cb) {
    if(!cb && _.isFunction(options)) {
        cb = options;
        options = {};
    }

    const config = Config();

    if(config.users.badUserNames.includes(username.toLowerCase())) {
        client.log.info( { username, ip : client.remoteAddress }, 'Attempt to login with banned username');

        //  slow down a bit to thwart brute force attacks
        return setTimeout( () => {
            return cb(Errors.BadLogin('Disallowed username', ErrorReasons.NotAllowed));
        }, 2000);
    }

    const authInfo = {
        username,
        password,
    };

    authInfo.type   = options.authType || User.AuthFactor1Types.Password;
    authInfo.pubKey = options.ctx;

    client.user.authenticateFactor1(authInfo, err => {
        if(err) {
            return cb(transformLoginError(err, client, username));
        }

        const user = client.user;

        //  Good login; reset any failed attempts
        delete client.sessionFailedLoginAttempts;

        //
        //  Ensure this user is not already logged in.
        //
        const existingClientConnection = clientConnections.find(cc => {
            return user !== cc.user &&          //  not current connection
                user.userId === cc.user.userId; //  ...but same user
        });

        if(existingClientConnection) {
            client.log.info(
                {
                    existingClientId    : existingClientConnection.session.id,
                    username            : user.username,
                    userId              : user.userId
                },
                'Already logged in'
            );

            return cb(Errors.BadLogin(
                `User ${user.username} already logged in.`,
                ErrorReasons.AlreadyLoggedIn
            ));
        }

        //  update client logger with addition of username
        client.log = logger.log.child(
            {
                clientId    : client.log.fields.clientId,
                sessionId   : client.log.fields.sessionId,
                username    : user.username,
            }
        );
        client.log.info('Successful login');

        //  User's unique session identifier is the same as the connection itself
        user.sessionId = client.session.uniqueId;   //  convenience

        Events.emit(Events.getSystemEvents().UserLogin, { user } );

        setClientTheme(client, user.properties[UserProps.ThemeId]);

        postLoginPrep(client, err => {
            if(err) {
                return cb(err);
            }

            if(user.authenticated) {
                return recordLogin(client, cb);
            }

            //  recordLogin() must happen after 2FA!
            return cb(null);
        });
    });
}

function postLoginPrep(client, cb) {

    const defaultMsgAreaTag = (confTag) => {
        return getDefaultMessageAreaTagByConfTag(client, confTag) ||
            getDefaultMessageAreaTagByConfTag(client, getDefaultMessageConferenceTag(client)) ||
            '';
    };

    async.series(
        [
            (callback) => {
                //
                //  User may (no longer) have read (view) rights to their current
                //  message, conferences and/or areas. Move them out if so.
                //
                let confTag = client.user.getProperty(UserProps.MessageConfTag);
                const conf  = getMessageConferenceByTag(confTag) || {};
                const area  = getMessageAreaByTag(client.user.getProperty(UserProps.MessageAreaTag), confTag) || {};

                if(!client.acs.hasMessageConfRead(conf)) {
                    confTag = getDefaultMessageConferenceTag(client) || '';
                    client.user.persistProperties({
                        [ UserProps.MessageConfTag ] : confTag,
                        [ UserProps.MessageAreaTag ] : defaultMsgAreaTag(confTag),
                    },
                    err => {
                        return callback(err);
                    });
                } else if (!client.acs.hasMessageAreaRead(area)) {
                    client.user.persistProperty(UserProps.MessageAreaTag, defaultMsgAreaTag(confTag), err => {
                        return callback(err);
                    });
                } else {
                    return callback(null);
                }
            },
            (callback) => {
                //  Likewise for file areas
                const area = getFileAreaByTag(client.user.getProperty(UserProps.FileAreaTag)) || {};
                if(!client.acs.hasFileAreaRead(area)) {
                    const areaTag = getDefaultFileAreaTag(client) || '';
                    client.user.persistProperty(UserProps.FileAreaTag, areaTag, err => {
                        return callback(err);
                    });
                } else {
                    return callback(null);
                }
            }
        ],
        err => {
            return cb(err);
        }
    );
}

function recordLogin(client, cb) {
    assert(client.user.authenticated);  //  don't get in situations where this isn't true

    const user = client.user;
    async.parallel(
        [
            (callback) => {
                StatLog.incrementNonPersistentSystemStat(SysProps.LoginsToday, 1);
                return StatLog.incrementSystemStat(SysProps.LoginCount, 1, callback);
            },
            (callback) => {
                return StatLog.setUserStat(user, UserProps.LastLoginTs, StatLog.now, callback);
            },
            (callback) => {
                return StatLog.incrementUserStat(user, UserProps.LoginCount, 1, callback);
            },
            (callback) => {
                const loginHistoryMax = Config().statLog.systemEvents.loginHistoryMax;
                const historyItem = JSON.stringify({
                    userId      : user.userId,
                    sessionId   : user.sessionId,
                });

                return StatLog.appendSystemLogEntry(
                    SystemLogKeys.UserLoginHistory,
                    historyItem,
                    loginHistoryMax,
                    StatLog.KeepType.Max,
                    callback
                );
            }
        ],
        err => {
            return cb(err);
        }
    );
}

function transformLoginError(err, client, username) {
    client.sessionFailedLoginAttempts = _.get(client, 'sessionFailedLoginAttempts', 0) + 1;
    const disconnect = Config().users.failedLogin.disconnect;
    if(disconnect > 0 && client.sessionFailedLoginAttempts >= disconnect) {
        err = Errors.BadLogin('To many failed login attempts', ErrorReasons.TooMany);
    }

    client.log.info( { username, ip : client.remoteAddress, reason : err.message }, 'Failed login attempt');
    return err;
}<|endoftext|>


<commit_before>"use strict";
/*jshint rhino:true*/
/*eslint-env rhino*/

function getEnv (name) {
    return "" + java.lang.System.getProperty(name);
}

var gpfPath = getEnv("user.dir"),
    pathSeparator = getEnv("file.separator");

load([
    gpfPath,
    "test",
    "host",
    "loader.js"
].join(pathSeparator));

/*global loadGpfAndTests*/

loadGpfAndTests({
    parameters: (function () {
        return this["arguments"]; //eslint-disable-line dot-notation, no-invalid-this
    }()),
    gpfPath: gpfPath,
    pathSeparator: pathSeparator,
    log: function (text) {
        print(text);
    },
    exit: function (code) {
        java.lang.System.exit(code);
    },
    read: readFile
});
<commit_msg>Increase compatibility for Nashorn support (#220)<commit_after> // no "use strict" to be able to set global context
/*jshint strict:false */
/*jshint rhino:true*/
/*eslint strict:0*/
/*eslint-env rhino*/
/*exported global*/

var global = (function () { //eslint-disable-line no-unused-vars
    return this;
}());

function getEnv (name) {
    return String(java.lang.System.getProperty(name));
}

var gpfPath = getEnv("user.dir"),
    pathSeparator = getEnv("file.separator"),
    readApi;

if ("undefined" === typeof readFile) {
    readApi = function (path) {
        return [].join.call(java.nio.file.Files.readAllLines(java.nio.file.Paths.get(path)), "\n");
    };
} else {
    readApi = readFile;
}

load([
    gpfPath,
    "test",
    "host",
    "loader.js"
].join(pathSeparator));

/*global loadGpfAndTests*/

loadGpfAndTests({
    parameters: (function () {
        return this["arguments"]; //eslint-disable-line dot-notation, no-invalid-this
    }()),
    gpfPath: gpfPath,
    pathSeparator: pathSeparator,
    log: function (text) {
        print(text);
    },
    exit: function (code) {
        java.lang.System.exit(code);
    },
    read: readApi
});
<|endoftext|>