<commit_before>import React from 'react';
import Utils from '../lib/Utils';
import Player from './player';
import Header from './header';
import Food from './food';
import SetPlayer from './set-player';
import FoodModel from '../models/FoodModel';
import PlayerModel from '../models/PlayerModel';
import Colors from '../styles/colors';

class Svg extends React.Component {

  constructor(){
    super();

    this.utils = new Utils();

    this.style = {
      paddingTop: 40,
    };

    this.svgstyle = {
      position: 'fixed',
      border: '2px solid black',
      top: 10,
      marginLeft: "200px",
      backgroundColor: "#252933",
      boxShadow: "1px 1px 5px rgba(0,0,0,0.3)",
    };

    this.state = {
      foods: [],
      players: [],
      game: false
    };

    this.modelFood = new FoodModel();
    this.modelFood.subscribe(this.updateFood.bind(this));

    this.modelPlayer = new PlayerModel();
    this.modelPlayer.subscribe(this.updatePlayer.bind(this));
  }

  updateFood(){
    this.setState({
      foods: this.modelFood.resources
    });
  }

  updatePlayer(){
    this.setState({
      players: this.modelPlayer.resources
    });
  }

  setPlayer(name, fill) {
    console.log("setPlayer");

    let player = this.newPlayer(name, fill);

    this.modelPlayer.addResource({
      name: player.name,
      r: player.r,
      cx: player.cx,
      cy: player.cy,
      nx: player.nx,
      ny: player.ny,
      fill: player.fill,
      food_eaten: player.food_eaten,
      time_alive: player.time_alive,
      delay: player.delay,
      ranking: player.ranking,
      stroke: player.stroke,
      stroke_width: player.stroke_width
    });

    this.updatePlayer();
    console.log(player);

    this.setState({
        game: true
    })

    this.startGame();
  }

  newPlayer(name, fill){
    console.log("newPlayer");

    return {
        name: name,
        r: 20,
        cx: 20,
        cy: 20,
        nx: 20,
        ny: 20,
        fill: fill,
        food_eaten: 0,
        time_alive: "00:00:00",
        delay: 5,
        ranking: 0,
        stroke: "#ccc",
        stroke_width: 2
    }
  }

  startGame() {
    console.log("startGame");

    this.createFoods();
    this.playGame();
  }

  playGame(){
    console.log("playGame");

    let lost = false;

    //while(!lost){
      //this.updateTime();
      //this.updateGame();
      //window.addEventListener('mousemove', (event) => {
      //  this.updatePosition(event.clientX, event.clientY);
      //});
    //}
  }

  createFoods(){
    console.log("createFoods");
    let tempFoods = []

    for (let i = 0; i < 100; i++){
      tempFoods.push(this.setFood("red"));
    }
    this.setState({
      foods: tempFoods
    })
  }

  setFood(color){
    let x = Math.floor(Math.random() * 990);
    let y = Math.floor(Math.random() * 640);
    let food = {cx: x, cy: y, r:6, fill:color };

    this.modelFood.addResource({
      r: food.r,
      cx: food.cx,
      cy: food.cy,
      fill: food.fill
    })
    this.updateFood();

    return food;
  }

  updateGame(){

    let ate = this.eatFood(this.state.player.nx, this.state.player.ny);
    ate = ate + parseInt(this.state.player.food_eaten);

    let delay = parseInt(this.state.player.delay);

    this.setState({
      player: {
        r: this.playerGrow(ate),
        cx: this.playerDelay(delay, ate)[0],
        cy: this.playerDelay(delay, ate)[1],
        nx: this.state.player.nx,
        ny: this.state.player.ny,
        fill: this.state.player.fill,
        name: this.state.player.name,
        food_eaten: ate,
        time_alive: this.state.player.time_alive,
        speed: 0,
        delay: this.playerDelay(delay, ate)[2]
      }
    });
  }

  playerGrow(eatFood){
    let size = parseInt(this.state.player.r);
    let newSize = 20 + (eatFood/5);

    if (size > newSize) {
      return size;
    } else {
      return newSize;
    }
  }

  playerDelay(delay, ate){

    delay = 5 + (ate/5);

    let nX = parseInt(this.state.player.nx);
    let nY = parseInt(this.state.player.ny);
    let cX = parseInt(this.state.player.cx);
    let cY = parseInt(this.state.player.cy);

    let arr = [];
    arr.push(cX + ((nX-cX)/delay));
    arr.push(cY + ((nY-cY)/delay));
    arr.push(delay);

    return arr;
  }

  // updateTime(){
  //   this.state.players.map(function(player){
  //     player.time_alive = player.time_alive + 1;
  //   })
  // }

  setFormatTime(time){
    var hours   = Math.floor(time / 3600);
    var minutes = Math.floor((time - (hours * 3600)) / 60);
    var seconds = time - (hours * 3600) - (minutes * 60);

    if (hours   < 10) {hours   = "0"+hours;}
    if (minutes < 10) {minutes = "0"+minutes;}
    if (seconds < 10) {seconds = "0"+seconds;}

    return hours+':'+minutes+':'+seconds;
  }

  eatFood(x, y){
    let ate = 0;
    let tempFoods = [];
    for (let i = 0; i < this.state.foods.length; i++){

      let food = this.state.foods[i];
      let player = this.state.player;

      let startXFood = parseInt(food.cx) - parseInt(food.r);
      let startYFood = parseInt(food.cy) - parseInt(food.r);
      let endXFood = parseInt(food.cx) + parseInt(food.r);
      let endYFood = parseInt(food.cy) + parseInt(food.r);

      let startXPlayer = parseInt(player.cx) - parseInt(player.r);
      let startYPlayer = parseInt(player.cy) - parseInt(player.r);
      let endXPlayer = parseInt(player.cx) + parseInt(player.r);
      let endYPlayer = parseInt(player.cy) + parseInt(player.r);

      if (startXPlayer < startXFood &&
          startYPlayer < startYFood &&
          endXPlayer > endXFood &&
          endYPlayer > endYFood){
        ate = ate + 1;
        this.loadNewFood();

      }else{
        tempFoods.push(food);
      }
    }
    this.setState({
      foods: tempFoods
    });
    return ate;
  }

  updatePosition(x,y){
    let tempPlayer = this.state.player;
    tempPlayer.nx = x;
    tempPlayer.ny = y;
    this.setState({
      player: tempPlayer
    });
  }

  loadNewFood(){
    setTimeout(() => {
      let tempFoods = this.state.foods;
      tempFoods.push(this.newFood("green"));

      this.setState({
        foods: tempFoods
      });

    }, 500);
  }

  renderFood(food, index){
    return (<Food key={index} cx={food.cx} cy={food.cy} r={food.r} fill={food.fill} />);
  }

  renderPlayer(player, index){
    return (
      <Player key={index} cx={player.cx} cy={player.cy} r={player.r} fill={player.fill} />);
  }

  renderSvg(){
    //
    // { this.state.players.map(this.renderPlayer) }
    return (

          <svg id="board"  style={this.svgstyle} width="1000" height="650">
            { this.state.foods.map(this.renderFood) }
          </svg>

    );
  }

  renderSetPlayer(){
    return (
      <SetPlayer onChange={ this.setPlayer.bind(this) } />
    );
  }

  render(){
    if (!this.state.game){
      return this.renderSetPlayer();
    }else{
      return this.renderSvg();
    }
  }
}

export default Svg;
<commit_msg>player o/<commit_after>import React from 'react';
import Utils from '../lib/Utils';
import Player from './player';
import Header from './header';
import Food from './food';
import SetPlayer from './set-player';
import FoodModel from '../models/FoodModel';
import PlayerModel from '../models/PlayerModel';
import Colors from '../styles/colors';

class Svg extends React.Component {

  constructor(){
    super();

    this.utils = new Utils();

    this.style = {
      paddingTop: 40,
    };

    this.svgstyle = {
      position: 'fixed',
      border: '2px solid black',
      top: 10,
      marginLeft: "200px",
      backgroundColor: "#252933",
      boxShadow: "1px 1px 5px rgba(0,0,0,0.3)",
    };

    this.state = {
      foods: [],
      players: [],
      game: false
    };

    this.modelFood = new FoodModel();
    this.modelFood.subscribe(this.updateFood.bind(this));

    this.modelPlayer = new PlayerModel();
    this.modelPlayer.subscribe(this.updatePlayer.bind(this));
  }

  updateFood(){
    this.setState({
      foods: this.modelFood.resources
    });
  }

  updatePlayer(){
    this.setState({
      players: this.modelPlayer.resources
    });
  }

  setPlayer(name, fill) {
    console.log("setPlayer");

    let player = this.newPlayer(name, fill);

    this.modelPlayer.addResource({
      name: player.name,
      r: player.r,
      cx: player.cx,
      cy: player.cy,
      nx: player.nx,
      ny: player.ny,
      fill: player.fill,
      stroke: player.stroke,
      stroke_width: player.stroke_width,
      food_eaten: player.food_eaten,
      time_alive: player.time_alive,
      delay: player.delay,
      ranking: player.ranking
    });
    this.updatePlayer();

    console.log(this.state.players);

    this.setState({
        game: true
    });

    this.startGame();
  }

  newPlayer(name, fill){
    console.log("newPlayer");

    return {
        name: name,
        r: 20,
        cx: 20,
        cy: 20,
        nx: 20,
        ny: 20,
        fill: fill,
        food_eaten: 0,
        time_alive: "00:00:00",
        delay: 5,
        ranking: 0,
        stroke: "#ccc",
        stroke_width: 2
    }
  }

  startGame() {
    console.log("startGame");

    this.createFoods();
    this.playGame();
  }

  playGame(){
    console.log("playGame");

    let lost = false;

    //while(!lost){
      //this.updateTime();
      //this.updateGame();
      //window.addEventListener('mousemove', (event) => {
      //  this.updatePosition(event.clientX, event.clientY);
      //});
    //}
  }

  createFoods(){
    console.log("createFoods");
    let tempFoods = []

    for (let i = 0; i < 100; i++){
      tempFoods.push(this.setFood("red"));
    }
    this.setState({
      foods: tempFoods
    })
  }

  setFood(color){
    let x = Math.floor(Math.random() * 990);
    let y = Math.floor(Math.random() * 640);
    let food = {cx: x, cy: y, r:6, fill:color };

    this.modelFood.addResource({
      r: food.r,
      cx: food.cx,
      cy: food.cy,
      fill: food.fill
    })
    this.updateFood();
    console.log(this.state.foods)

    return food;
  }

  updateGame(){

    let ate = this.eatFood(this.state.player.nx, this.state.player.ny);
    ate = ate + parseInt(this.state.player.food_eaten);

    let delay = parseInt(this.state.player.delay);

    this.setState({
      player: {
        r: this.playerGrow(ate),
        cx: this.playerDelay(delay, ate)[0],
        cy: this.playerDelay(delay, ate)[1],
        nx: this.state.player.nx,
        ny: this.state.player.ny,
        fill: this.state.player.fill,
        name: this.state.player.name,
        food_eaten: ate,
        time_alive: this.state.player.time_alive,
        speed: 0,
        delay: this.playerDelay(delay, ate)[2]
      }
    });
  }

  playerGrow(eatFood){
    let size = parseInt(this.state.player.r);
    let newSize = 20 + (eatFood/5);

    if (size > newSize) {
      return size;
    } else {
      return newSize;
    }
  }

  playerDelay(delay, ate){

    delay = 5 + (ate/5);

    let nX = parseInt(this.state.player.nx);
    let nY = parseInt(this.state.player.ny);
    let cX = parseInt(this.state.player.cx);
    let cY = parseInt(this.state.player.cy);

    let arr = [];
    arr.push(cX + ((nX-cX)/delay));
    arr.push(cY + ((nY-cY)/delay));
    arr.push(delay);

    return arr;
  }

  // updateTime(){
  //   this.state.players.map(function(player){
  //     player.time_alive = player.time_alive + 1;
  //   })
  // }

  setFormatTime(time){
    var hours   = Math.floor(time / 3600);
    var minutes = Math.floor((time - (hours * 3600)) / 60);
    var seconds = time - (hours * 3600) - (minutes * 60);

    if (hours   < 10) {hours   = "0"+hours;}
    if (minutes < 10) {minutes = "0"+minutes;}
    if (seconds < 10) {seconds = "0"+seconds;}

    return hours+':'+minutes+':'+seconds;
  }

  eatFood(x, y){
    let ate = 0;
    let tempFoods = [];
    for (let i = 0; i < this.state.foods.length; i++){

      let food = this.state.foods[i];
      let player = this.state.player;

      let startXFood = parseInt(food.cx) - parseInt(food.r);
      let startYFood = parseInt(food.cy) - parseInt(food.r);
      let endXFood = parseInt(food.cx) + parseInt(food.r);
      let endYFood = parseInt(food.cy) + parseInt(food.r);

      let startXPlayer = parseInt(player.cx) - parseInt(player.r);
      let startYPlayer = parseInt(player.cy) - parseInt(player.r);
      let endXPlayer = parseInt(player.cx) + parseInt(player.r);
      let endYPlayer = parseInt(player.cy) + parseInt(player.r);

      if (startXPlayer < startXFood &&
          startYPlayer < startYFood &&
          endXPlayer > endXFood &&
          endYPlayer > endYFood){
        ate = ate + 1;
        this.loadNewFood();

      }else{
        tempFoods.push(food);
      }
    }
    this.setState({
      foods: tempFoods
    });
    return ate;
  }

  updatePosition(x,y){
    let tempPlayer = this.state.player;
    tempPlayer.nx = x;
    tempPlayer.ny = y;
    this.setState({
      player: tempPlayer
    });
  }

  loadNewFood(){
    setTimeout(() => {
      let tempFoods = this.state.foods;
      tempFoods.push(this.newFood("green"));

      this.setState({
        foods: tempFoods
      });

    }, 500);
  }

  renderPlayer(player, index){
    return (
      <Player key={index} cx={player.cx} cy={player.cy} r={player.r} fill={player.fill} />
    );
  }

  renderFood(food, index){
    return (
      <Food key={index} cx={food.cx} cy={food.cy} r={food.r} fill={food.fill} />
    );
  }

  renderSvg(){
    //
    console.log("PLAYERS: ", this.state.players.data);
    return (

          <svg id="board"  style={this.svgstyle} width="1000" height="650">
            { this.state.players.data.map(this.renderPlayer) }
            { this.state.foods.map(this.renderFood) }
          </svg>

    );
  }

  renderSetPlayer(){
    return (
      <SetPlayer onChange={ this.setPlayer.bind(this) } />
    );
  }

  render(){
    if (!this.state.game){
      return this.renderSetPlayer();
    }else{
      return this.renderSvg();
    }
  }
}

export default Svg;
<|endoftext|>


<commit_before>var rekuire = require('rekuire');
var util = require('util');
var config = require('config');
var _ = require('underscore');
var rest = rekuire('src/util/rest');
var QR = rekuire('src/models/qr');
var request = require('request');
var Canvas = new require('canvas');
var qrcode = require('qrcode');
var fs = require('fs');

module.exports.getAllQRs = function(req, res) {
    QR.find({}).sort({_id: 1}).exec(function(err, qrs) {
        res.send(err ? 404 : qrs);
    });
}

module.exports.newQR = function(req, res) {

    function pad(n, width, z) {
        z = z || '0';
        n = n + '';
        return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
    }

    QR.count({}, function (err, count){
        QR.create({humanId: 'UK' + pad(count, 10)}, function (err, qr) {
            res.send(err ? 404 : qr);
        });
    });
}

module.exports.getQR = function(req, res) {
    QR.findOne({humanId: req.param('id')}, function(err, qr) {
        res.send(qr ? qr : 404);
    });
}

module.exports.getQRImage = function(req, res) {
    var margin = req.param('print') ? 10 : 0;

    QR.findOne({humanId: req.param('id')}, function(err, qr) {
        if (!qr) {
            res.send(404);
            return;
        }
        qrcode.draw(qr.id, {scale: 10, margin: margin}, function(error, canvas) {
            ctx = canvas.getContext('2d');

            if (req.param('print')) {
                ctx.font = 'italic 20pt Calibri';
                ctx.fillStyle = 'black';
                ctx.textAlign = 'center';
                //ctx.rotate(90*Math.PI/180);
                ctx.fillText(qr.humanId, canvas.width / 2, canvas.height - 10);
                //ctx.rotate(-90*Math.PI/180);
            }

            function sendImage() {
                res.type('jpg');
                canvas.jpegStream({bufsize: 4096, quality: 100, progressive: false}).pipe(res);
            }

            var brand = req.param('brand');

            var brands = {
                wds: __dirname + '/../data/wds.gif',
                wds2: __dirname + '/../data/wds.png',
                apple: __dirname + '/../data/apple.png'
            }

            if (brands[brand]) {
                var data = fs.readFileSync(brands[brand]);
                var rect = {
                    center: {
                        x: canvas.width / 2,
                        y: canvas.height / 2
                    },
                    width: (canvas.width - margin * 10) / 3,
                    height: (canvas.height - margin * 10) / 3
                };

                ctx.beginPath();
                ctx.rect(rect.center.x - rect.width / 2, rect.center.y - rect.height / 2, rect.width, rect.height);
                ctx.fillStyle = 'white';
                ctx.fill();
                var img = new Canvas.Image;
                img.src = data;
                ctx.drawImage(img, rect.center.x - rect.width / 2 + 5, rect.center.y - rect.height / 2 + 5, rect.width - 10, rect.height - 10);
            }

            sendImage();
        });
    });
}
<commit_msg>Fixed aspect ratio of the brand<commit_after>var rekuire = require('rekuire');
var util = require('util');
var config = require('config');
var _ = require('underscore');
var rest = rekuire('src/util/rest');
var QR = rekuire('src/models/qr');
var request = require('request');
var Canvas = new require('canvas');
var qrcode = require('qrcode');
var fs = require('fs');

module.exports.getAllQRs = function(req, res) {
    QR.find({}).sort({_id: 1}).exec(function(err, qrs) {
        res.send(err ? 404 : qrs);
    });
}

module.exports.newQR = function(req, res) {

    function pad(n, width, z) {
        z = z || '0';
        n = n + '';
        return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
    }

    QR.count({}, function (err, count){
        QR.create({humanId: 'UK' + pad(count, 10)}, function (err, qr) {
            res.send(err ? 404 : qr);
        });
    });
}

module.exports.getQR = function(req, res) {
    QR.findOne({humanId: req.param('id')}, function(err, qr) {
        res.send(qr ? qr : 404);
    });
}

module.exports.getQRImage = function(req, res) {
    var margin = req.param('print') ? 10 : 0;

    QR.findOne({humanId: req.param('id')}, function(err, qr) {
        if (!qr) {
            res.send(404);
            return;
        }
        qrcode.draw(qr.id, {scale: 10, margin: margin}, function(error, canvas) {
            ctx = canvas.getContext('2d');

            if (req.param('print')) {
                ctx.font = 'italic 20pt Calibri';
                ctx.fillStyle = 'black';
                ctx.textAlign = 'center';
                //ctx.rotate(90*Math.PI/180);
                ctx.fillText(qr.humanId, canvas.width / 2, canvas.height - 10);
                //ctx.rotate(-90*Math.PI/180);
            }

            function sendImage() {
                res.type('jpg');
                canvas.jpegStream({bufsize: 4096, quality: 100, progressive: false}).pipe(res);
            }

            var brand = req.param('brand');

            var brands = {
                wds: __dirname + '/../data/wds.gif',
                wds2: __dirname + '/../data/wds.png',
                apple: __dirname + '/../data/apple.png'
            }

            if (brands[brand]) {
                var data = fs.readFileSync(brands[brand]);
                var rect = {
                    center: {
                        x: canvas.width / 2,
                        y: canvas.height / 2
                    },
                    width: (canvas.width - margin * 10) / 3,
                    height: (canvas.height - margin * 10) / 3
                };

                ctx.beginPath();
                ctx.rect(rect.center.x - rect.width / 2, rect.center.y - rect.height / 2, rect.width, rect.height);
                ctx.fillStyle = 'white';
                ctx.fill();
                var img = new Canvas.Image;
                img.src = data;
                var ratio = img.height / img.width;
                var iwidth = rect.width - 10;
                var iheight = iwidth * ratio;
                var ix = rect.center.x - iwidth / 2;
                var iy = rect.center.y - iheight / 2;
                ctx.drawImage(img, ix, iy, iwidth, iheight);
            }

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


<commit_before>/**
 * @author mrdoob / http://mrdoob.com/
 * @author bhouston / http://exocortex.com/
 */

( function ( THREE ) {

	THREE.Raycaster = function ( origin, direction, near, far ) {

		this.ray = new THREE.Ray( origin, direction );

		// normalized ray.direction required for accurate distance calculations
		if( this.ray.direction.length() > 0 ) {

			this.ray.direction.normalize();

		}

		this.near = near || 0;
		this.far = far || Infinity;

	};

	var sphere = new THREE.Sphere();
	var localRay = new THREE.Ray();
	var facePlane = new THREE.Plane();
	var intersectPoint = new THREE.Vector3();

	var inverseMatrix = new THREE.Matrix4();

	var descSort = function ( a, b ) {

		return a.distance - b.distance;

	};

	var v0 = new THREE.Vector3(), v1 = new THREE.Vector3(), v2 = new THREE.Vector3();

	// http://www.blackpawn.com/texts/pointinpoly/default.html

	var intersectObject = function ( object, raycaster, intersects ) {

		if ( object instanceof THREE.Particle ) {

			var distance = raycaster.ray.distanceToPoint( object.matrixWorld.getPosition() );

			if ( distance > object.scale.x ) {

				return intersects;

			}

			intersects.push( {

				distance: distance,
				point: object.position,
				face: null,
				object: object

			} );

		} else if ( object instanceof THREE.Mesh ) {

			// Checking boundingSphere distance to ray
			sphere.set(
				object.matrixWorld.getPosition(),
				object.geometry.boundingSphere.radius* object.matrixWorld.getMaxScaleOnAxis() );

			if ( ! raycaster.ray.isIntersectionSphere( sphere ) ) {

				return intersects;

			}

			// Checking faces

			var geometry = object.geometry;
			var vertices = geometry.vertices;

			var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
			var objectMaterials = isFaceMaterial === true ? object.material.materials : null;

			var side = object.material.side;

			var a, b, c, d;
			var precision = raycaster.precision;

			object.matrixRotationWorld.extractRotation( object.matrixWorld );

			inverseMatrix.getInverse( object.matrixWorld );

			localRay.copy( raycaster.ray ).transform( inverseMatrix );

			for ( var f = 0, fl = geometry.faces.length; f < fl; f ++ ) {

				var face = geometry.faces[ f ];

				var material = isFaceMaterial === true ? objectMaterials[ face.materialIndex ] : object.material;

				if ( material === undefined ) continue;

				facePlane.setFromNormalAndCoplanarPoint( face.normal, vertices[face.a] );

				var planeDistance = localRay.distanceToPlane( facePlane );

				// bail if raycaster and plane are parallel
				if ( Math.abs( planeDistance ) < precision ) continue;

				// if negative distance, then plane is behind raycaster
				if ( planeDistance < 0 ) continue;

				// check if we hit the wrong side of a single sided face
				side = material.side;
				if( side !== THREE.DoubleSide ) {

					var planeSign = localRay.direction.dot( facePlane.normal );

					if( ! ( side === THREE.FrontSide ? planeSign < 0 : planeSign > 0 ) ) continue;

				}

				// this can be done using the planeDistance from localRay because localRay wasn't normalized, but ray was
				if ( planeDistance < raycaster.near || planeDistance > raycaster.far ) continue;

				intersectPoint = localRay.at( planeDistance, intersectPoint ); // passing in intersectPoint avoids a copy

				if ( face instanceof THREE.Face3 ) {

					a = vertices[ face.a ];
					b = vertices[ face.b ];
					c = vertices[ face.c ];

					if ( ! THREE.Triangle.containsPoint( intersectPoint, a, b, c ) ) continue;

				} else if ( face instanceof THREE.Face4 ) {

					a = vertices[ face.a ];
					b = vertices[ face.b ];
					c = vertices[ face.c ];
					d = vertices[ face.d ];

					if ( ( ! THREE.Triangle.containsPoint( intersectPoint, a, b, d ) ) &&
						 ( ! THREE.Triangle.containsPoint( intersectPoint, b, c, d ) ) ) continue;

				} else {

					// This is added because if we call out of this if/else group when none of the cases
					//    match it will add a point to the intersection list erroneously.
					throw Error( "face type not supported" );

				}

				intersects.push( {

					distance: planeDistance,	// this works because the original ray was normalized, and the transformed localRay wasn't
					point: raycaster.ray.at( planeDistance ),
					face: face,
					faceIndex: f,
					object: object

				} );

			}

		}

	};

	var intersectDescendants = function ( object, raycaster, intersects ) {

		var descendants = object.getDescendants();

		for ( var i = 0, l = descendants.length; i < l; i ++ ) {

			intersectObject( descendants[ i ], raycaster, intersects );

		}
	};

	//

	THREE.Raycaster.prototype.precision = 0.0001;

	THREE.Raycaster.prototype.set = function ( origin, direction ) {

		this.ray.set( origin, direction );

		// normalized ray.direction required for accurate distance calculations
		if( this.ray.direction.length() > 0 ) {

			this.ray.direction.normalize();

		}

	};

	THREE.Raycaster.prototype.intersectObject = function ( object, recursive ) {

		var intersects = [];

		if ( recursive === true ) {

			intersectDescendants( object, this, intersects );

		}

		intersectObject( object, this, intersects );

		intersects.sort( descSort );

		return intersects;

	};

	THREE.Raycaster.prototype.intersectObjects = function ( objects, recursive ) {

		var intersects = [];

		for ( var i = 0, l = objects.length; i < l; i ++ ) {

			intersectObject( objects[ i ], this, intersects );

			if ( recursive === true ) {

				intersectDescendants( objects[ i ], this, intersects );

			}
		}

		intersects.sort( descSort );

		return intersects;

	};

}( THREE ) );
<commit_msg>remove unused variables from Raycaster.<commit_after>/**
 * @author mrdoob / http://mrdoob.com/
 * @author bhouston / http://exocortex.com/
 */

( function ( THREE ) {

	THREE.Raycaster = function ( origin, direction, near, far ) {

		this.ray = new THREE.Ray( origin, direction );

		// normalized ray.direction required for accurate distance calculations
		if( this.ray.direction.length() > 0 ) {

			this.ray.direction.normalize();

		}

		this.near = near || 0;
		this.far = far || Infinity;

	};

	var sphere = new THREE.Sphere();
	var localRay = new THREE.Ray();
	var facePlane = new THREE.Plane();
	var intersectPoint = new THREE.Vector3();

	var inverseMatrix = new THREE.Matrix4();

	var descSort = function ( a, b ) {

		return a.distance - b.distance;

	};

	// http://www.blackpawn.com/texts/pointinpoly/default.html

	var intersectObject = function ( object, raycaster, intersects ) {

		if ( object instanceof THREE.Particle ) {

			var distance = raycaster.ray.distanceToPoint( object.matrixWorld.getPosition() );

			if ( distance > object.scale.x ) {

				return intersects;

			}

			intersects.push( {

				distance: distance,
				point: object.position,
				face: null,
				object: object

			} );

		} else if ( object instanceof THREE.Mesh ) {

			// Checking boundingSphere distance to ray
			sphere.set(
				object.matrixWorld.getPosition(),
				object.geometry.boundingSphere.radius* object.matrixWorld.getMaxScaleOnAxis() );

			if ( ! raycaster.ray.isIntersectionSphere( sphere ) ) {

				return intersects;

			}

			// Checking faces

			var geometry = object.geometry;
			var vertices = geometry.vertices;

			var isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
			var objectMaterials = isFaceMaterial === true ? object.material.materials : null;

			var side = object.material.side;

			var a, b, c, d;
			var precision = raycaster.precision;

			object.matrixRotationWorld.extractRotation( object.matrixWorld );

			inverseMatrix.getInverse( object.matrixWorld );

			localRay.copy( raycaster.ray ).transform( inverseMatrix );

			for ( var f = 0, fl = geometry.faces.length; f < fl; f ++ ) {

				var face = geometry.faces[ f ];

				var material = isFaceMaterial === true ? objectMaterials[ face.materialIndex ] : object.material;

				if ( material === undefined ) continue;

				facePlane.setFromNormalAndCoplanarPoint( face.normal, vertices[face.a] );

				var planeDistance = localRay.distanceToPlane( facePlane );

				// bail if raycaster and plane are parallel
				if ( Math.abs( planeDistance ) < precision ) continue;

				// if negative distance, then plane is behind raycaster
				if ( planeDistance < 0 ) continue;

				// check if we hit the wrong side of a single sided face
				side = material.side;
				if( side !== THREE.DoubleSide ) {

					var planeSign = localRay.direction.dot( facePlane.normal );

					if( ! ( side === THREE.FrontSide ? planeSign < 0 : planeSign > 0 ) ) continue;

				}

				// this can be done using the planeDistance from localRay because localRay wasn't normalized, but ray was
				if ( planeDistance < raycaster.near || planeDistance > raycaster.far ) continue;

				intersectPoint = localRay.at( planeDistance, intersectPoint ); // passing in intersectPoint avoids a copy

				if ( face instanceof THREE.Face3 ) {

					a = vertices[ face.a ];
					b = vertices[ face.b ];
					c = vertices[ face.c ];

					if ( ! THREE.Triangle.containsPoint( intersectPoint, a, b, c ) ) continue;

				} else if ( face instanceof THREE.Face4 ) {

					a = vertices[ face.a ];
					b = vertices[ face.b ];
					c = vertices[ face.c ];
					d = vertices[ face.d ];

					if ( ( ! THREE.Triangle.containsPoint( intersectPoint, a, b, d ) ) &&
						 ( ! THREE.Triangle.containsPoint( intersectPoint, b, c, d ) ) ) continue;

				} else {

					// This is added because if we call out of this if/else group when none of the cases
					//    match it will add a point to the intersection list erroneously.
					throw Error( "face type not supported" );

				}

				intersects.push( {

					distance: planeDistance,	// this works because the original ray was normalized, and the transformed localRay wasn't
					point: raycaster.ray.at( planeDistance ),
					face: face,
					faceIndex: f,
					object: object

				} );

			}

		}

	};

	var intersectDescendants = function ( object, raycaster, intersects ) {

		var descendants = object.getDescendants();

		for ( var i = 0, l = descendants.length; i < l; i ++ ) {

			intersectObject( descendants[ i ], raycaster, intersects );

		}
	};

	//

	THREE.Raycaster.prototype.precision = 0.0001;

	THREE.Raycaster.prototype.set = function ( origin, direction ) {

		this.ray.set( origin, direction );

		// normalized ray.direction required for accurate distance calculations
		if( this.ray.direction.length() > 0 ) {

			this.ray.direction.normalize();

		}

	};

	THREE.Raycaster.prototype.intersectObject = function ( object, recursive ) {

		var intersects = [];

		if ( recursive === true ) {

			intersectDescendants( object, this, intersects );

		}

		intersectObject( object, this, intersects );

		intersects.sort( descSort );

		return intersects;

	};

	THREE.Raycaster.prototype.intersectObjects = function ( objects, recursive ) {

		var intersects = [];

		for ( var i = 0, l = objects.length; i < l; i ++ ) {

			intersectObject( objects[ i ], this, intersects );

			if ( recursive === true ) {

				intersectDescendants( objects[ i ], this, intersects );

			}
		}

		intersects.sort( descSort );

		return intersects;

	};

}( THREE ) );
<|endoftext|>


<commit_before>goog.provide('webfont.DomHelper');

/**
 * Handles common DOM manipulation tasks. The aim of this library is to cover
 * the needs of typical font loading. Not more, not less.
 * @param {Window} mainWindow The main window webfontloader.js is loaded in.
 * @param {Window=} opt_loadWindow The window we'll load the font into. By
 *   default, the main window is used.
 * @constructor
 */
webfont.DomHelper = function(mainWindow, opt_loadWindow) {
  this.mainWindow_ = mainWindow;
  this.loadWindow_ = opt_loadWindow || mainWindow;

  /** @type {Document} */
  this.document_ = this.loadWindow_.document;

  /** @type {boolean|undefined} */
  this.supportForStyle_ = undefined;
};

goog.scope(function () {
  var DomHelper = webfont.DomHelper;

  /**
   * Creates an element.
   * @param {string} elem The element type.
   * @param {Object=} opt_attr A hash of attribute key/value pairs.
   * @param {string=} opt_innerHtml Contents of the element.
   * @return {Element} the new element.
   */
  DomHelper.prototype.createElement = function(elem, opt_attr,
      opt_innerHtml) {
    var domElement = this.document_.createElement(elem);

    if (opt_attr) {
      for (var attr in opt_attr) {
        // protect against native prototype augmentations
        if (opt_attr.hasOwnProperty(attr)) {
          if (attr == "style") {
            this.setStyle(domElement, opt_attr[attr]);
          } else {
            domElement.setAttribute(attr, opt_attr[attr]);
          }
        }
      }
    }
    if (opt_innerHtml) {
      domElement.appendChild(this.document_.createTextNode(opt_innerHtml));
    }
    return domElement;
  };

  /**
   * Inserts an element into the document. This is intended for unambiguous
   * elements such as html, body, head.
   * @param {string} tagName The element name.
   * @param {Element} e The element to append.
   * @return {boolean} True if the element was inserted.
   */
  DomHelper.prototype.insertInto = function(tagName, e) {
    var t = this.document_.getElementsByTagName(tagName)[0];

    if (!t) { // opera allows documents without a head
      t = document.documentElement;
    }

    if (t && t.lastChild) {
      // This is safer than appendChild in IE. appendChild causes random
      // JS errors in IE. Sometimes errors in other JS exectution, sometimes
      // complete 'This page cannot be displayed' errors. For our purposes,
      // it's equivalent because we don't need to insert at any specific
      // location.
      t.insertBefore(e, t.lastChild);
      return true;
    }
    return false;
  };

  /**
   * Calls a function when the body tag exists.
   * @param {function()} callback The function to call.
   */
  DomHelper.prototype.whenBodyExists = function(callback) {
    var that = this;
    var check = function() {
      if (that.document_.body) {
        callback();
      } else {
        setTimeout(check, 0);
      }
    }
    check();
  };

  /**
   * Removes an element from the DOM.
   * @param {Element} node The element to remove.
   * @return {boolean} True if the element was removed.
   */
  DomHelper.prototype.removeElement = function(node) {
    if (node.parentNode) {
      node.parentNode.removeChild(node);
      return true;
    }
    return false;
  };

  /**
   * Creates a link to a javascript document.
   * @param {string} src The URL of the script.
   * @return {Element} a script element.
   */
  DomHelper.prototype.createScriptSrc = function(src) {
    return this.createElement('script', {
      'src': src
    });
  };

  /**
   * Appends a name to an element's class attribute.
   * @param {Element} e The element.
   * @param {string} name The class name to add.
   */
  DomHelper.prototype.appendClassName = function(e, name) {
    var classes = e.className.split(/\s+/);
    for (var i = 0, len = classes.length; i < len; i++) {
      if (classes[i] == name) {
        return;
      }
    }
    classes.push(name);
    e.className = classes.join(' ')
                    .replace(/\s+/g, ' ')
                    .replace(/^\s+|\s+$/, '');
  };

  /**
   * Removes a name to an element's class attribute.
   * @param {Element} e The element.
   * @param {string} name The class name to remove.
   */
  DomHelper.prototype.removeClassName = function(e, name) {
    var classes = e.className.split(/\s+/);
    var remainingClasses = [];
    for (var i = 0, len = classes.length; i < len; i++) {
      if (classes[i] != name) {
        remainingClasses.push(classes[i]);
      }
    }
    e.className = remainingClasses.join(' ')
                    .replace(/\s+/g, ' ')
                    .replace(/^\s+|\s+$/, '');
  };

  /**
   * Returns true if an element has a given class name and false otherwise.
   * @param {Element} e The element.
   * @param {string} name The class name to check for.
   * @return {boolean} Whether or not the element has this class name.
   */
  DomHelper.prototype.hasClassName = function(e, name) {
    var classes = e.className.split(/\s+/);
    for (var i = 0, len = classes.length; i < len; i++) {
      if (classes[i] == name) {
        return true;
      }
    }
    return false;
  };

  /**
   * Sets the style attribute on an element.
   * @param {Element} e The element.
   * @param {string} styleString The style string.
   */
  DomHelper.prototype.setStyle = function(e, styleString) {
    if (this.hasSupportForStyle_()) {
      e.setAttribute("style", styleString);
    } else {
      e.style.cssText = styleString;
    }
  };

  /**
   * Check if getting and setting the style attribute on an element with
   * getAttribute/setAttribute is supported. In old IE, you must use style.cssText
   * instead. Feature detection is only done the first time this is called.
   * @private
   * @return {boolean} Whether or not the feature is supported.
   */
  DomHelper.prototype.hasSupportForStyle_ = function() {
    if (this.supportForStyle_ === undefined) {
      var e = this.document_.createElement('p');
      e.innerHTML = 'w';
      this.supportForStyle_ = /top/.test(e.getElementsByTagName('a')[0].getAttribute('style'));
    }
    return this.supportForStyle_
  };

  /**
   * @return {Window} The main window webfontloader.js is loaded in (for config).
   */
  DomHelper.prototype.getMainWindow = function() {
    return this.mainWindow_;
  };

  /**
   * @return {Window} The window that we're loading the font(s) into.
   */
  DomHelper.prototype.getLoadWindow = function() {
    return this.loadWindow_;
  };

  /**
   * @return {string} The protocol (http: or https:) to request resources in.
   */
  DomHelper.prototype.getProtocol = function() {
    var protocol = this.loadWindow_.location.protocol;
    // For empty iframes, fallback to main window's protocol.
    if (protocol == 'about:') {
      protocol = this.mainWindow_.location.protocol;
    }
    return protocol == 'https:' ? 'https:' : 'http:';
  };

  /**
   * Returns the secure status of the current document.
   * @return {boolean} true if the current document is served securely.
   */
  DomHelper.prototype.isHttps = function() {
    return this.getProtocol() === 'https:';
  };

  /**
   * Returns the hostname of the current document.
   * @return {string} hostname.
   */
  DomHelper.prototype.getHostName = function() {
    return this.getLoadWindow().location.hostname || this.getMainWindow().location.hostname;
  };

  /**
   * Creates a style element.
   * @param {string} css Contents of the style element.
   * @return {Element} a DOM element.
   */
  DomHelper.prototype.createStyle = function(css) {
    var e = this.document_.createElement('style');

    e.setAttribute('type', 'text/css');
    if (e.styleSheet) { // IE
      e.styleSheet.cssText = css;
    } else {
      e.appendChild(document.createTextNode(css));
    }
    return e;
  };

  /**
   * Loads an external stylesheet.
   *
   * @param {string} href the URL of the stylesheet
   * @param {function(Error)=} opt_callback Called when the stylesheet has loaded or failed to
   * load. Note that the callback is *NOT* guaranteed to be called in all browsers. The first
   * argument to the callback is an error object that is falsy when there are no errors and
   * truthy when there are.
   * @return {Element} The link element
   */
  DomHelper.prototype.loadStylesheet = function (href, opt_callback) {
    var head = this.document_.getElementsByTagName('head')[0];

    if (head) {
      var link = this.createElement('link', {
        'rel': 'stylesheet',
        'href': href
      });

      var done = false;

      link.onload = function () {
        if (!done) {
          done = true;

          if (opt_callback) {
            opt_callback(null);
          }
          link.onload = null;
        }
      };

      link.onerror = function () {
        if (!done) {
          done = true;

          if (opt_callback) {
            opt_callback(new Error('Stylesheet failed to load'));
          }
          link.onload = null;
        }
      };
      head.appendChild(link);

      return link;
    }
    return null;
  };

  /**
   * Loads an external script file.
   * @param {string} src URL of the script.
   * @param {function()=} opt_callback callback when the script has loaded.
   */
  DomHelper.prototype.loadScript = function(src, opt_callback) {
    var head = this.document_.getElementsByTagName('head')[0];

    if (head) {
      var script = this.document_.createElement('script');
      script.src = src;
      var done = false;
      script.onload = script.onreadystatechange = function() {
        if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
          done = true;
          if (opt_callback) {
            opt_callback();
          }
          script.onload = script.onreadystatechange = null;
          // Avoid a bizarre issue with unclosed <base> tag in IE6 - http://blog.dotsmart.net/2008/04/
          if (script.parentNode.tagName == 'HEAD') head.removeChild(script);
        }
      };
      head.appendChild(script);
    }
  };
});
<commit_msg>Do not set onload/onerror handler to null after handling the callback.<commit_after>goog.provide('webfont.DomHelper');

/**
 * Handles common DOM manipulation tasks. The aim of this library is to cover
 * the needs of typical font loading. Not more, not less.
 * @param {Window} mainWindow The main window webfontloader.js is loaded in.
 * @param {Window=} opt_loadWindow The window we'll load the font into. By
 *   default, the main window is used.
 * @constructor
 */
webfont.DomHelper = function(mainWindow, opt_loadWindow) {
  this.mainWindow_ = mainWindow;
  this.loadWindow_ = opt_loadWindow || mainWindow;

  /** @type {Document} */
  this.document_ = this.loadWindow_.document;

  /** @type {boolean|undefined} */
  this.supportForStyle_ = undefined;
};

goog.scope(function () {
  var DomHelper = webfont.DomHelper;

  /**
   * Creates an element.
   * @param {string} elem The element type.
   * @param {Object=} opt_attr A hash of attribute key/value pairs.
   * @param {string=} opt_innerHtml Contents of the element.
   * @return {Element} the new element.
   */
  DomHelper.prototype.createElement = function(elem, opt_attr,
      opt_innerHtml) {
    var domElement = this.document_.createElement(elem);

    if (opt_attr) {
      for (var attr in opt_attr) {
        // protect against native prototype augmentations
        if (opt_attr.hasOwnProperty(attr)) {
          if (attr == "style") {
            this.setStyle(domElement, opt_attr[attr]);
          } else {
            domElement.setAttribute(attr, opt_attr[attr]);
          }
        }
      }
    }
    if (opt_innerHtml) {
      domElement.appendChild(this.document_.createTextNode(opt_innerHtml));
    }
    return domElement;
  };

  /**
   * Inserts an element into the document. This is intended for unambiguous
   * elements such as html, body, head.
   * @param {string} tagName The element name.
   * @param {Element} e The element to append.
   * @return {boolean} True if the element was inserted.
   */
  DomHelper.prototype.insertInto = function(tagName, e) {
    var t = this.document_.getElementsByTagName(tagName)[0];

    if (!t) { // opera allows documents without a head
      t = document.documentElement;
    }

    if (t && t.lastChild) {
      // This is safer than appendChild in IE. appendChild causes random
      // JS errors in IE. Sometimes errors in other JS exectution, sometimes
      // complete 'This page cannot be displayed' errors. For our purposes,
      // it's equivalent because we don't need to insert at any specific
      // location.
      t.insertBefore(e, t.lastChild);
      return true;
    }
    return false;
  };

  /**
   * Calls a function when the body tag exists.
   * @param {function()} callback The function to call.
   */
  DomHelper.prototype.whenBodyExists = function(callback) {
    var that = this;
    var check = function() {
      if (that.document_.body) {
        callback();
      } else {
        setTimeout(check, 0);
      }
    }
    check();
  };

  /**
   * Removes an element from the DOM.
   * @param {Element} node The element to remove.
   * @return {boolean} True if the element was removed.
   */
  DomHelper.prototype.removeElement = function(node) {
    if (node.parentNode) {
      node.parentNode.removeChild(node);
      return true;
    }
    return false;
  };

  /**
   * Creates a link to a javascript document.
   * @param {string} src The URL of the script.
   * @return {Element} a script element.
   */
  DomHelper.prototype.createScriptSrc = function(src) {
    return this.createElement('script', {
      'src': src
    });
  };

  /**
   * Appends a name to an element's class attribute.
   * @param {Element} e The element.
   * @param {string} name The class name to add.
   */
  DomHelper.prototype.appendClassName = function(e, name) {
    var classes = e.className.split(/\s+/);
    for (var i = 0, len = classes.length; i < len; i++) {
      if (classes[i] == name) {
        return;
      }
    }
    classes.push(name);
    e.className = classes.join(' ')
                    .replace(/\s+/g, ' ')
                    .replace(/^\s+|\s+$/, '');
  };

  /**
   * Removes a name to an element's class attribute.
   * @param {Element} e The element.
   * @param {string} name The class name to remove.
   */
  DomHelper.prototype.removeClassName = function(e, name) {
    var classes = e.className.split(/\s+/);
    var remainingClasses = [];
    for (var i = 0, len = classes.length; i < len; i++) {
      if (classes[i] != name) {
        remainingClasses.push(classes[i]);
      }
    }
    e.className = remainingClasses.join(' ')
                    .replace(/\s+/g, ' ')
                    .replace(/^\s+|\s+$/, '');
  };

  /**
   * Returns true if an element has a given class name and false otherwise.
   * @param {Element} e The element.
   * @param {string} name The class name to check for.
   * @return {boolean} Whether or not the element has this class name.
   */
  DomHelper.prototype.hasClassName = function(e, name) {
    var classes = e.className.split(/\s+/);
    for (var i = 0, len = classes.length; i < len; i++) {
      if (classes[i] == name) {
        return true;
      }
    }
    return false;
  };

  /**
   * Sets the style attribute on an element.
   * @param {Element} e The element.
   * @param {string} styleString The style string.
   */
  DomHelper.prototype.setStyle = function(e, styleString) {
    if (this.hasSupportForStyle_()) {
      e.setAttribute("style", styleString);
    } else {
      e.style.cssText = styleString;
    }
  };

  /**
   * Check if getting and setting the style attribute on an element with
   * getAttribute/setAttribute is supported. In old IE, you must use style.cssText
   * instead. Feature detection is only done the first time this is called.
   * @private
   * @return {boolean} Whether or not the feature is supported.
   */
  DomHelper.prototype.hasSupportForStyle_ = function() {
    if (this.supportForStyle_ === undefined) {
      var e = this.document_.createElement('p');
      e.innerHTML = 'w';
      this.supportForStyle_ = /top/.test(e.getElementsByTagName('a')[0].getAttribute('style'));
    }
    return this.supportForStyle_
  };

  /**
   * @return {Window} The main window webfontloader.js is loaded in (for config).
   */
  DomHelper.prototype.getMainWindow = function() {
    return this.mainWindow_;
  };

  /**
   * @return {Window} The window that we're loading the font(s) into.
   */
  DomHelper.prototype.getLoadWindow = function() {
    return this.loadWindow_;
  };

  /**
   * @return {string} The protocol (http: or https:) to request resources in.
   */
  DomHelper.prototype.getProtocol = function() {
    var protocol = this.loadWindow_.location.protocol;
    // For empty iframes, fallback to main window's protocol.
    if (protocol == 'about:') {
      protocol = this.mainWindow_.location.protocol;
    }
    return protocol == 'https:' ? 'https:' : 'http:';
  };

  /**
   * Returns the secure status of the current document.
   * @return {boolean} true if the current document is served securely.
   */
  DomHelper.prototype.isHttps = function() {
    return this.getProtocol() === 'https:';
  };

  /**
   * Returns the hostname of the current document.
   * @return {string} hostname.
   */
  DomHelper.prototype.getHostName = function() {
    return this.getLoadWindow().location.hostname || this.getMainWindow().location.hostname;
  };

  /**
   * Creates a style element.
   * @param {string} css Contents of the style element.
   * @return {Element} a DOM element.
   */
  DomHelper.prototype.createStyle = function(css) {
    var e = this.document_.createElement('style');

    e.setAttribute('type', 'text/css');
    if (e.styleSheet) { // IE
      e.styleSheet.cssText = css;
    } else {
      e.appendChild(document.createTextNode(css));
    }
    return e;
  };

  /**
   * Loads an external stylesheet.
   *
   * @param {string} href the URL of the stylesheet
   * @param {function(Error)=} opt_callback Called when the stylesheet has loaded or failed to
   * load. Note that the callback is *NOT* guaranteed to be called in all browsers. The first
   * argument to the callback is an error object that is falsy when there are no errors and
   * truthy when there are.
   * @return {Element} The link element
   */
  DomHelper.prototype.loadStylesheet = function (href, opt_callback) {
    var head = this.document_.getElementsByTagName('head')[0];

    if (head) {
      var link = this.createElement('link', {
        'rel': 'stylesheet',
        'href': href
      });

      var done = false;

      link.onload = function () {
        if (!done) {
          done = true;

          if (opt_callback) {
            opt_callback(null);
          }
        }
      };

      link.onerror = function () {
        if (!done) {
          done = true;

          if (opt_callback) {
            opt_callback(new Error('Stylesheet failed to load'));
          }
        }
      };
      head.appendChild(link);

      return link;
    }
    return null;
  };

  /**
   * Loads an external script file.
   * @param {string} src URL of the script.
   * @param {function()=} opt_callback callback when the script has loaded.
   */
  DomHelper.prototype.loadScript = function(src, opt_callback) {
    var head = this.document_.getElementsByTagName('head')[0];

    if (head) {
      var script = this.document_.createElement('script');
      script.src = src;
      var done = false;
      script.onload = script.onreadystatechange = function() {
        if (!done && (!this.readyState || this.readyState == 'loaded' || this.readyState == 'complete')) {
          done = true;
          if (opt_callback) {
            opt_callback();
          }
          script.onload = script.onreadystatechange = null;
          // Avoid a bizarre issue with unclosed <base> tag in IE6 - http://blog.dotsmart.net/2008/04/
          if (script.parentNode.tagName == 'HEAD') head.removeChild(script);
        }
      };
      head.appendChild(script);
    }
  };
});
<|endoftext|>


<commit_before>import express from "express";
import CameraShot from "../objects/CameraShot";
import CameraTimeline from "../objects/CameraTimeline";
import xml2js from "xml2js";
import fs from "fs";
const router = new express.Router();
const parser = new xml2js.Parser();

// Get timelines from xml
const getTimelines = function (callback) {
    // Dummyfile Todo: replace with dynamic
    fs.readFile(`${__dirname}/../test_project.scp`, (err, data) => {
        parser.parseString(data, (err, result) => {
            // Read timelines from xml
            const cameraTimelinesXML =
                result.scriptingProject["camera-centerarea"][0].cameraTimeline;

            const cameraTimelines = [];
            const flattenedCameraTimelines = [];

            // Insert shots in timeline which is pushed to timelinesarray
            // and push to flattenedArray
            cameraTimelinesXML.forEach(timeline => {
                const cameraTimeline = new CameraTimeline("dummy", "dymmy");
                if (typeof timeline.shotList[0].shot !== "undefined") {
                    timeline.shotList[0].shot.forEach(shot => {
                        const cameraShot = new CameraShot(shot.beginCount[0],
                            shot.endCount[0], shot.name[0], shot.description[0]);
                        cameraTimeline.addCameraShot(cameraShot);
                        flattenedCameraTimelines.push(cameraShot);
                    });
                }
                cameraTimelines.push(cameraTimeline);
            });
            console.log("here though");
            callback([cameraTimelines, flattenedCameraTimelines]);
        });
    });
};

// Get max and mincount of an array of shots
const getMaxAndMinCount = function (flattenedCameraTimelines) {
    // Calculate minimum and maximum counts
    let minCount = 0;
    let maxCount = 0;
    if (flattenedCameraTimelines.length > 0) {
        minCount = Number(flattenedCameraTimelines[0].beginCount);
        maxCount = Number(flattenedCameraTimelines[0].endCount);
        flattenedCameraTimelines.forEach(shot => {
            if (shot.beginCount < minCount) {
                minCount = Number(shot.beginCount);
            }
            if (shot.endCount > maxCount) {
                maxCount = Number(shot.endCount);
            }
        });
    }

    return [minCount, maxCount];
};

/* GET home page. */
router.get("/", (req, res) => {
    // Get the timelines
    getTimelines((timelines) => {
        const cameraTimelines = timelines[0];
        const counts = getMaxAndMinCount(timelines[1]);
        const minCount = counts[0];
        const maxCount = counts[1];

        // Render the timeline.ejs file with the correct variables
        res.render("timeline", {
            cameraTimelines,
            minCount,
            maxCount});
    });
});

module.exports = router;
<commit_msg>solved esint errors<commit_after>import express from "express";
import CameraShot from "../objects/CameraShot";
import CameraTimeline from "../objects/CameraTimeline";
import xml2js from "xml2js";
import fs from "fs";
const router = new express.Router();
const parser = new xml2js.Parser();

// Get timelines from xml
const getTimelines = function getTimelines(callback) {
    // Dummyfile Todo: replace with dynamic
    fs.readFile(`${__dirname}/../test_project.scp`, (err, data) => {
        parser.parseString(data, (err, result) => {
            // Read timelines from xml
            const cameraTimelinesXML =
                result.scriptingProject["camera-centerarea"][0].cameraTimeline;

            const cameraTimelines = [];
            const flattenedCameraTimelines = [];

            // Insert shots in timeline which is pushed to timelinesarray
            // and push to flattenedArray
            cameraTimelinesXML.forEach(timeline => {
                const cameraTimeline = new CameraTimeline("dummy", "dymmy");
                if (typeof timeline.shotList[0].shot !== "undefined") {
                    timeline.shotList[0].shot.forEach(shot => {
                        const cameraShot = new CameraShot(shot.beginCount[0],
                            shot.endCount[0], shot.name[0], shot.description[0]);
                        cameraTimeline.addCameraShot(cameraShot);
                        flattenedCameraTimelines.push(cameraShot);
                    });
                }
                cameraTimelines.push(cameraTimeline);
            });
            callback([cameraTimelines, flattenedCameraTimelines]);
        });
    });
};

// Get max and mincount of an array of shots
const getMaxAndMinCount = function getMaxAndMinCount(flattenedCameraTimelines) {
    // Calculate minimum and maximum counts
    let minCount = 0;
    let maxCount = 0;
    if (flattenedCameraTimelines.length > 0) {
        minCount = Number(flattenedCameraTimelines[0].beginCount);
        maxCount = Number(flattenedCameraTimelines[0].endCount);
        flattenedCameraTimelines.forEach(shot => {
            if (shot.beginCount < minCount) {
                minCount = Number(shot.beginCount);
            }
            if (shot.endCount > maxCount) {
                maxCount = Number(shot.endCount);
            }
        });
    }

    return [minCount, maxCount];
};

/* GET home page. */
router.get("/", (req, res) => {
    // Get the timelines
    getTimelines((timelines) => {
        const cameraTimelines = timelines[0];
        const counts = getMaxAndMinCount(timelines[1]);
        const minCount = counts[0];
        const maxCount = counts[1];

        // Render the timeline.ejs file with the correct variables
        res.render("timeline", {
            cameraTimelines,
            minCount,
            maxCount });
    });
});

module.exports = router;
<|endoftext|>


<commit_before>// Import Libraries
var Q = require('q');
var httpRequest = require('request');
var util = require('util');

// Environment Variables
var STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;

/*******
Stripe payments
*******/

module.exports = function(app){

	 // Charge a card and log the transaction
	 app.post("/pay/stripe",function(request,response){

		request.assert('amount', 'Amount is required').isDecimal();   //Validate amount
		request.assert('item_id', 'A valid item id is required').equals(0);  //Validate item_id
		request.assert(['custom', 'email'], 'No email - we need one!').isEmail();  //Validate email field
		request.assert(['custom', 'newsletter'], 'Issue with the newsletter form field').isAlpha();  //Validate newsletter field

		 var errors = request.validationErrors();
		 if (errors) {
		 	response.send('There have been validation errors: ' + util.inspect(errors), 400);
			return;
		 }

		Q.fcall(function(){

		   // Charge card
		   return callStripe("charges",{
			card: request.body.stripeToken,
			amount: Math.round(request.body.amount*100), // Converting to USD cents.
			currency: "usd"
		   });

		}).then(function(chargeData){

			// It gets returned as a JSON string, ugh.
			chargeData = JSON.parse(chargeData);

			// Log transaction with Custom Vars
			return app.logTransaction({

				 item_id: request.body.item_id,
				 amount: (chargeData.amount/100), // Converting to USD dollars
				 custom: request.body.custom,

				 payment_method: "stripe",
				 payment_data: chargeData

			});

		}).then(function(transaction){
			response.redirect("/paid?id="+transaction._id);
		},function(err){
			console.log(err);
			response.end();
		});

	 });

};

// Helper method: Make a Stripe API call, with promise.
function callStripe(url,params){

	var deferred = Q.defer();

	httpRequest.post({

		url: "https://api.stripe.com/v1/"+url,
		auth: {
		   user: STRIPE_SECRET_KEY,
		   pass: "",
		   sendImmediately: true
		},
		form: params

	}, function(error,response,body){

		if(error){
		   return deferred.reject(new Error());
		}

		deferred.resolve(body);
	});

	return deferred.promise;
}
<commit_msg>removed strip validation to test crashing server<commit_after>// Import Libraries
var Q = require('q');
var httpRequest = require('request');
var util = require('util');

// Environment Variables
var STRIPE_SECRET_KEY = process.env.STRIPE_SECRET_KEY;

/*******
Stripe payments
*******/

module.exports = function(app){

	 // Charge a card and log the transaction
	 app.post("/pay/stripe",function(request,response){

		 var errors = request.validationErrors();
		 if (errors) {
		 	response.send('There have been validation errors: ' + util.inspect(errors), 400);
			return;
		 }

		Q.fcall(function(){

		   // Charge card
		   return callStripe("charges",{
			card: request.body.stripeToken,
			amount: Math.round(request.body.amount*100), // Converting to USD cents.
			currency: "usd"
		   });

		}).then(function(chargeData){

			// It gets returned as a JSON string, ugh.
			chargeData = JSON.parse(chargeData);

			// Log transaction with Custom Vars
			return app.logTransaction({

				 item_id: request.body.item_id,
				 amount: (chargeData.amount/100), // Converting to USD dollars
				 custom: request.body.custom,

				 payment_method: "stripe",
				 payment_data: chargeData

			});

		}).then(function(transaction){
			response.redirect("/paid?id="+transaction._id);
		},function(err){
			console.log(err);
			response.end();
		});

	 });

};

// Helper method: Make a Stripe API call, with promise.
function callStripe(url,params){

	var deferred = Q.defer();

	httpRequest.post({

		url: "https://api.stripe.com/v1/"+url,
		auth: {
		   user: STRIPE_SECRET_KEY,
		   pass: "",
		   sendImmediately: true
		},
		form: params

	}, function(error,response,body){

		if(error){
		   return deferred.reject(new Error());
		}

		deferred.resolve(body);
	});

	return deferred.promise;
}
<|endoftext|>


<commit_before>module.exports = function(_grid) {
    var grid = _grid;

    var api = {
        _decorators: {}
    };

    function setColShowing(col) {
        grid.colModel.get(col).hidden = false;
    }

    function doWhileHidden(col, fn) {
        while (grid.colModel.get(col - 1).hidden) {
            col--;
            fn && fn(col);
        }
        return col;
    }

    function createDecorator(col, right) {
        var headerDecorator = grid.decorators.create(0, col, 1, 1, 'cell', 'virtual');

        headerDecorator.postRender = function(div) {

            if (right) {
                div.style.transform = 'translate(50%, -50%)';
                div.style.webkitTransform = 'translate(50%, -50%)';
                div.style.removeProperty('left');
            } else {
                div.style.transform = 'translate(-50%, -50%)';
                div.style.webkitTransform = 'translate(-50%, -50%)';
                div.style.removeProperty('right');
            }
            div.style.removeProperty('bottom');
            div.style.top = '50%';
            div.setAttribute('class', 'show-hidden-cols');
            div.setAttribute('dts', 'grid_column_unhide_btn');

            grid.eventLoop.bind('click', div, function() {
                doWhileHidden(col, setColShowing);
            });
        };
        return headerDecorator;
    }

    grid.eventLoop.bind('grid-col-change', function(e) {
        if (e.action === 'hide' || e.action === 'add') {
            e.descriptors.forEach(function(descriptor) {
                var col = descriptor.index;
                if (!col && col !== 0) {
                    return;
                }
                if (descriptor.hidden) {
                    var decCol = col + 1;
                    var rightSide = col === grid.colModel.length(true) - 1;
                    if (rightSide) {
                        //if we're last we actually have to backtrack to the last showing column
                        var lastHiddenCol = doWhileHidden(col);
                        decCol = lastHiddenCol - 1;

                    }
                    var decorator = createDecorator(decCol, rightSide);
                    grid.decorators.add(decorator);
                    api._decorators[col] = decorator;
                } else {
                    var decorator = api._decorators[col];
                    grid.decorators.remove(decorator);
                    api._decorators[col] = undefined;
                }
            });
        }
    });

    return api;
};<commit_msg>make col decorators idempotent<commit_after>module.exports = function(_grid) {
    var grid = _grid;

    var api = {
        _decorators: {}
    };

    function setColShowing(col) {
        grid.colModel.get(col).hidden = false;
    }

    function doWhileHidden(col, fn) {
        while (grid.colModel.get(col - 1).hidden) {
            col--;
            fn && fn(col);
        }
        return col;
    }

    function createDecorator(col, right) {
        var headerDecorator = grid.decorators.create(0, col, 1, 1, 'cell', 'virtual');

        headerDecorator.postRender = function(div) {

            if (right) {
                div.style.transform = 'translate(50%, -50%)';
                div.style.webkitTransform = 'translate(50%, -50%)';
                div.style.removeProperty('left');
            } else {
                div.style.transform = 'translate(-50%, -50%)';
                div.style.webkitTransform = 'translate(-50%, -50%)';
                div.style.removeProperty('right');
            }
            div.style.removeProperty('bottom');
            div.style.top = '50%';
            div.setAttribute('class', 'show-hidden-cols');
            div.setAttribute('dts', 'grid_column_unhide_btn');

            grid.eventLoop.bind('click', div, function() {
                doWhileHidden(col, setColShowing);
            });
        };
        return headerDecorator;
    }

    function maybeRemoveDecorator(col) {
        if (api._decorators[col]) {
            var decorator = api._decorators[col];
            grid.decorators.remove(decorator);
            api._decorators[col] = undefined;
        }
    }

    grid.eventLoop.bind('grid-col-change', function(e) {
        if (e.action === 'hide' || e.action === 'add') {
            e.descriptors.forEach(function(descriptor) {
                var col = descriptor.index;
                if (!col && col !== 0) {
                    return;
                }
                if (descriptor.hidden) {
                    var decCol = col + 1;
                    var rightSide = col === grid.colModel.length(true) - 1;
                    if (rightSide) {
                        //if we're last we actually have to backtrack to the last showing column
                        var lastHiddenCol = doWhileHidden(col);
                        decCol = lastHiddenCol - 1;

                    }
                    maybeRemoveDecorator(col);
                    var decorator = createDecorator(decCol, rightSide);
                    grid.decorators.add(decorator);
                    api._decorators[col] = decorator;
                } else {
                    maybeRemoveDecorator(col);
                }
            });
        }
    });

    return api;
};<|endoftext|>


<commit_before>let Octo = require('octonode');
import * as utilityMethods from '../utils/utilityMethods';
import PaginatedResponse from '../data_structures/PaginatedResponse';

let octoClient = Octo.client();

class GithubApi {

  /**
   * Creates new Octonode client instance initialized with the oauth token passed to this method.
   *
   * https://github.com/pksunkara/octonode#build-a-client-from-an-access-token
   *
   * @param {String} token - The oauth token to store in new Octonode client instance.
   * @returns {Promise} A promise which resolves after Octonode client instance is created.
   * @public
   */
  static addTokenToGhApi(token) {
    return new Promise(resolve => {
      octoClient = Octo.client(token);
      // This is required for CORS requests to pass preflight checks using the Octonode library (due to 'request' library used by Octonode)
      octoClient.requestDefaults['withCredentials'] = false;
      resolve();
    });
  }

  /**
   * Removes currently stored GitHub oauth token from Octonode client instance by
   * overwriting current Octonode client instance with a new, empty Octonode client instance.
   *
   * https://github.com/pksunkara/octonode#build-a-client-which-accesses-any-public-information
   *
   * @returns {Promise} A promise which resolves after Octonode client instance is overwritten.
   * @public
   */
  static removeTokenFromGhApi() {
    return new Promise((resolve) => {
      octoClient = Octo.client();
      resolve();
    });
  }

  /**
   * Gets the user object for the currently logged in user.
   *
   * https://developer.github.com/v3/users/#get-the-authenticated-user
   *
   * @returns {Promise} A promise which resolves to a user object, or rejects with a String error message.
   * @public
   */
  static getAuthenticatedUser() {
    return new Promise((resolve, reject) => {
      let octoMe = octoClient.me();
      let cb = cbFactory(resolve, reject);

      octoMe.info(cb);
    });
  }

  /**
   * Gets a list of repositories owned and/or contributed to by the currently logged in user.
   *
   * https://developer.github.com/v3/repos/#list-your-repositories
   *
   * @returns {Promise} A promise which resolves to a list of repository objects, or rejects with a String error message.
   * @public
   */
  static getCurrentUserAllRepos() {
    return new Promise((resolve, reject) => {
      let octoMe = octoClient.me();
      let cb = cbFactory(resolve, reject);

      octoMe.repos(cb);
    });
  }

  /**
   * Gets a list of repositories owned by specified owner login.
   *
   * https://developer.github.com/v3/repos/#list-user-repositories
   *
   * @param {String} ownerLogin - The GitHub owner login name for which to get owned repos.
   * @returns {Promise} A promise which resolves to a list of repository objects, or rejects with a String error message.
   * @public
   */
  static getReposByOwner(ownerLogin) {
    return new Promise((resolve, reject) => {
      let octoUser = octoClient.user(ownerLogin);
      let cb = cbFactory(resolve, reject);

      octoUser.repos(cb);
    });
  }

  /**
   * Gets a list of branches in the specified repo.
   *
   * https://developer.github.com/v3/repos/branches/#list-branches
   *
   * @param {String} ownerLogin - The GitHub owner login name of the owner of the repo.
   * @param {String} repoName - The name of the repo.
   * @returns {Promise} A promise which resolves to a list of branch objects, or rejects with a String error message.
   * @public
   */
  static getBranchesInRepo(ownerLogin, repoName) {
    return new Promise((resolve, reject) => {
      let repoFullName = ownerLogin + "/" + repoName;
      let octoRepo = octoClient.repo(repoFullName);
      let cb = cbFactory(resolve, reject);

      octoRepo.branches(cb);
    });
  }

  /**
   * Gets a list of commits on the specified branch in the specified repo.
   *
   * https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository
   *
   * @param {String} ownerLogin - The GitHub owner login name of the owner of the repo.
   * @param {String} repoName - The name of the repo.
   * @param {String} branchName - The name of the branch.
   * @param {Number} inPageNum - The page number of data to retrieve (required for GitHub pagination support).
   * @returns {Promise} A promise which resolves to a list of commit objects wrapped in a PaginatedResponse object, or rejects with a String error message.
   * @public
   */
  static getCommitsOnBranch(ownerLogin, repoName, branchName, inPageNum) {
    return new Promise((resolve, reject) => {
      let repoFullName = ownerLogin + "/" + repoName;
      let octoRepo = octoClient.repo(repoFullName);
      let cb = cbWithPaginationFactory(resolve, reject, inPageNum);

      let params = {
        sha: branchName,
        page: inPageNum
      };

      octoRepo.commits(params, cb);
    });
  }

  /**
   * Gets a list of statuses for the specified commit reference in reverse chronological order.
   *
   * https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref
   *
   * @param {String} ownerLogin - The GitHub owner login name of the owner of the repo.
   * @param {String} repoName - The name of the repo.
   * @param {String} commitRef - A string specifying the commit reference (can be commit SHA ID, branch name, or tag name).
   * @returns {Promise} A promise which resolves to a list of commit status objects, or rejects with a String error message.
   * @public
   */
  static getStatusesForCommit(ownerLogin, repoName, commitRef) {
    return new Promise((resolve, reject) => {
      let repoFullName = ownerLogin + "/" + repoName;
      let octoRepo = octoClient.repo(repoFullName);
      let cb = cbFactory(resolve, reject);

      octoRepo.statuses(commitRef, cb);
    });
  }

  /**
   * Gets the latest status for each context, as well as a
   * single combined 'state', for the specified commit reference.
   *
   * https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref
   *
   * @param {String} ownerLogin - The GitHub owner login name of the owner of the repo.
   * @param {String} repoName - The name of the repo.
   * @param {String} ref - A string specifying the commit reference (can be commit SHA ID, branch name, or tag name).
   * @returns {Promise} A promise which resolves to a combined status object, or rejects with a String error message.
   * @public
   */
  //static getCombinedStatusForRef(ownerLogin, repoName, ref) {
  static getCombinedStatusForRef() {
    return new Promise((resolve, reject) => {
      reject("Support for the combined status endpoint is not yet available in the Github.js library");

      /*
      let isCommitRefParamValid = utilityMethods.validateCommitReference(ref);

      if (isCommitRefParamValid) {
        ghInstance.repos(ownerLogin, repoName).commits(ref).status.fetch().then(result => {
          resolve(result);
      }).catch(error => {
          console.log(getErrorResponseMsg(error));
          reject("ERROR: GitHub responded with an error.");
      });
      } else {
        reject("ERROR: Invalid ref parameter passed to GithubApi component.");
      }
      */
    });
  }

  /**
   * Creates a new status on the specified commit.
   *
   * https://developer.github.com/v3/repos/statuses/#create-a-status
   *
   * @param {String} ownerLogin - The GitHub owner login name of the owner of the repo.
   * @param {String} repoName - The name of the repo.
   * @param {String} commitSha - The sha of the commit for which the new status should be created.
   * @param {String} state - The state to set for the new status ("pending", "success", "error", or "failure").
   * @param {String} description - The description to set for the new status.
   * @param {String} targetUrl - A URL related to the new status (e.g. link to output from CI server build
   *                              which triggered status).
   * @param {String} context - The name of the context under which the status should be created.
   * @returns {Promise} A promise which resolves to the newly created status object, or rejects with a String
   *                    error message.
   * @public
   */
  static createStatusForCommit(ownerLogin, repoName, commitSha, state, description, targetUrl, context) {
    return new Promise((resolve, reject) => {
      reject("This API method is currently not supported.");
      /*let isCommitRefParamValid = utilityMethods.validateCommitReference(commitSha);

       if (isCommitRefParamValid) {
       let repo = octoClient.getRepo(ownerLogin, repoName);
       let createParams = {};

       if (utilityMethods.validateGitHubStatusState(state)) {
       createParams.state = state;
       } else {
       throw new Error("Invalid GitHub status state string passed to createStatusForCommit method in GithubApi componenet.");
       }

       if (utilityMethods.isValidString(description)) {
       createParams.description = description;
       }

       if (utilityMethods.isValidString(targetUrl)) {
       createParams.target_url = targetUrl;
       }

       if (utilityMethods.isValidString(context)) {
       createParams.context = context;
       }

       repo.updateStatus(commitSha, createParams).then(response => {
       resolve(response.data);
       }).catch(error => {
       console.log(processResponseErrorMsg(error));
       reject("ERROR: GitHub responded with an error.");
       });
       } else {
       reject("ERROR: Invalid ref parameter passed to GithubApi component.");
       }*/
    });
  }
}

/**
 * Processes an HTTP response object and wraps it in a pagination object.
 *
 * @param data
 * @param headers
 * @param currentPageNum
 * @return {PaginatedResponse} The response data wrapped in a pagination object
 * @private
 */
function processPagination(data, headers, currentPageNum){
  const REL_SEARCH_START_STRING = "rel=\"";
  const REL_SEARCH_END_STRING = "\"";
  const REL_SEARCH_STRING_LEN = REL_SEARCH_START_STRING.length;
  const LINK_SEARCH_START_STRING = "<";
  const LINK_SEARCH_END_STRING = ">";
  const LINK_SEARCH_START_STRING_LEN = LINK_SEARCH_START_STRING.length;

  let pageLinkString = headers.link;
  let lastPageNum;

  if(pageLinkString){
    let pageLinkArray = pageLinkString.split(", ");
    let parsedPageArray = [];
    let lastPageNumLink;

    pageLinkArray.forEach(pageLink => {
      let relStartIdx = pageLink.indexOf(REL_SEARCH_START_STRING) + REL_SEARCH_STRING_LEN;
      let relStopIdx = pageLink.indexOf(REL_SEARCH_END_STRING, relStartIdx);

      let linkStartIdx = pageLink.indexOf(LINK_SEARCH_START_STRING) + LINK_SEARCH_START_STRING_LEN;
      let linkStopIdx = pageLink.indexOf(LINK_SEARCH_END_STRING, linkStartIdx);

      let relNameString = pageLink.slice(relStartIdx, relStopIdx);
      let linkString = pageLink.slice(linkStartIdx, linkStopIdx);

      let pageNumValue = utilityMethods.extractParamFromURL("page", linkString);

      let newPageLinkObj = {
        rel: relNameString,
        link: linkString,
        pageNum: pageNumValue
      };

      parsedPageArray.push(newPageLinkObj);
    });

    lastPageNumLink = parsedPageArray.find(parsedPage => parsedPage.rel == "last");

    if(lastPageNumLink){
      lastPageNum = lastPageNumLink.pageNum;
    }else{
      lastPageNum = currentPageNum;
    }

  }else{
    lastPageNum = 1;
  }

  return new PaginatedResponse(parseInt(currentPageNum), parseInt(lastPageNum), data);
}

/**
 * Generates a new callback function instance to use with Octonode library requests
 *
 * @param {Function} resolve - a function to be invoked to resolve the promise using this callback
 * @param {Function} reject - a function to be invoked to reject the promise using this callback
 * @return {Function} a function to be used as the callback when making a request using the Octonode library
 * @private
 */
function cbFactory (resolve, reject) {
  return function(error, data){
    if (error) {
      console.log(processResponseErrorMsg(error));
      reject("ERROR: GitHub responded with an error.");
    } else {
      resolve(data);
    }
  };
}

/**
 * Generates a new callback function instance to use with Octonode library requests when response requires pagination
 *
 * @param {Function} resolve - a function to be invoked to resolve the promise using this callback
 * @param {Function} reject - a function to be invoked to reject the promise using this callback
 * @param {Number} pageNum - the page number of the current page of data being requested
 * @return {Function} a function to be used as the callback when making a request using the Octonode library
 * @private
 */
function cbWithPaginationFactory (resolve, reject, pageNum) {
  return function(error, data, headers){
    if (error) {
      console.log(processResponseErrorMsg(error));
      reject("ERROR: GitHub responded with an error.");
    } else {
      let paginatedResponseObj = processPagination(data, headers, pageNum);
      resolve(paginatedResponseObj);
    }
  };
}

/**
 * Logs and processes error messages returned from Octonode library.
 *
 * @param {Error} error - The error returned from Octonode library.
 * @returns {string} A string giving a general description of the type of error.
 * @private
 */
function processResponseErrorMsg(error) {
  let errMsg = "";

  if(error instanceof Error){
    if(error.constructor.name === "HttpError") {

      console.log("An HttpError occurred in response to GitHub HTTP request.");
      console.log("   HTTP Response Status Code: " + error.statusCode);
      console.log("   HTTP Response Message: " + error.message);

      console.log("ERROR DETAILS:");
      console.log(error);

      errMsg = "An HttpError occured in response to GitHub HTTP request.";
    }else{
      console.log(error);

      errMsg = "An unknown error occured in response to GitHub HTTP request.";
    }
  }else{
    console.log(error);

    errMsg = "An invalid error object was passed to processResponseErrorMsg function.";
  }

  return errMsg;
}

export default GithubApi;
<commit_msg>Refactor createStatusForCommit method to use Octonode<commit_after>let Octo = require('octonode');
import * as utilityMethods from '../utils/utilityMethods';
import PaginatedResponse from '../data_structures/PaginatedResponse';

let octoClient = Octo.client();

class GithubApi {

  /**
   * Creates new Octonode client instance initialized with the oauth token passed to this method.
   *
   * https://github.com/pksunkara/octonode#build-a-client-from-an-access-token
   *
   * @param {String} token - The oauth token to store in new Octonode client instance.
   * @returns {Promise} A promise which resolves after Octonode client instance is created.
   * @public
   */
  static addTokenToGhApi(token) {
    return new Promise(resolve => {
      octoClient = Octo.client(token);
      // This is required for CORS requests to pass preflight checks using the Octonode library (due to 'request' library used by Octonode)
      octoClient.requestDefaults['withCredentials'] = false;
      resolve();
    });
  }

  /**
   * Removes currently stored GitHub oauth token from Octonode client instance by
   * overwriting current Octonode client instance with a new, empty Octonode client instance.
   *
   * https://github.com/pksunkara/octonode#build-a-client-which-accesses-any-public-information
   *
   * @returns {Promise} A promise which resolves after Octonode client instance is overwritten.
   * @public
   */
  static removeTokenFromGhApi() {
    return new Promise((resolve) => {
      octoClient = Octo.client();
      resolve();
    });
  }

  /**
   * Gets the user object for the currently logged in user.
   *
   * https://developer.github.com/v3/users/#get-the-authenticated-user
   *
   * @returns {Promise} A promise which resolves to a user object, or rejects with a String error message.
   * @public
   */
  static getAuthenticatedUser() {
    return new Promise((resolve, reject) => {
      let octoMe = octoClient.me();
      let cb = cbFactory(resolve, reject);

      octoMe.info(cb);
    });
  }

  /**
   * Gets a list of repositories owned and/or contributed to by the currently logged in user.
   *
   * https://developer.github.com/v3/repos/#list-your-repositories
   *
   * @returns {Promise} A promise which resolves to a list of repository objects, or rejects with a String error message.
   * @public
   */
  static getCurrentUserAllRepos() {
    return new Promise((resolve, reject) => {
      let octoMe = octoClient.me();
      let cb = cbFactory(resolve, reject);

      octoMe.repos(cb);
    });
  }

  /**
   * Gets a list of repositories owned by specified owner login.
   *
   * https://developer.github.com/v3/repos/#list-user-repositories
   *
   * @param {String} ownerLogin - The GitHub owner login name for which to get owned repos.
   * @returns {Promise} A promise which resolves to a list of repository objects, or rejects with a String error message.
   * @public
   */
  static getReposByOwner(ownerLogin) {
    return new Promise((resolve, reject) => {
      let octoUser = octoClient.user(ownerLogin);
      let cb = cbFactory(resolve, reject);

      octoUser.repos(cb);
    });
  }

  /**
   * Gets a list of branches in the specified repo.
   *
   * https://developer.github.com/v3/repos/branches/#list-branches
   *
   * @param {String} ownerLogin - The GitHub owner login name of the owner of the repo.
   * @param {String} repoName - The name of the repo.
   * @returns {Promise} A promise which resolves to a list of branch objects, or rejects with a String error message.
   * @public
   */
  static getBranchesInRepo(ownerLogin, repoName) {
    return new Promise((resolve, reject) => {
      let repoFullName = ownerLogin + "/" + repoName;
      let octoRepo = octoClient.repo(repoFullName);
      let cb = cbFactory(resolve, reject);

      octoRepo.branches(cb);
    });
  }

  /**
   * Gets a list of commits on the specified branch in the specified repo.
   *
   * https://developer.github.com/v3/repos/commits/#list-commits-on-a-repository
   *
   * @param {String} ownerLogin - The GitHub owner login name of the owner of the repo.
   * @param {String} repoName - The name of the repo.
   * @param {String} branchName - The name of the branch.
   * @param {Number} inPageNum - The page number of data to retrieve (required for GitHub pagination support).
   * @returns {Promise} A promise which resolves to a list of commit objects wrapped in a PaginatedResponse object, or rejects with a String error message.
   * @public
   */
  static getCommitsOnBranch(ownerLogin, repoName, branchName, inPageNum) {
    return new Promise((resolve, reject) => {
      let repoFullName = ownerLogin + "/" + repoName;
      let octoRepo = octoClient.repo(repoFullName);
      let cb = cbWithPaginationFactory(resolve, reject, inPageNum);

      let params = {
        sha: branchName,
        page: inPageNum
      };

      octoRepo.commits(params, cb);
    });
  }

  /**
   * Gets a list of statuses for the specified commit reference in reverse chronological order.
   *
   * https://developer.github.com/v3/repos/statuses/#list-statuses-for-a-specific-ref
   *
   * @param {String} ownerLogin - The GitHub owner login name of the owner of the repo.
   * @param {String} repoName - The name of the repo.
   * @param {String} commitRef - A string specifying the commit reference (can be commit SHA ID, branch name, or tag name).
   * @returns {Promise} A promise which resolves to a list of commit status objects, or rejects with a String error message.
   * @public
   */
  static getStatusesForCommit(ownerLogin, repoName, commitRef) {
    return new Promise((resolve, reject) => {
      let repoFullName = ownerLogin + "/" + repoName;
      let octoRepo = octoClient.repo(repoFullName);
      let cb = cbFactory(resolve, reject);

      octoRepo.statuses(commitRef, cb);
    });
  }

  /**
   * Gets the latest status for each context, as well as a
   * single combined 'state', for the specified commit reference.
   *
   * https://developer.github.com/v3/repos/statuses/#get-the-combined-status-for-a-specific-ref
   *
   * @param {String} ownerLogin - The GitHub owner login name of the owner of the repo.
   * @param {String} repoName - The name of the repo.
   * @param {String} ref - A string specifying the commit reference (can be commit SHA ID, branch name, or tag name).
   * @returns {Promise} A promise which resolves to a combined status object, or rejects with a String error message.
   * @public
   */
  //static getCombinedStatusForRef(ownerLogin, repoName, ref) {
  static getCombinedStatusForRef() {
    return new Promise((resolve, reject) => {
      reject("Support for the combined status endpoint is not yet available in the Github.js library");

      /*
      let isCommitRefParamValid = utilityMethods.validateCommitReference(ref);

      if (isCommitRefParamValid) {
        ghInstance.repos(ownerLogin, repoName).commits(ref).status.fetch().then(result => {
          resolve(result);
      }).catch(error => {
          console.log(getErrorResponseMsg(error));
          reject("ERROR: GitHub responded with an error.");
      });
      } else {
        reject("ERROR: Invalid ref parameter passed to GithubApi component.");
      }
      */
    });
  }

  /**
   * Creates a new status on the specified commit.
   *
   * https://developer.github.com/v3/repos/statuses/#create-a-status
   *
   * @param {String} ownerLogin - The GitHub owner login name of the owner of the repo.
   * @param {String} repoName - The name of the repo.
   * @param {String} commitSha - The sha of the commit for which the new status should be created.
   * @param {String} state - The state to set for the new status ("pending", "success", "error", or "failure").
   * @param {String} description - The description to set for the new status.
   * @param {String} targetUrl - A URL related to the new status (e.g. link to output from CI server build
   *                              which triggered status).
   * @param {String} context - The name of the context under which the status should be created.
   * @returns {Promise} A promise which resolves to the newly created status object, or rejects with a String
   *                    error message.
   * @public
   */
  static createStatusForCommit(ownerLogin, repoName, commitSha, state, description, targetUrl, context) {
    return new Promise((resolve, reject) => {
      let isCommitRefParamValid = utilityMethods.validateCommitReference(commitSha);

      if(isCommitRefParamValid) {
        let repoFullName = ownerLogin + "/" + repoName;
        let octoRepo = octoClient.repo(repoFullName);
        let cb = cbFactory(resolve, reject);

        let createParams = {};

        if (utilityMethods.validateGitHubStatusState(state)) {
          createParams.state = state;
        } else {
          throw new Error("Invalid GitHub status state string passed to createStatusForCommit method in GithubApi componenet.");
        }

        if (utilityMethods.isValidString(description)) {
          createParams.description = description;
        }

        if (utilityMethods.isValidString(targetUrl)) {
          createParams.target_url = targetUrl;
        }

        if (utilityMethods.isValidString(context)) {
          createParams.context = context;
        }

        octoRepo.status(commitSha, createParams, cb);
      }else{
        reject("ERROR: Invalid ref parameter passed to GithubApi component.");
      }
    });
  }
}

/**
 * Processes an HTTP response object and wraps it in a pagination object.
 *
 * @param data
 * @param headers
 * @param currentPageNum
 * @return {PaginatedResponse} The response data wrapped in a pagination object
 * @private
 */
function processPagination(data, headers, currentPageNum){
  const REL_SEARCH_START_STRING = "rel=\"";
  const REL_SEARCH_END_STRING = "\"";
  const REL_SEARCH_STRING_LEN = REL_SEARCH_START_STRING.length;
  const LINK_SEARCH_START_STRING = "<";
  const LINK_SEARCH_END_STRING = ">";
  const LINK_SEARCH_START_STRING_LEN = LINK_SEARCH_START_STRING.length;

  let pageLinkString = headers.link;
  let lastPageNum;

  if(pageLinkString){
    let pageLinkArray = pageLinkString.split(", ");
    let parsedPageArray = [];
    let lastPageNumLink;

    pageLinkArray.forEach(pageLink => {
      let relStartIdx = pageLink.indexOf(REL_SEARCH_START_STRING) + REL_SEARCH_STRING_LEN;
      let relStopIdx = pageLink.indexOf(REL_SEARCH_END_STRING, relStartIdx);

      let linkStartIdx = pageLink.indexOf(LINK_SEARCH_START_STRING) + LINK_SEARCH_START_STRING_LEN;
      let linkStopIdx = pageLink.indexOf(LINK_SEARCH_END_STRING, linkStartIdx);

      let relNameString = pageLink.slice(relStartIdx, relStopIdx);
      let linkString = pageLink.slice(linkStartIdx, linkStopIdx);

      let pageNumValue = utilityMethods.extractParamFromURL("page", linkString);

      let newPageLinkObj = {
        rel: relNameString,
        link: linkString,
        pageNum: pageNumValue
      };

      parsedPageArray.push(newPageLinkObj);
    });

    lastPageNumLink = parsedPageArray.find(parsedPage => parsedPage.rel == "last");

    if(lastPageNumLink){
      lastPageNum = lastPageNumLink.pageNum;
    }else{
      lastPageNum = currentPageNum;
    }

  }else{
    lastPageNum = 1;
  }

  return new PaginatedResponse(parseInt(currentPageNum), parseInt(lastPageNum), data);
}

/**
 * Generates a new callback function instance to use with Octonode library requests
 *
 * @param {Function} resolve - a function to be invoked to resolve the promise using this callback
 * @param {Function} reject - a function to be invoked to reject the promise using this callback
 * @return {Function} a function to be used as the callback when making a request using the Octonode library
 * @private
 */
function cbFactory (resolve, reject) {
  return function(error, data){
    if (error) {
      console.log(processResponseErrorMsg(error));
      reject("ERROR: GitHub responded with an error.");
    } else {
      resolve(data);
    }
  };
}

/**
 * Generates a new callback function instance to use with Octonode library requests when response requires pagination
 *
 * @param {Function} resolve - a function to be invoked to resolve the promise using this callback
 * @param {Function} reject - a function to be invoked to reject the promise using this callback
 * @param {Number} pageNum - the page number of the current page of data being requested
 * @return {Function} a function to be used as the callback when making a request using the Octonode library
 * @private
 */
function cbWithPaginationFactory (resolve, reject, pageNum) {
  return function(error, data, headers){
    if (error) {
      console.log(processResponseErrorMsg(error));
      reject("ERROR: GitHub responded with an error.");
    } else {
      let paginatedResponseObj = processPagination(data, headers, pageNum);
      resolve(paginatedResponseObj);
    }
  };
}

/**
 * Logs and processes error messages returned from Octonode library.
 *
 * @param {Error} error - The error returned from Octonode library.
 * @returns {string} A string giving a general description of the type of error.
 * @private
 */
function processResponseErrorMsg(error) {
  let errMsg = "";

  if(error instanceof Error){
    if(error.constructor.name === "HttpError") {

      console.log("An HttpError occurred in response to GitHub HTTP request.");
      console.log("   HTTP Response Status Code: " + error.statusCode);
      console.log("   HTTP Response Message: " + error.message);

      console.log("ERROR DETAILS:");
      console.log(error);

      errMsg = "An HttpError occured in response to GitHub HTTP request.";
    }else{
      console.log(error);

      errMsg = "An unknown error occured in response to GitHub HTTP request.";
    }
  }else{
    console.log(error);

    errMsg = "An invalid error object was passed to processResponseErrorMsg function.";
  }

  return errMsg;
}

export default GithubApi;
<|endoftext|>