<commit_before>/*
Copyright 2016 OpenMarket Ltd

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

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

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

import React from 'react';
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';

export default class NetworkDropdown extends React.Component {
    constructor(props) {
        super(props);

        this.dropdownRootElement = null;
        this.ignoreEvent = null;

        this.onInputClick = this.onInputClick.bind(this);
        this.onRootClick = this.onRootClick.bind(this);
        this.onDocumentClick = this.onDocumentClick.bind(this);
        this.onMenuOptionClick = this.onMenuOptionClick.bind(this);
        this.onInputKeyUp = this.onInputKeyUp.bind(this);
        this.collectRoot = this.collectRoot.bind(this);
        this.collectInputTextBox = this.collectInputTextBox.bind(this);

        this.inputTextBox = null;

        const server = MatrixClientPeg.getHomeServerName();
        let defaultNetwork = null;
        if (
            this.props.config.serverConfig &&
            this.props.config.serverConfig[server] &&
            this.props.config.serverConfig[server].networks &&
            '_matrix' in this.props.config.serverConfig[server].networks
        ) {
            defaultNetwork = '_matrix';
        }

        this.state = {
            expanded: false,
            selectedServer: server,
            selectedNetwork: defaultNetwork,
        };
    }

    componentWillMount() {
        // Listen for all clicks on the document so we can close the
        // menu when the user clicks somewhere else
        document.addEventListener('click', this.onDocumentClick, false);

        // fire this now so the defaults can be set up
        this.props.onOptionChange(this.state.selectedServer, this.state.selectedNetwork);
    }

    componentWillUnmount() {
        document.removeEventListener('click', this.onDocumentClick, false);
    }

    componentDidUpdate() {
        if (this.state.expanded && this.inputTextBox) {
            this.inputTextBox.focus();
        }
    }

    onDocumentClick(ev) {
        // Close the dropdown if the user clicks anywhere that isn't
        // within our root element
        if (ev !== this.ignoreEvent) {
            this.setState({
                expanded: false,
            });
        }
    }

    onRootClick(ev) {
        // This captures any clicks that happen within our elements,
        // such that we can then ignore them when they're seen by the
        // click listener on the document handler, ie. not close the
        // dropdown immediately after opening it.
        // NB. We can't just stopPropagation() because then the event
        // doesn't reach the React onClick().
        this.ignoreEvent = ev;
    }

    onInputClick(ev) {
        this.setState({
            expanded: !this.state.expanded,
        });
        ev.preventDefault();
    }

    onMenuOptionClick(server, network, ev) {
        this.setState({
            expanded: false,
            selectedServer: server,
            selectedNetwork: network,
        });
        this.props.onOptionChange(server, network);
    }

    onInputKeyUp(e) {
        if (e.key == 'Enter') {
            this.setState({
                expanded: false,
                selectedServer: e.target.value,
                selectedNetwork: null,
            });
            this.props.onOptionChange(e.target.value, null);
        }
    }

    collectRoot(e) {
        if (this.dropdownRootElement) {
            this.dropdownRootElement.removeEventListener('click', this.onRootClick, false);
        }
        if (e) {
            e.addEventListener('click', this.onRootClick, false);
        }
        this.dropdownRootElement = e;
    }

    collectInputTextBox(e) {
        this.inputTextBox = e;
    }

    _getMenuOptions() {
        const options = [];

        let servers = [];
        if (this.props.config.servers) {
            servers = servers.concat(this.props.config.servers);
        }

        if (servers.indexOf(MatrixClientPeg.getHomeServerName()) == -1) {
            servers.unshift(MatrixClientPeg.getHomeServerName());
        }

        for (const server of servers) {
            options.push(this._makeMenuOption(server, null));
            if (this.props.config.serverConfig && this.props.config.serverConfig[server] && this.props.config.serverConfig[server].networks) {
                for (const network of this.props.config.serverConfig[server].networks) {
                    options.push(this._makeMenuOption(server, network));
                }
            }
        }

        return options;
    }

    _makeMenuOption(server, network, wire_onclick) {
        if (wire_onclick === undefined) wire_onclick = true;
        let icon;
        let name;
        let span_class;

        if (network === null) {
            name = server;
            span_class = 'mx_NetworkDropdown_menu_all';
        } else if (network == '_matrix') {
            name = 'Matrix';
            icon = ;
            span_class = 'mx_NetworkDropdown_menu_network';
        } else {
            name = this.props.config.networkNames[network];
            icon = ;
            span_class = 'mx_NetworkDropdown_menu_network';
        }

        const click_handler = wire_onclick ? this.onMenuOptionClick.bind(this, server, network) : null;

        let key = server;
        if (network !== null) {
            key += '_' + network;
        }

        return

            {icon}
            {name}

;
    }

    render() {
        let current_value;

        let menu;
        if (this.state.expanded) {
            const menu_options = this._getMenuOptions();
            menu =

                {menu_options}

;
            current_value = <input type="text" className="mx_NetworkDropdown_networkoption"
                ref={this.collectInputTextBox} onKeyUp={this.onInputKeyUp}
            />
        } else {
            current_value = this._makeMenuOption(
                this.state.selectedServer, this.state.selectedNetwork, false
            );
        }

        return

                {current_value}

                {menu}

;
    }
}

NetworkDropdown.propTypes = {
    onOptionChange: React.PropTypes.func.isRequired,
    config: React.PropTypes.object,
};

NetworkDropdown.defaultProps = {
    config: {
        networks: [],
    }
};

<commit_msg>Relative img paths please<commit_after>/*
Copyright 2016 OpenMarket Ltd

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

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

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

import React from 'react';
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';

export default class NetworkDropdown extends React.Component {
    constructor(props) {
        super(props);

        this.dropdownRootElement = null;
        this.ignoreEvent = null;

        this.onInputClick = this.onInputClick.bind(this);
        this.onRootClick = this.onRootClick.bind(this);
        this.onDocumentClick = this.onDocumentClick.bind(this);
        this.onMenuOptionClick = this.onMenuOptionClick.bind(this);
        this.onInputKeyUp = this.onInputKeyUp.bind(this);
        this.collectRoot = this.collectRoot.bind(this);
        this.collectInputTextBox = this.collectInputTextBox.bind(this);

        this.inputTextBox = null;

        const server = MatrixClientPeg.getHomeServerName();
        let defaultNetwork = null;
        if (
            this.props.config.serverConfig &&
            this.props.config.serverConfig[server] &&
            this.props.config.serverConfig[server].networks &&
            '_matrix' in this.props.config.serverConfig[server].networks
        ) {
            defaultNetwork = '_matrix';
        }

        this.state = {
            expanded: false,
            selectedServer: server,
            selectedNetwork: defaultNetwork,
        };
    }

    componentWillMount() {
        // Listen for all clicks on the document so we can close the
        // menu when the user clicks somewhere else
        document.addEventListener('click', this.onDocumentClick, false);

        // fire this now so the defaults can be set up
        this.props.onOptionChange(this.state.selectedServer, this.state.selectedNetwork);
    }

    componentWillUnmount() {
        document.removeEventListener('click', this.onDocumentClick, false);
    }

    componentDidUpdate() {
        if (this.state.expanded && this.inputTextBox) {
            this.inputTextBox.focus();
        }
    }

    onDocumentClick(ev) {
        // Close the dropdown if the user clicks anywhere that isn't
        // within our root element
        if (ev !== this.ignoreEvent) {
            this.setState({
                expanded: false,
            });
        }
    }

    onRootClick(ev) {
        // This captures any clicks that happen within our elements,
        // such that we can then ignore them when they're seen by the
        // click listener on the document handler, ie. not close the
        // dropdown immediately after opening it.
        // NB. We can't just stopPropagation() because then the event
        // doesn't reach the React onClick().
        this.ignoreEvent = ev;
    }

    onInputClick(ev) {
        this.setState({
            expanded: !this.state.expanded,
        });
        ev.preventDefault();
    }

    onMenuOptionClick(server, network, ev) {
        this.setState({
            expanded: false,
            selectedServer: server,
            selectedNetwork: network,
        });
        this.props.onOptionChange(server, network);
    }

    onInputKeyUp(e) {
        if (e.key == 'Enter') {
            this.setState({
                expanded: false,
                selectedServer: e.target.value,
                selectedNetwork: null,
            });
            this.props.onOptionChange(e.target.value, null);
        }
    }

    collectRoot(e) {
        if (this.dropdownRootElement) {
            this.dropdownRootElement.removeEventListener('click', this.onRootClick, false);
        }
        if (e) {
            e.addEventListener('click', this.onRootClick, false);
        }
        this.dropdownRootElement = e;
    }

    collectInputTextBox(e) {
        this.inputTextBox = e;
    }

    _getMenuOptions() {
        const options = [];

        let servers = [];
        if (this.props.config.servers) {
            servers = servers.concat(this.props.config.servers);
        }

        if (servers.indexOf(MatrixClientPeg.getHomeServerName()) == -1) {
            servers.unshift(MatrixClientPeg.getHomeServerName());
        }

        for (const server of servers) {
            options.push(this._makeMenuOption(server, null));
            if (this.props.config.serverConfig && this.props.config.serverConfig[server] && this.props.config.serverConfig[server].networks) {
                for (const network of this.props.config.serverConfig[server].networks) {
                    options.push(this._makeMenuOption(server, network));
                }
            }
        }

        return options;
    }

    _makeMenuOption(server, network, wire_onclick) {
        if (wire_onclick === undefined) wire_onclick = true;
        let icon;
        let name;
        let span_class;

        if (network === null) {
            name = server;
            span_class = 'mx_NetworkDropdown_menu_all';
        } else if (network == '_matrix') {
            name = 'Matrix';
            icon = ;
            span_class = 'mx_NetworkDropdown_menu_network';
        } else {
            name = this.props.config.networkNames[network];
            icon = ;
            span_class = 'mx_NetworkDropdown_menu_network';
        }

        const click_handler = wire_onclick ? this.onMenuOptionClick.bind(this, server, network) : null;

        let key = server;
        if (network !== null) {
            key += '_' + network;
        }

        return

            {icon}
            {name}

;
    }

    render() {
        let current_value;

        let menu;
        if (this.state.expanded) {
            const menu_options = this._getMenuOptions();
            menu =

                {menu_options}

;
            current_value = <input type="text" className="mx_NetworkDropdown_networkoption"
                ref={this.collectInputTextBox} onKeyUp={this.onInputKeyUp}
            />
        } else {
            current_value = this._makeMenuOption(
                this.state.selectedServer, this.state.selectedNetwork, false
            );
        }

        return

                {current_value}

                {menu}

;
    }
}

NetworkDropdown.propTypes = {
    onOptionChange: React.PropTypes.func.isRequired,
    config: React.PropTypes.object,
};

NetworkDropdown.defaultProps = {
    config: {
        networks: [],
    }
};

<|endoftext|>


<commit_before>'use strict';

var angular = require('angular');

module.exports = ['$q', 'defaultContacts', 'Contact', seed];

function seed($q, defaultContacts, Contact) {
  function maybeFetchDefaults(contacts) {
    if (contacts.length === 0) {
      contacts = defaultContacts.get();
    }
    console.log('query', contacts);
    return contacts;
  }

  function saveAll(contacts) {
    var deferredSaves = [],
    promise;

    angular.forEach(contacts, function(contact) {
      promise = contact.$save().then(function () {
        return contact;
      });
      deferredSaves.push(promise);
    });

  // wrap all pending saves in a promise
  return $q.all(deferredSaves);
}
  return {
    seed: function () {
      return Contact.query().
        then(maybeFetchDefaults).
        then(saveAll);
    }
  };
}
<commit_msg>remove stray debugging line<commit_after>'use strict';

var angular = require('angular');

module.exports = ['$q', 'defaultContacts', 'Contact', seed];

function seed($q, defaultContacts, Contact) {
  function maybeFetchDefaults(contacts) {
    if (contacts.length === 0) {
      contacts = defaultContacts.get();
    }
    return contacts;
  }

  function saveAll(contacts) {
    var deferredSaves = [],
    promise;

    angular.forEach(contacts, function(contact) {
      promise = contact.$save().then(function () {
        return contact;
      });
      deferredSaves.push(promise);
    });

  // wrap all pending saves in a promise
  return $q.all(deferredSaves);
}
  return {
    seed: function () {
      return Contact.query().
        then(maybeFetchDefaults).
        then(saveAll);
    }
  };
}
<|endoftext|>


<commit_before>/*
    Nodes – Arko's Experiment with HTML5 canvas element
    Author: Loïc Cattani (Arko) <loic.cattani@gmail.com>
    Date: December 2010
*/

var canvas;
var context;
var mouse = { x: 0, y: 0, down: false };
var framerate = 60;
var intervalId; // Will hold the loop reference

function initialize() {

  // Get the canvas element
  canvas = document.getElementById('world');

  if (canvas && canvas.getContext) {

    // Get 2D context
    context = canvas.getContext('2d');

    // Register Event Listeners
    canvas.addEventListener('mousedown', mouseDown, false);
    document.addEventListener('mouseup', mouseUp, false);
    canvas.addEventListener('mousemove', mouseMove, false);

    // Initiate Nodes World
    NodesWorld.initialize();

    // Initiate the loop
    start();
  }
}

// Event handler for mouseDown
function mouseDown() {
  mouse.down = true;
  mouseMove();
  event.preventDefault();
}

// Event handler for mouseUp
function mouseUp() {
  mouse.down = false;
  mouseMove();
  pause();
}

// Event handler for mouseMove
function mouseMove() {
  mouse.x = event.clientX - (window.innerWidth - canvas.width) / 2;
  mouse.y = event.clientY - (window.innerHeight - canvas.height) / 2;
}

// Initiate the loop
function start() {
  intervalId = setInterval(loop, 1000/framerate);
}

// Clear the loop
function pause() {
  clearInterval(intervalId);
}

// The loop
function loop() {
  NodesWorld.update();
  NodesWorld.draw();
}

var NodesWorld = new function () {
  // Physics
  this.boundaries = { x: 0, y: 0, width: 940, height: 660 };
  this.drag = 0.002; // Good val: 0.002
  this.gravity = { force: 0.2, direction: Math.PI/2 }; // Good force: 0.2 Direction: Math.PI/2 rad => 90° from +x axis CW

  // Content
  this.node_count = 10;
  this.nodes = new Array();

  this.initialize = function() {
    // Transform gravity to a force vector
    this.gravity = new Vector(this.gravity.force, this.gravity.direction);

    // Fill world with randomly positionned nodes
    for (var i = this.node_count - 1; i >= 0; i--){
      node = new Point(Math.random() * this.boundaries.width, Math.random() * this.boundaries.height);
      this.nodes.push(node);
    }
  }

  // Update world's objects
  this.update = function () {
    // Update nodes
    for( var i = 0, len = this.nodes.length; i < len; i++ ) {
      node = this.nodes[i];
      node.update(this.drag, this.gravity);
    }
  }

  // Draw world
  this.draw = function () {

    // Clear world
    context.fillStyle = "rgba(0,0,0,1)";
    context.fillRect(this.boundaries.x, this.boundaries.y, this.boundaries.width, this.boundaries.height);

    // Draw nodes
    for( var i = 0, len = this.nodes.length; i < len; i++ ) {
      node = this.nodes[i];
      context.beginPath();
      context.arc( node.x, node.y, node.radius, 0, Math.PI*2, true );
      context.fillStyle = node.fillcolor;
      context.strokeStyle = node.strokecolor;
      context.lineWidth = 2;
      context.fill();
      context.stroke();
    }
  }
}

/* Defines a point in a 2D space */
function Point (x, y) {
  this.x = x || 0;
  this.y = y || 0;
  this.velocity = new Vector();
  this.mass = 1; // Can't be 0!
  this.bounce_damp = 0.8;
  this.radius = 8;
  this.fillcolor = 'rgba(0,160,255,0.3)';
  this.strokecolor = 'rgba(0,160,255,1)';
}

/* Update a point's position, optionally applying a drag and a force */
Point.prototype.update = function (d, f) {
  this.drag(d);
  this.applyForce(f);
  this.x += this.velocity.x;
  this.y += this.velocity.y;
  this.checkCollisions();
}

/* Apply the given drag as a coefficient */
Point.prototype.drag = function (d) {
  d = d || 0;
  this.velocity.setMagnitude(this.velocity.magnitude * ( 1 - d ));
}

/* Apply the given force as a vector */
Point.prototype.applyForce = function (f) {
  f = f || new Vector();
  this.velocity.setX( this.velocity.x + f.x / this.mass );
  this.velocity.setY( this.velocity.y + f.y / this.mass );
}

/* Returns the speed in pixels per time interval */
Point.prototype.speed = function () {
  return this.velocity.magnitude;
}

/* Check World's Boundaries Collisions */
Point.prototype.checkCollisions = function () {
  bx = NodesWorld.boundaries.x + this.radius;
  bw = NodesWorld.boundaries.width - this.radius;
  by = NodesWorld.boundaries.y + this.radius;
  bh = NodesWorld.boundaries.height - this.radius;

  // Check if the point's position is outside the x-axis boundaries
  if (this.x < bx || this.x > bw) {
     // Reverse and damp x velocity
    this.velocity.setX(this.velocity.x * -this.bounce_damp);
    if (this.x < bx)
      this.x += 2 * (bx - this.x)
    if (this.x > bw)
      this.x += 2 * (bw - this.x)
  }

  if (this.y < by || this.y > bh) {
     // Reverse and damp y velocity
    this.velocity.setY(this.velocity.y * -this.bounce_damp);
    if (this.y < by)
      this.y += 2 * (by - this.y)
    if (this.y > bh)
      this.y += 2 * (bh - this.y)
  }
}

/* Defines a vector in a 2D space */
function Vector (m, a) {
  this.magnitude = m || 0;
  this.angle = a || 0;
  this.x = 0;
  this.y = 0;
  this.updateXY();
}

Vector.prototype.setX = function (x) {
  this.x = x || 0;
  this.updateMA();
}

Vector.prototype.setY = function (y) {
  this.y = y || 0;
  this.updateMA();
}

Vector.prototype.setMagnitude = function (m) {
  this.magnitude = m || 0;
  this.updateXY();
}

Vector.prototype.setAngle = function (a) {
  this.angle = a || 0;
  this.updateXY();
}

Vector.prototype.updateMA = function () {
  x = this.x;
  y = this.y;
  this.magnitude = Math.sqrt(x*x + y*y);
  this.angle = Math.atan2(y,x);
}

Vector.prototype.updateXY = function () {
  this.x = this.magnitude * Math.cos(this.angle);
  this.y = this.magnitude * Math.sin(this.angle);
}

initialize();
<commit_msg>Fixed bounce repositionning calculation...<commit_after>/*
    Nodes – Arko's Experiment with HTML5 canvas element
    Author: Loïc Cattani (Arko) <loic.cattani@gmail.com>
    Date: December 2010
*/

var canvas;
var context;
var mouse = { x: 0, y: 0, down: false };
var framerate = 60;
var intervalId; // Will hold the loop reference

function initialize() {

  // Get the canvas element
  canvas = document.getElementById('world');

  if (canvas && canvas.getContext) {

    // Get 2D context
    context = canvas.getContext('2d');

    // Register Event Listeners
    canvas.addEventListener('mousedown', mouseDown, false);
    document.addEventListener('mouseup', mouseUp, false);
    canvas.addEventListener('mousemove', mouseMove, false);

    // Initiate Nodes World
    NodesWorld.initialize();

    // Initiate the loop
    start();
  }
}

// Event handler for mouseDown
function mouseDown() {
  mouse.down = true;
  mouseMove();
  event.preventDefault();
}

// Event handler for mouseUp
function mouseUp() {
  mouse.down = false;
  mouseMove();
  pause();
}

// Event handler for mouseMove
function mouseMove() {
  mouse.x = event.clientX - (window.innerWidth - canvas.width) / 2;
  mouse.y = event.clientY - (window.innerHeight - canvas.height) / 2;
}

// Initiate the loop
function start() {
  intervalId = setInterval(loop, 1000/framerate);
}

// Clear the loop
function pause() {
  clearInterval(intervalId);
}

// The loop
function loop() {
  NodesWorld.update();
  NodesWorld.draw();
}

var NodesWorld = new function () {
  // Physics
  this.boundaries = { x: 0, y: 0, width: 940, height: 660 };
  this.drag = 0.002; // Good val: 0.002
  this.gravity = { force: 0.2, direction: Math.PI/2 }; // Good force: 0.2 Direction: Math.PI/2 rad => 90° from +x axis CW

  // Content
  this.node_count = 10;
  this.nodes = new Array();

  this.initialize = function() {
    // Transform gravity to a force vector
    this.gravity = new Vector(this.gravity.force, this.gravity.direction);

    // Fill world with randomly positionned nodes
    for (var i = this.node_count - 1; i >= 0; i--){
      node = new Point(Math.random() * this.boundaries.width, Math.random() * this.boundaries.height);
      this.nodes.push(node);
    }
  }

  // Update world's objects
  this.update = function () {
    // Update nodes
    for( var i = 0, len = this.nodes.length; i < len; i++ ) {
      node = this.nodes[i];
      node.update(this.drag, this.gravity);
    }
  }

  // Draw world
  this.draw = function () {

    // Clear world
    context.fillStyle = "rgba(0,0,0,1)";
    context.fillRect(this.boundaries.x, this.boundaries.y, this.boundaries.width, this.boundaries.height);

    // Draw nodes
    for( var i = 0, len = this.nodes.length; i < len; i++ ) {
      node = this.nodes[i];
      context.beginPath();
      context.arc( node.x, node.y, node.radius, 0, Math.PI*2, true );
      context.fillStyle = node.fillcolor;
      context.strokeStyle = node.strokecolor;
      context.lineWidth = 2;
      context.fill();
      context.stroke();
    }
  }
}

/* Defines a point in a 2D space */
function Point (x, y) {
  this.x = x || 0;
  this.y = y || 0;
  this.velocity = new Vector();
  this.mass = 1; // Can't be 0!
  this.bounce_damp = 0.8;
  this.radius = 8;
  this.fillcolor = 'rgba(0,160,255,0.3)';
  this.strokecolor = 'rgba(0,160,255,1)';
}

/* Update a point's position, optionally applying a drag and a force */
Point.prototype.update = function (d, f) {
  this.drag(d);
  this.applyForce(f);
  this.x += this.velocity.x;
  this.y += this.velocity.y;
  this.checkCollisions();
}

/* Apply the given drag as a coefficient */
Point.prototype.drag = function (d) {
  d = d || 0;
  this.velocity.setMagnitude(this.velocity.magnitude * ( 1 - d ));
}

/* Apply the given force as a vector */
Point.prototype.applyForce = function (f) {
  f = f || new Vector();
  this.velocity.setX( this.velocity.x + f.x / this.mass );
  this.velocity.setY( this.velocity.y + f.y / this.mass );
}

/* Returns the speed in pixels per time interval */
Point.prototype.speed = function () {
  return this.velocity.magnitude;
}

/* Check World's Boundaries Collisions */
Point.prototype.checkCollisions = function () {
  bx = NodesWorld.boundaries.x + this.radius;
  bw = NodesWorld.boundaries.width - this.radius;
  by = NodesWorld.boundaries.y + this.radius;
  bh = NodesWorld.boundaries.height - this.radius;

  // Check if the point's position is outside the x-axis boundaries
  if (this.x < bx || this.x > bw) {
     // Reverse and damp x velocity
    this.velocity.setX(this.velocity.x * -this.bounce_damp);
    // Reposition the point in the x axis minus the damp effect
    if (this.x < bx)
      this.x += (1 + this.bounce_damp) * (bx - this.x)
    if (this.x > bw)
      this.x += (1 + this.bounce_damp) * (bw - this.x)
  }

  if (this.y < by || this.y > bh) {
     // Reverse and damp y velocity
    this.velocity.setY(this.velocity.y * -this.bounce_damp);
    // Reposition the point in the y axis minus the damp effect
    if (this.y < by)
      this.y += (1 + this.bounce_damp) * (by - this.y)
    if (this.y > bh)
      this.y += (1 + this.bounce_damp) * (bh - this.y)
  }
}

/* Defines a vector in a 2D space */
function Vector (m, a) {
  this.magnitude = m || 0;
  this.angle = a || 0;
  this.x = 0;
  this.y = 0;
  this.updateXY();
}

Vector.prototype.setX = function (x) {
  this.x = x || 0;
  this.updateMA();
}

Vector.prototype.setY = function (y) {
  this.y = y || 0;
  this.updateMA();
}

Vector.prototype.setMagnitude = function (m) {
  this.magnitude = m || 0;
  this.updateXY();
}

Vector.prototype.setAngle = function (a) {
  this.angle = a || 0;
  this.updateXY();
}

Vector.prototype.updateMA = function () {
  x = this.x;
  y = this.y;
  this.magnitude = Math.sqrt(x*x + y*y);
  this.angle = Math.atan2(y,x);
}

Vector.prototype.updateXY = function () {
  this.x = this.magnitude * Math.cos(this.angle);
  this.y = this.magnitude * Math.sin(this.angle);
}

initialize();
<|endoftext|>


<commit_before>module.exports = function (grunt) {
  grunt.initConfig({

    watch: {
      html: {
        files: ['**/*.html'],
         options: {
          interrupt: true,
          livereload: true,
        }
      },
      css: {
        files: ['src/**/*.scss'],
        tasks: ['default'],
        options: {
          interrupt: true,
          livereload: true,
        }
      }
    },

    sass: {
      options: {
        style: 'expanded',
        sourcemap: 'none',
        noCache: true
      },
      single_file: {
        files: {
          'dist/css/br-select-box.css': 'src/br-select-box.scss'
        }
      }
    },

    cssmin: {
      my_target: {
        files: [{
          expand: true,
          cwd: 'dist/css/',
          src: ['*.css', '!*.min.css'],
          dest: 'dist/css/',
          ext: '.min.css'
        }]
      }
    },

    postcss: {
      options: {
        safe: true,
        processors: [
          require('autoprefixer-core')({browsers: 'last 2 version'})
        ]
      },
      dist: {
        expand: true,
        cascade: true,
        remove: true,
        cwd: 'dist/css/',
        src: ['*.css', '!*.min.css'],
        dest: 'dist/css/'
      }
    },

    uglify: {
      my_target: {
        files: [{
          expand: true,
          flatten: true,
          mangle: false,
          cwd: 'dist/js/',
          src: [
          '*.js',
          '!*.min.js'
          ],
          dest: 'dist/js/',
          ext: '.min.js'
        }]
      }
    }

  });

grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-postcss');

grunt.registerTask( 'default', [ 'sass', 'postcss' ] );
grunt.registerTask( 'css', [ 'sass', 'postcss', 'cssmin' ] );
grunt.registerTask( 'js', [ 'uglify'] );

};<commit_msg>Added css min to default<commit_after>module.exports = function (grunt) {
  grunt.initConfig({

    watch: {
      html: {
        files: ['**/*.html'],
         options: {
          interrupt: true,
          livereload: true,
        }
      },
      css: {
        files: ['src/**/*.scss'],
        tasks: ['default'],
        options: {
          interrupt: true,
          livereload: true,
        }
      }
    },

    sass: {
      options: {
        style: 'expanded',
        sourcemap: 'none',
        noCache: true
      },
      single_file: {
        files: {
          'dist/css/br-select-box.css': 'src/br-select-box.scss'
        }
      }
    },

    cssmin: {
      my_target: {
        files: [{
          expand: true,
          cwd: 'dist/css/',
          src: ['*.css', '!*.min.css'],
          dest: 'dist/css/',
          ext: '.min.css'
        }]
      }
    },

    postcss: {
      options: {
        safe: true,
        processors: [
          require('autoprefixer-core')({browsers: 'last 2 version'})
        ]
      },
      dist: {
        expand: true,
        cascade: true,
        remove: true,
        cwd: 'dist/css/',
        src: ['*.css', '!*.min.css'],
        dest: 'dist/css/'
      }
    },

    uglify: {
      my_target: {
        files: [{
          expand: true,
          flatten: true,
          mangle: false,
          cwd: 'dist/js/',
          src: [
          '*.js',
          '!*.min.js'
          ],
          dest: 'dist/js/',
          ext: '.min.js'
        }]
      }
    }

  });

grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-sass');
grunt.loadNpmTasks('grunt-postcss');

grunt.registerTask( 'default', [ 'sass', 'postcss', 'cssmin' ] );
grunt.registerTask( 'css', [ 'sass', 'postcss', 'cssmin' ] );
grunt.registerTask( 'js', [ 'uglify'] );

};<|endoftext|>


<commit_before>import React, { PropTypes } from 'react'
import { Link } from 'react-router'
import { ElloMark, ElloRainbowMark, ElloDonutMark, ElloNinjaSuit } from '../svg/ElloIcons'

const getLogoMark = (mark) => {
  console.log(mark)
  switch (mark) {
    case 'rainbow':
      return <ElloRainbowMark />
    case 'donut':
      return <ElloDonutMark />
    case 'none':
      return null
    case 'normal':
    default:
      return <ElloMark />
  }
}

const getLogoModifier = (mods) => {
  switch (mods) {
    case 'isNinja':
      return <ElloNinjaSuit />
    default:
      return null
  }
}

export const NavbarMark = ({ currentStream, isLoggedIn, onClick }) => {
  const list = ENV.LOGO_MARK.split('.')
  const mark = list[0]
  const mods = list.slice(1).join(' ')
  return (
    <Link
      className="NavbarMark"
      draggable
      onClick={ onClick }
      to={ isLoggedIn ? currentStream : '/' }
    >
      { getLogoModifier(mods) }
      { getLogoMark(mark) }
    </Link>
  )
}

NavbarMark.propTypes = {
  currentStream: PropTypes.string.isRequired,
  isLoggedIn: PropTypes.bool.isRequired,
  onClick: PropTypes.func.isRequired,
}

<commit_msg>Remove a console log<commit_after>import React, { PropTypes } from 'react'
import { Link } from 'react-router'
import { ElloMark, ElloRainbowMark, ElloDonutMark, ElloNinjaSuit } from '../svg/ElloIcons'

const getLogoMark = (mark) => {
  switch (mark) {
    case 'rainbow':
      return <ElloRainbowMark />
    case 'donut':
      return <ElloDonutMark />
    case 'none':
      return null
    case 'normal':
    default:
      return <ElloMark />
  }
}

const getLogoModifier = (mods) => {
  switch (mods) {
    case 'isNinja':
      return <ElloNinjaSuit />
    default:
      return null
  }
}

export const NavbarMark = ({ currentStream, isLoggedIn, onClick }) => {
  const list = ENV.LOGO_MARK.split('.')
  const mark = list[0]
  const mods = list.slice(1).join(' ')
  return (
    <Link
      className="NavbarMark"
      draggable
      onClick={ onClick }
      to={ isLoggedIn ? currentStream : '/' }
    >
      { getLogoModifier(mods) }
      { getLogoMark(mark) }
    </Link>
  )
}

NavbarMark.propTypes = {
  currentStream: PropTypes.string.isRequired,
  isLoggedIn: PropTypes.bool.isRequired,
  onClick: PropTypes.func.isRequired,
}

<|endoftext|>


<commit_before>// var eyes = require('eyes');
var path = require('path');
var util = require('./lib/grunt/utils.js');

/*global module:false*/
module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    // Metadata.
    pkg: grunt.file.readJSON('package.json'),
    version: util.getVersion(),
    stable_version: util.getStableVersion(),
    dist: 'dist',
    site: process.env.TRAVIS ? 'ui-grid.info' : '127.0.0.1:<%= connect.docs.options.port %>',
    banner: '/*! <%= pkg.title || pkg.name %> - v<%= version %> - ' +
      '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
      '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
      '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
      ' Licensed <%= pkg.license %> */\n',

    shell: {
      options: {
        stdout: true
      },
      selenium: {
        command: './selenium/start',
        options: {
          stdout: false,
          async: true
        }
      },
      'protractor-install': {
        command: 'node ./node_modules/protractor/bin/webdriver-manager update'
      },
      'protractor-start': {
        command: 'node ./node_modules/protractor/bin/webdriver-manager start',
        options: {
          stdout: true,
          async: true
        }
      },
      'bower-install': {
        command: 'bower install'
      }
    },

    // Clean the temp directory
    clean: ['.tmp', '<%= dist %>', 'docs'],

    // Templates
    ngtemplates: {
      'ui-grid': {
        cwd: 'src/templates',
        src: ['**/*.html'],
        dest: '.tmp/template.js',
        options: {
          module: 'ui.grid',
          htmlmin:  { collapseWhitespace: true, collapseBooleanAttributes: true },
          // Strip .html extension
          url: function(url) { return url.replace('.html', ''); }
        }
      }
    },

    // ngtemplates: {
    //   'ui-grid': {
    //     cwd: 'src/templates',
    //     src: '_partials/**/*.html',
    //     dest: '.tmp/template.js',
    //     options: {
    //       htmlmin:  { collapseWhitespace: true, collapseBooleanAttributes: true }
    //     }
    //   }
    // },

    // Task configuration.
    concat: {
      options: {
        banner: '<%= banner %>',
        stripBanners: true
      },
      dist: {
        src: ['src/js/**/*.js', '.tmp/template.js'],
        dest: '<%= dist %>/release/<%= pkg.name %>.js'
      }
    },

    less: {
      dist: {
        // paths: ['/bower_components/bootstrap'],
        files: {
          'dist/release/<%= pkg.name %>.css': 'src/less/main.less',
        }
      },
      min: {
        files: {
          'dist/release/<%= pkg.name %>.min.css': 'src/less/main.less',
        },
        options: {
          compress: true
        }
      }
    },

    uglify: {
      options: {
        banner: '<%= banner %>'
      },
      concat: {
        src: '<%= concat.dist.dest %>',
        dest: '<%= dist %>/release/<%= pkg.name %>.min.js'
      }
    },

    karma: {
      options: {
        configFile: 'test/karma.conf.js',
        files: util.angularFiles(util.latestAngular()).concat(util.testFiles.unit),
        background: true
      },
      // dev: {
      //   singleRun: false,
      //   background: true
      // },
      single: {
        background: false,
        singleRun: true,
        reporters: ['progress'],
      },

      travis: {
        background: false,
        singleRun: true,
        reporters: ['dots'],
      }
    },

    protractor: {
      options: {
        keepAlive: true,
        configFile: "./test/protractor.conf.js"
      },
      singlerun: {
        options: {
          keepAlive: false,
          args: {
            seleniumPort: 4444,
            baseUrl: 'http://127.0.0.1:9999',
            specs: ['.tmp/doc-scenarios/**/*.spec.js', 'test/e2e/**/*.spec.js']
          }
        }
      },
      ci: {
        options: {
          keepAlive: false,
          args: {
            // seleniumAddress: 'http://localhost:4445',
            // seleniumPort: 4445,
            baseUrl: 'http://127.0.0.1:9999',
            specs: ['.tmp/doc-scenarios/**/*.spec.js', 'test/e2e/**/*.spec.js'],
            sauceUser: process.env.SAUCE_USERNAME,
            sauceKey: process.env.SAUCE_ACCESS_KEY
          }
        }
      },
      auto: {
        options: {
          keepAlive: true,
          args: {
            seleniumPort: 4444,
            baseUrl: 'http://127.0.0.1:9999',
            specs: ['.tmp/doc-scenarios/**/*.spec.js', 'test/e2e/**/*.spec.js']
          }
        }
      }
      // docs: {
      //   options: {
      //     args: {
      //       seleniumPort: 4444,

      //     }
      //   }
      // }
    },

    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: false,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        unused: false,
        boss: true,
        eqnull: true,
        browser: true,
        debug: true, // debugger statements allowed
        globals: {
          angular: false,
          console: false,

          /* jquery (testing only) */
          $:false,
          jQuery: false,

          /* grunt */
          process: false,
          require: false,

          /* Jasmine */
          after: false,
          afterEach: false,
          before: false,
          beforeEach: false,
          dump: false,
          describe: false,
          ddescribe: false,
          expect: false,
          inject: false,
          it: false,
          iit: false,
          module: false,
          debugger: false,
          DocumentTouch: false
        }
      },
      gruntfile: {
        src: 'Gruntfile.js'
      },
      src_test: {
        src: ['src/**/*.js', 'test/**/*.spec.js']
      }
    },

    watch: {
      gruntfile: {
        files: '<%= jshint.gruntfile.src %>',
        tasks: ['jshint:gruntfile']
      },

      ngtemplates: {
        files: 'src/templates/**/*.html',
        tasks: ['ngtemplates']
      },

      // src_test: {
      //   files: '<%= jshint.src_test.src %>',
      //   tasks: ['jshint:src_test', 'jasmine']
      // },
      rebuild: {
        files: util.testFiles.unit,
        tasks: ['jshint:src_test', 'karmangular:run', 'concat', 'uglify', 'ngdocs'],
        options: {
          // livereload: true
        }
      },
      protractor: {
        files: ['.tmp/doc-scenarios/**/*.spec.js', 'test/e2e/**/*.spec.js'],
        tasks: ['protractor-watch:auto']
      },

      less: {
        files: 'src/**/*.less',
        tasks: ['less', 'ngdocs']
      },

      docs: {
        files: ['misc/tutorial/**/*.ngdoc', 'misc/doc/**'],
        tasks: 'ngdocs'
      },

      copy: {
        files: ['misc/site/**'],
        tasks: 'copy'
      },

      // karma: {
      //   files: ['src/**/*.js', 'test/unit/**/*.spec.js'],
      //   tasks: ['karma:dev:run'] //NOTE the :run flag
      // },

      livereload: {
        options: { livereload: true },
        files: ['dist/**/*', 'misc/demo/**/*.html', 'docs/**/*'],
      }
    },

    'gh-pages': {
      'gh-pages': {
        options: {
          base: '<%= dist %>',
          repo: 'https://github.com/angular-ui/ui-grid.info.git',
          message: 'gh-pages v<%= version %>',
          add: true
        },
        src: ['**/*']
      }
    },

    connect: {
      dev: {
        options: {
          port: process.env.DEV_PORT || 9002,
          base: '.',
          livereload: true
        }
      },
      docs: {
        options: {
          hostname: '*',
          port: process.env.DOCS_PORT || 9003,
          base: '<%= dist %>',
          livereload: true
        }
      },
      testserver: {
        options: {
          port: process.env.TEST_PORT || 9999,
          base: '<%= dist %>'
        }
      }
    },

    ngdocs: {
      options: {
        dest: '<%= dist %>/docs',
        testingUrlPrefix: '<%= protractor.auto.options.args.baseUrl %>/docs/#/',
        versionedFiles: {
          default: process.env.TRAVIS ? 'unstable' : 'stable',
          waitEval: "(function() { var ret = true; try { angular.module('ui.grid'); } catch (e) { ret = false; } return ret; })()",
          versions: {
            stable: [
              { src: '/release/<%= pkg.name %>.js', type: 'script' },
              { src: '/release/<%= pkg.name %>.css', type: 'css' }
            ],
            unstable: [
              { src: '/release/<%= pkg.name %>-unstable.js', type: 'script' },
              { src: '/release/<%= pkg.name %>-unstable.css', type: 'css' }
            ]
          }
        },
        scripts: [
          '//ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.js',
          '//ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular-touch.js',
        ],
        hiddenScripts: [
          '//ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular-animate.js',
          'bower_components/google-code-prettify/src/prettify.js',
          'node_modules/marked/lib/marked.js'
        ],
        httpScripts: [
          // process.env.TRAVIS ? '/release/<%= pkg.name %>.unstable.js' : '/release/<%= pkg.name %>.js'
          // '/release/<%= pkg.name %>.js'
        ],
        styles: [
          'misc/doc/css/prettify.css',
          'misc/doc/css/bootstrap-flatly.css',
          // process.env.TRAVIS ? '<%= dist %>/release/<%= pkg.name %>.unstable.css' : '<%= dist %>/release/<%= pkg.name %>.css'
          // '<%= dist %>/release/<%= pkg.name %>.css'
        ],
        title: 'UI Grid',
        titleLink: 'http://<%= site %>',
        html5Mode: false,
        analytics: {
          account: 'UA-46391685-1',
          domainName: 'ui-grid.info'
        },
        navTemplate: 'misc/doc/templates/nav.html'
      },
      api: {
        src: ['src/**/*.js'],
        title: 'API'
      },
      tutorial: {
        src: ['misc/tutorial/**/*.ngdoc'],
        title: 'Tutorial'
      }
    },

    copy: {
      site: {
        options: {
          processContent: grunt.template.process
        },
        files: [
          {
            expand: true,
            cwd: 'misc/site/',
            src: '**',
            dest: '<%= dist %>'
          }
        ]
      }
    },

    changelog: {
      options: {
        dest: 'CHANGELOG.md',
        github: 'angular-ui/ng-grid'
      }
    },

    'cut-release': {
      options: {
        cleanup: true,
        keepUnstable: false
      },
      dist: {
        src: '<%= dist %>/release/*.{js,css}',
        dest: '<%= dist %>/release/'
      }
    }
  });
  util.updateConfig();

  grunt.loadTasks('lib/grunt');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-jasmine');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-angular-templates');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-protractor-runner');
  grunt.loadNpmTasks('grunt-ngdocs');
  grunt.loadNpmTasks('grunt-conventional-changelog');
  grunt.loadNpmTasks('grunt-gh-pages');
  grunt.loadNpmTasks('grunt-shell-spawn');

  // grunt.renameTask('protractor', 'protractor-old');
  grunt.registerTask('protractor-watch', function () {
    var e2e = grunt.option('e2e');

    if (e2e !== false) {
      var args = '';
      if (this.args) {
        args = ':' + this.args.join(':');
      }

      grunt.task.run('protractor' + args);
    }
    else {
      grunt.log.writeln("Skipping e2e testing...");
    }
  });

  grunt.registerTask('install', ['shell:bower-install', 'shell:protractor-install']);

  // register before and after test tasks so we don't have to change cli
  // options on the CI server
  grunt.registerTask('before-test', ['clean', 'jshint', 'ngtemplates']);
  grunt.registerTask('after-test', ['build']);

  // Default task.
  // grunt.registerTask('default', ['clean', 'jshint', 'ngtemplates', 'karma:single', 'concat', 'uglify', 'less', 'ngdocs']);
  grunt.registerTask('default', ['before-test', 'test', 'after-test']);

  // Build with no testing
  grunt.registerTask('build', ['concat', 'uglify', 'less', 'ngdocs', 'copy']);

  // Auto-test tasks for development
  grunt.registerTask('autotest:unit', ['karmangular:start']);
  grunt.registerTask('autotest:e2e', ['shell:protractor-start']);

  // Development watch task
  grunt.registerTask('dev', function() {
    var e2e = grunt.option('e2e');

    var tasks = ['before-test', 'after-test', 'connect', 'autotest:unit', 'autotest:e2e', 'watch'];
    if (e2e === false) {
      tasks = ['before-test', 'after-test', 'connect', 'autotest:unit', 'watch'];
    }

    grunt.task.run(tasks);
  });

  // Testing tasks
  // grunt.registerTask('test:ci', ['clean', 'jshint', 'ngtemplates', 'karma:sauce']);
  grunt.registerTask('test:ci', ['clean', 'jshint', 'ngtemplates', 'serialsauce']);
  grunt.registerTask('test:docs', ['connect:testserver', 'protractor:docs']);
  grunt.registerTask('test:e2e', ['connect:testserver', 'protractor:singlerun']);
  grunt.registerTask('test:e2e:ci', ['clean', 'build', 'connect:testserver', 'protractor:ci']);

  // Test
  grunt.registerTask('test', 'Run tests on singleRun karma server', function() {
    // This task can be executed in 2 different environments: local, and Travis-CI
    if (process.env.TRAVIS) {
      grunt.task.run('karma:travis');
    }
    else {
      // grunt.task.run(this.args.length ? 'karma:single' : 'karma:continuous');
      grunt.task.run('karmangular');
    }
  });

  grunt.registerTask('release', ['clean', 'ngtemplates', 'build', 'cut-release', 'gh-pages']);
};
<commit_msg>fix(grunt): Add testDependencies file array to karma config for travis<commit_after>// var eyes = require('eyes');
var path = require('path');
var util = require('./lib/grunt/utils.js');

/*global module:false*/
module.exports = function(grunt) {
  // Project configuration.
  grunt.initConfig({
    // Metadata.
    pkg: grunt.file.readJSON('package.json'),
    version: util.getVersion(),
    stable_version: util.getStableVersion(),
    dist: 'dist',
    site: process.env.TRAVIS ? 'ui-grid.info' : '127.0.0.1:<%= connect.docs.options.port %>',
    banner: '/*! <%= pkg.title || pkg.name %> - v<%= version %> - ' +
      '<%= grunt.template.today("yyyy-mm-dd") %>\n' +
      '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
      '* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
      ' Licensed <%= pkg.license %> */\n',

    shell: {
      options: {
        stdout: true
      },
      selenium: {
        command: './selenium/start',
        options: {
          stdout: false,
          async: true
        }
      },
      'protractor-install': {
        command: 'node ./node_modules/protractor/bin/webdriver-manager update'
      },
      'protractor-start': {
        command: 'node ./node_modules/protractor/bin/webdriver-manager start',
        options: {
          stdout: true,
          async: true
        }
      },
      'bower-install': {
        command: 'bower install'
      }
    },

    // Clean the temp directory
    clean: ['.tmp', '<%= dist %>', 'docs'],

    // Templates
    ngtemplates: {
      'ui-grid': {
        cwd: 'src/templates',
        src: ['**/*.html'],
        dest: '.tmp/template.js',
        options: {
          module: 'ui.grid',
          htmlmin:  { collapseWhitespace: true, collapseBooleanAttributes: true },
          // Strip .html extension
          url: function(url) { return url.replace('.html', ''); }
        }
      }
    },

    // ngtemplates: {
    //   'ui-grid': {
    //     cwd: 'src/templates',
    //     src: '_partials/**/*.html',
    //     dest: '.tmp/template.js',
    //     options: {
    //       htmlmin:  { collapseWhitespace: true, collapseBooleanAttributes: true }
    //     }
    //   }
    // },

    // Task configuration.
    concat: {
      options: {
        banner: '<%= banner %>',
        stripBanners: true
      },
      dist: {
        src: ['src/js/**/*.js', '.tmp/template.js'],
        dest: '<%= dist %>/release/<%= pkg.name %>.js'
      }
    },

    less: {
      dist: {
        // paths: ['/bower_components/bootstrap'],
        files: {
          'dist/release/<%= pkg.name %>.css': 'src/less/main.less',
        }
      },
      min: {
        files: {
          'dist/release/<%= pkg.name %>.min.css': 'src/less/main.less',
        },
        options: {
          compress: true
        }
      }
    },

    uglify: {
      options: {
        banner: '<%= banner %>'
      },
      concat: {
        src: '<%= concat.dist.dest %>',
        dest: '<%= dist %>/release/<%= pkg.name %>.min.js'
      }
    },

    karma: {
      options: {
        configFile: 'test/karma.conf.js',
        files:  util.testDependencies.unit
                .concat(util.angularFiles(util.latestAngular()))
                .concat(util.testFiles.unit),
        background: true
      },
      // dev: {
      //   singleRun: false,
      //   background: true
      // },
      single: {
        background: false,
        singleRun: true,
        reporters: ['progress'],
      },

      travis: {
        background: false,
        singleRun: true,
        reporters: ['dots'],
      }
    },

    protractor: {
      options: {
        keepAlive: true,
        configFile: "./test/protractor.conf.js"
      },
      singlerun: {
        options: {
          keepAlive: false,
          args: {
            seleniumPort: 4444,
            baseUrl: 'http://127.0.0.1:9999',
            specs: ['.tmp/doc-scenarios/**/*.spec.js', 'test/e2e/**/*.spec.js']
          }
        }
      },
      ci: {
        options: {
          keepAlive: false,
          args: {
            // seleniumAddress: 'http://localhost:4445',
            // seleniumPort: 4445,
            baseUrl: 'http://127.0.0.1:9999',
            specs: ['.tmp/doc-scenarios/**/*.spec.js', 'test/e2e/**/*.spec.js'],
            sauceUser: process.env.SAUCE_USERNAME,
            sauceKey: process.env.SAUCE_ACCESS_KEY
          }
        }
      },
      auto: {
        options: {
          keepAlive: true,
          args: {
            seleniumPort: 4444,
            baseUrl: 'http://127.0.0.1:9999',
            specs: ['.tmp/doc-scenarios/**/*.spec.js', 'test/e2e/**/*.spec.js']
          }
        }
      }
      // docs: {
      //   options: {
      //     args: {
      //       seleniumPort: 4444,

      //     }
      //   }
      // }
    },

    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: false,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        unused: false,
        boss: true,
        eqnull: true,
        browser: true,
        debug: true, // debugger statements allowed
        globals: {
          angular: false,
          console: false,

          /* jquery (testing only) */
          $:false,
          jQuery: false,

          /* grunt */
          process: false,
          require: false,

          /* Jasmine */
          after: false,
          afterEach: false,
          before: false,
          beforeEach: false,
          dump: false,
          describe: false,
          ddescribe: false,
          expect: false,
          inject: false,
          it: false,
          iit: false,
          module: false,
          debugger: false,
          DocumentTouch: false
        }
      },
      gruntfile: {
        src: 'Gruntfile.js'
      },
      src_test: {
        src: ['src/**/*.js', 'test/**/*.spec.js']
      }
    },

    watch: {
      gruntfile: {
        files: '<%= jshint.gruntfile.src %>',
        tasks: ['jshint:gruntfile']
      },

      ngtemplates: {
        files: 'src/templates/**/*.html',
        tasks: ['ngtemplates']
      },

      // src_test: {
      //   files: '<%= jshint.src_test.src %>',
      //   tasks: ['jshint:src_test', 'jasmine']
      // },
      rebuild: {
        files: util.testFiles.unit,
        tasks: ['jshint:src_test', 'karmangular:run', 'concat', 'uglify', 'ngdocs'],
        options: {
          // livereload: true
        }
      },
      protractor: {
        files: ['.tmp/doc-scenarios/**/*.spec.js', 'test/e2e/**/*.spec.js'],
        tasks: ['protractor-watch:auto']
      },

      less: {
        files: 'src/**/*.less',
        tasks: ['less', 'ngdocs']
      },

      docs: {
        files: ['misc/tutorial/**/*.ngdoc', 'misc/doc/**'],
        tasks: 'ngdocs'
      },

      copy: {
        files: ['misc/site/**'],
        tasks: 'copy'
      },

      // karma: {
      //   files: ['src/**/*.js', 'test/unit/**/*.spec.js'],
      //   tasks: ['karma:dev:run'] //NOTE the :run flag
      // },

      livereload: {
        options: { livereload: true },
        files: ['dist/**/*', 'misc/demo/**/*.html', 'docs/**/*'],
      }
    },

    'gh-pages': {
      'gh-pages': {
        options: {
          base: '<%= dist %>',
          repo: 'https://github.com/angular-ui/ui-grid.info.git',
          message: 'gh-pages v<%= version %>',
          add: true
        },
        src: ['**/*']
      }
    },

    connect: {
      dev: {
        options: {
          port: process.env.DEV_PORT || 9002,
          base: '.',
          livereload: true
        }
      },
      docs: {
        options: {
          hostname: '*',
          port: process.env.DOCS_PORT || 9003,
          base: '<%= dist %>',
          livereload: true
        }
      },
      testserver: {
        options: {
          port: process.env.TEST_PORT || 9999,
          base: '<%= dist %>'
        }
      }
    },

    ngdocs: {
      options: {
        dest: '<%= dist %>/docs',
        testingUrlPrefix: '<%= protractor.auto.options.args.baseUrl %>/docs/#/',
        versionedFiles: {
          default: process.env.TRAVIS ? 'unstable' : 'stable',
          waitEval: "(function() { var ret = true; try { angular.module('ui.grid'); } catch (e) { ret = false; } return ret; })()",
          versions: {
            stable: [
              { src: '/release/<%= pkg.name %>.js', type: 'script' },
              { src: '/release/<%= pkg.name %>.css', type: 'css' }
            ],
            unstable: [
              { src: '/release/<%= pkg.name %>-unstable.js', type: 'script' },
              { src: '/release/<%= pkg.name %>-unstable.css', type: 'css' }
            ]
          }
        },
        scripts: [
          '//ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.js',
          '//ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular-touch.js',
        ],
        hiddenScripts: [
          '//ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular-animate.js',
          'bower_components/google-code-prettify/src/prettify.js',
          'node_modules/marked/lib/marked.js'
        ],
        httpScripts: [
          // process.env.TRAVIS ? '/release/<%= pkg.name %>.unstable.js' : '/release/<%= pkg.name %>.js'
          // '/release/<%= pkg.name %>.js'
        ],
        styles: [
          'misc/doc/css/prettify.css',
          'misc/doc/css/bootstrap-flatly.css',
          // process.env.TRAVIS ? '<%= dist %>/release/<%= pkg.name %>.unstable.css' : '<%= dist %>/release/<%= pkg.name %>.css'
          // '<%= dist %>/release/<%= pkg.name %>.css'
        ],
        title: 'UI Grid',
        titleLink: 'http://<%= site %>',
        html5Mode: false,
        analytics: {
          account: 'UA-46391685-1',
          domainName: 'ui-grid.info'
        },
        navTemplate: 'misc/doc/templates/nav.html'
      },
      api: {
        src: ['src/**/*.js'],
        title: 'API'
      },
      tutorial: {
        src: ['misc/tutorial/**/*.ngdoc'],
        title: 'Tutorial'
      }
    },

    copy: {
      site: {
        options: {
          processContent: grunt.template.process
        },
        files: [
          {
            expand: true,
            cwd: 'misc/site/',
            src: '**',
            dest: '<%= dist %>'
          }
        ]
      }
    },

    changelog: {
      options: {
        dest: 'CHANGELOG.md',
        github: 'angular-ui/ng-grid'
      }
    },

    'cut-release': {
      options: {
        cleanup: true,
        keepUnstable: false
      },
      dist: {
        src: '<%= dist %>/release/*.{js,css}',
        dest: '<%= dist %>/release/'
      }
    }
  });
  util.updateConfig();

  grunt.loadTasks('lib/grunt');
  grunt.loadNpmTasks('grunt-contrib-concat');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-jasmine');
  grunt.loadNpmTasks('grunt-contrib-clean');
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-less');
  grunt.loadNpmTasks('grunt-contrib-copy');
  grunt.loadNpmTasks('grunt-angular-templates');
  grunt.loadNpmTasks('grunt-contrib-connect');
  grunt.loadNpmTasks('grunt-karma');
  grunt.loadNpmTasks('grunt-protractor-runner');
  grunt.loadNpmTasks('grunt-ngdocs');
  grunt.loadNpmTasks('grunt-conventional-changelog');
  grunt.loadNpmTasks('grunt-gh-pages');
  grunt.loadNpmTasks('grunt-shell-spawn');

  // grunt.renameTask('protractor', 'protractor-old');
  grunt.registerTask('protractor-watch', function () {
    var e2e = grunt.option('e2e');

    if (e2e !== false) {
      var args = '';
      if (this.args) {
        args = ':' + this.args.join(':');
      }

      grunt.task.run('protractor' + args);
    }
    else {
      grunt.log.writeln("Skipping e2e testing...");
    }
  });

  grunt.registerTask('install', ['shell:bower-install', 'shell:protractor-install']);

  // register before and after test tasks so we don't have to change cli
  // options on the CI server
  grunt.registerTask('before-test', ['clean', 'jshint', 'ngtemplates']);
  grunt.registerTask('after-test', ['build']);

  // Default task.
  // grunt.registerTask('default', ['clean', 'jshint', 'ngtemplates', 'karma:single', 'concat', 'uglify', 'less', 'ngdocs']);
  grunt.registerTask('default', ['before-test', 'test', 'after-test']);

  // Build with no testing
  grunt.registerTask('build', ['concat', 'uglify', 'less', 'ngdocs', 'copy']);

  // Auto-test tasks for development
  grunt.registerTask('autotest:unit', ['karmangular:start']);
  grunt.registerTask('autotest:e2e', ['shell:protractor-start']);

  // Development watch task
  grunt.registerTask('dev', function() {
    var e2e = grunt.option('e2e');

    var tasks = ['before-test', 'after-test', 'connect', 'autotest:unit', 'autotest:e2e', 'watch'];
    if (e2e === false) {
      tasks = ['before-test', 'after-test', 'connect', 'autotest:unit', 'watch'];
    }

    grunt.task.run(tasks);
  });

  // Testing tasks
  // grunt.registerTask('test:ci', ['clean', 'jshint', 'ngtemplates', 'karma:sauce']);
  grunt.registerTask('test:ci', ['clean', 'jshint', 'ngtemplates', 'serialsauce']);
  grunt.registerTask('test:docs', ['connect:testserver', 'protractor:docs']);
  grunt.registerTask('test:e2e', ['connect:testserver', 'protractor:singlerun']);
  grunt.registerTask('test:e2e:ci', ['clean', 'build', 'connect:testserver', 'protractor:ci']);

  // Test
  grunt.registerTask('test', 'Run tests on singleRun karma server', function() {
    // This task can be executed in 2 different environments: local, and Travis-CI
    if (process.env.TRAVIS) {
      grunt.task.run('karma:travis');
    }
    else {
      // grunt.task.run(this.args.length ? 'karma:single' : 'karma:continuous');
      grunt.task.run('karmangular');
    }
  });

  grunt.registerTask('release', ['clean', 'ngtemplates', 'build', 'cut-release', 'gh-pages']);
};
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var BinaryParser = require('./binary_parser').BinaryParser,
  inspect = require('util').inspect,
  debug = require('util').debug;

/**
 * Machine id.
 *
 * Create a random 3-byte value (i.e. unique for this
 * process). Other drivers use a md5 of the machine id here, but
 * that would mean an asyc call to gethostname, so we don't bother.
 */

var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10);

/**
 * Constructor.
 *
 * @param {String} id (optional)
 */

function ObjectID (id) {

  // Throw an error if it's not a valid setup
  if(id != null && !id instanceof Date && (id.length != 12 && id.length != 24)) throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters in hex format");
  // Generate id based on the input
  if (null == id || id instanceof Date) {
    this.id = this.generate(id);
  } else if (/^[0-9a-fA-F]{24}$/.test(id)) {
    return ObjectID.createFromHexString(id);
  } else {
    this.id = id;
  }
};

/**
 * Updates the ObjectID index.
 *
 * @return {Number}
 */

ObjectID.prototype.get_inc = function() {
  return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF;
};

/**
 * Generates an ObjectId.
 *
 * @return {String}
 */

ObjectID.prototype.generate = function(time) {

  if (time instanceof Date) {
    var unixTime = time.getTime();
  } else {
  	var unixTime = Date.now();
  }

  unixTime = parseInt(unixTime/1000,10);

  var time4Bytes = BinaryParser.encodeInt(unixTime, 32, true, true);
  var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false);
  var pid2Bytes = BinaryParser.fromShort(process.pid);
  var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true);
  return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes;
};

/**
 * Converts this ObjectId to a hex string.
 *
 * @return {String}
 */

ObjectID.prototype.toHexString = function() {
  var hexString = ''
    , number
    , value;

  for (var index = 0, len = this.id.length; index < len; index++) {
    value = BinaryParser.toByte(this.id.substr(index, 1));
    number = value <= 15
      ? '0' + value.toString(16)
      : value.toString(16);
    hexString = hexString + number;
  }

  return hexString;
};

/**
 * Converts this id to a string.
 *
 * @return {String}
 */

ObjectID.prototype.toString = function() {
  return this.toHexString();
};

/**
 * Converts to a string representation of this Id.
 */

ObjectID.prototype.inspect = ObjectID.prototype.toString;

/**
 * Converts to its JSON representation.
 */

ObjectID.prototype.toJSON = ObjectID.prototype.toString;

/**
 * Compares the equality of this ObjectID with `otherID`.
 *
 * @return {Bool}
 */

ObjectID.prototype.equals = function equals (otherID) {
  var id = (otherID instanceof ObjectID || otherID.toHexString)
    ? otherID.id
    : ObjectID.createFromHexString(otherID).id;

  return this.id === id;
}

/**
 * Returns the generation time in seconds that this
 * ID was generated.
 *
 * @return {Number}
 */

ObjectID.prototype.__defineGetter__("generationTime", function() {
  return BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true) * 1000;
});

/**
 * Statics.
 */

ObjectID.index = 0;

ObjectID.createPk = function createPk () {
  return new ObjectID();
};

/**
 * Creates an ObjectID from a hex string representation
 * of an ObjectID.
 *
 * @param {String} hexString
 * @return {ObjectID}
 */

ObjectID.createFromHexString = function createFromHexString (hexString) {
  // Throw an error if it's not a valid setup
  if(hexString != null && hexString.length != 24) throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters in hex format");

  var len = hexString.length;

  if(len > 12*2) {
    throw new Error('Id cannot be longer than 12 bytes');
  }

  var result = ''
    , string
    , number;

  for (var index = 0; index < len; index += 2) {
    string = hexString.substr(index, 2);
    number = parseInt(string, 16);
    result += BinaryParser.fromByte(number);
  }

  return new ObjectID(result);
};

/**
 * Expose.
 */

exports.ObjectID = ObjectID;

<commit_msg>zeroed extra bytes<commit_after>/**
 * Module dependencies.
 */

var BinaryParser = require('./binary_parser').BinaryParser,
  inspect = require('util').inspect,
  debug = require('util').debug;

/**
 * Machine id.
 *
 * Create a random 3-byte value (i.e. unique for this
 * process). Other drivers use a md5 of the machine id here, but
 * that would mean an asyc call to gethostname, so we don't bother.
 */

var MACHINE_ID = parseInt(Math.random() * 0xFFFFFF, 10);

/**
 * Constructor.
 *
 * @param {String} id (optional)
 */

function ObjectID (id) {

  // Throw an error if it's not a valid setup
  if(id != null && !id instanceof Date && (id.length != 12 && id.length != 24)) throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters in hex format");
  // Generate id based on the input
  if (null == id || id instanceof Date) {
    this.id = this.generate(id);
  } else if (/^[0-9a-fA-F]{24}$/.test(id)) {
    return ObjectID.createFromHexString(id);
  } else {
    this.id = id;
  }
};

/**
 * Updates the ObjectID index.
 *
 * @return {Number}
 */

ObjectID.prototype.get_inc = function() {
  return ObjectID.index = (ObjectID.index + 1) % 0xFFFFFF;
};

/**
 * Generates an ObjectId.
 *
 * @return {String}
 */

ObjectID.prototype.generate = function(time) {

  if (time instanceof Date) {
    var unixTime = parseInt(time.getTime()/1000,10);
    var time4Bytes = BinaryParser.encodeInt(unixTime, 32, true, true);
    /* if time-based ObjectID is desired the bytes following the time will be zeroed */
    var machine3Bytes = BinaryParser.encodeInt(0, 24, false);
    var pid2Bytes = BinaryParser.fromShort(0);
    var index3Bytes = BinaryParser.encodeInt(0, 24, false, true);
  } else {
  	var unixTime = parseInt(Date.now()/1000,10);
    var time4Bytes = BinaryParser.encodeInt(unixTime, 32, true, true);
    var machine3Bytes = BinaryParser.encodeInt(MACHINE_ID, 24, false);
    var pid2Bytes = BinaryParser.fromShort(process.pid);
    var index3Bytes = BinaryParser.encodeInt(this.get_inc(), 24, false, true);

  }

  return time4Bytes + machine3Bytes + pid2Bytes + index3Bytes;
};

/**
 * Converts this ObjectId to a hex string.
 *
 * @return {String}
 */

ObjectID.prototype.toHexString = function() {
  var hexString = ''
    , number
    , value;

  for (var index = 0, len = this.id.length; index < len; index++) {
    value = BinaryParser.toByte(this.id.substr(index, 1));
    number = value <= 15
      ? '0' + value.toString(16)
      : value.toString(16);
    hexString = hexString + number;
  }

  return hexString;
};

/**
 * Converts this id to a string.
 *
 * @return {String}
 */

ObjectID.prototype.toString = function() {
  return this.toHexString();
};

/**
 * Converts to a string representation of this Id.
 */

ObjectID.prototype.inspect = ObjectID.prototype.toString;

/**
 * Converts to its JSON representation.
 */

ObjectID.prototype.toJSON = ObjectID.prototype.toString;

/**
 * Compares the equality of this ObjectID with `otherID`.
 *
 * @return {Bool}
 */

ObjectID.prototype.equals = function equals (otherID) {
  var id = (otherID instanceof ObjectID || otherID.toHexString)
    ? otherID.id
    : ObjectID.createFromHexString(otherID).id;

  return this.id === id;
}

/**
 * Returns the generation time in seconds that this
 * ID was generated.
 *
 * @return {Number}
 */

ObjectID.prototype.__defineGetter__("generationTime", function() {
  return BinaryParser.decodeInt(this.id.substring(0,4), 32, true, true) * 1000;
});

/**
 * Statics.
 */

ObjectID.index = 0;

ObjectID.createPk = function createPk () {
  return new ObjectID();
};

/**
 * Creates an ObjectID from a hex string representation
 * of an ObjectID.
 *
 * @param {String} hexString
 * @return {ObjectID}
 */

ObjectID.createFromHexString = function createFromHexString (hexString) {
  // Throw an error if it's not a valid setup
  if(hexString != null && hexString.length != 24) throw new Error("Argument passed in must be a single String of 12 bytes or a string of 24 hex characters in hex format");

  var len = hexString.length;

  if(len > 12*2) {
    throw new Error('Id cannot be longer than 12 bytes');
  }

  var result = ''
    , string
    , number;

  for (var index = 0; index < len; index += 2) {
    string = hexString.substr(index, 2);
    number = parseInt(string, 16);
    result += BinaryParser.fromByte(number);
  }

  return new ObjectID(result);
};

/**
 * Expose.
 */

exports.ObjectID = ObjectID;

<|endoftext|>


<commit_before>/*global module:false*/
module.exports = function(grunt) {

  // Project configuration.
  grunt.initConfig({
    meta: {
      package: grunt.file.readJSON('package.json'),
      src: {
        main: 'src/',
        test: 'spec/'
      },
      bin: {
        coverage: 'bin/coverage'
      }
    },
    // Task configuration.
    jshint: {
      options: {
        curly: true,
        eqeqeq: true,
        immed: true,
        latedef: true,
        newcap: true,
        noarg: true,
        sub: true,
        undef: true,
        unused: true,
        boss: true,
        eqnull: true,
        globals: {
          jQuery: true
        }
      },
      gruntfile: {
        src: 'Gruntfile.js'
      },
      lib_test: {
        src: ['src/**/*.js', 'spec/**/*.js']
      }
    },
    jasmine: {
      coverage: {
        src: '<%= meta.src.main %>/js/*.js',
        options: {
          specs: '<%= meta.src.test %>/js/*.js',
          template: require('grunt-template-jasmine-istanbul'),
          templateOptions: {
            coverage: '<%= meta.bin.coverage %>/coverage.json',
            report: [
              {
                type: 'html',
                options: {
                  dir: '<%= meta.bin.coverage %>/html'
                }
              },
              {
                type: 'cobertura',
                options: {
                  dir: '<%= meta.bin.coverage %>/cobertura'
                }
              },
              {
                type: 'text-summary'
              }
            ]
          }
        }
      }
    },
    watch: {
      gruntfile: {
        files: '<%= jshint.gruntfile.src %>',
        tasks: ['jshint:gruntfile']
      }
    }
  });

  // These plugins provide necessary tasks.
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-jasmine');

  // Default task.
  grunt.registerTask('default', ['jshint', 'nodeunit']);
  grunt.registerTask('test:coverage', ['jasmine:coverage']);

};
<commit_msg>Switching to karam<commit_after><|endoftext|>


<commit_before>/*jshint expr: true*/

var rewire = require('rewire');

var events = require('events');
var eventEmitter = new events.EventEmitter();

var nock = require('nock');

var shuttle = rewire('../../routes/shuttle.js');
var revert;

var Code = require('code');
var Lab = require('lab');
var lab = exports.lab = Lab.script();

var expect = Code.expect;
var describe = lab.experiment;
var it = lab.test;

var beforeEach = lab.beforeEach;

describe('exports', function () {
  beforeEach(function (done) {
    eventEmitter.removeAllListeners();
    nock.disableNetConnect();
    if (typeof revert === 'function') {
      revert();
    }
    done();
  });

  it('should have properties for stops(), routes(), times(), plans(), and predictions()', function (done) {
    expect(typeof shuttle.stops).to.equal('function');
    expect(typeof shuttle.routes).to.equal('function');
    expect(typeof shuttle.times).to.equal('function');
    expect(typeof shuttle.plan).to.equal('function');
    expect(typeof shuttle.predictions).to.equal('function');
    done();
  });

  describe('times()', function () {
    it('should return times for route at stop, omitting dropoff-only times', function (done) {
      var mockReq = {query: {routeId: 'black', stopId: 'lhts', startTime: '1427698800000'}};
      var mockRes = {json: function (data) {
        expect(data.times instanceof Array).to.be.true;
        expect(data.times.length).to.equal(39);
        expect(data.times[0].time).to.equal(1427722200);
        // expect(data.times[0].direction).to.be.null;
        // TODO: test that results are sorted
        done();
      }};

      nock('http://localhost:8080')
        .get('/otp/routers/default/index/stops/ucsf%3Alhts/stoptimes/20150330?details=true&refs=true')
        .replyWithFile(200, __dirname + '/../fixtures/shuttleTimes.json');

      shuttle.times(mockReq, mockRes);
    });
  });

  describe('routes()', function () {
    it('should return JSON for routes', function (done) {
      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        var expectedResults = {
          routes: [
            { id: { id: 'black' }, routeShortName: 'Black', routeLongName: 'Parnassus - Mt. Zion - Laurel Heights' },
            { id: { id: 'blue' }, routeShortName: 'Blue', routeLongName: 'Parnassus - SFGH - Mission Bay - Mt. Zion' },
            { id: { id: 'bronze' }, routeShortName: 'Bronze', routeLongName: 'Aldea - ACC - Library - 6th - Dental - LPPI' },
            { id: { id: 'gold' }, routeShortName: 'Gold', routeLongName: 'Parnassus - Mt. Zion - Mission Bay - SFGH' },
            { id: { id: 'green' }, routeShortName: 'Green', routeLongName: 'Mission Bay - China Basin - 654 Minnesota' },
            { id: { id: 'grey' }, routeShortName: 'Grey', routeLongName: 'Parnassus - Mission Bay' },
            { id: { id: 'lime' }, routeShortName: 'Lime', routeLongName: 'Parnassus - 55 Laguna Parking - BDC - MCB' },
            { id: { id: 'pink' }, routeShortName: 'Pink', routeLongName: 'Parnassus E/R - Kezar' },
            { id: { id: 'purple' }, routeShortName: 'Purple', routeLongName: 'Parnassus (Library) - 3360 Geary - Mt. Zion - 3360 Geary' },
            { id: { id: 'red' }, routeShortName: 'Red', routeLongName: 'Mission Bay - MCB - 16th St BART' },
            { id: { id: 'tan' }, routeShortName: 'Tan', routeLongName: 'Parnassus - Laurel Heights - Mt. Zion' },
            { id: { id: 'va' }, routeShortName: 'VA', routeLongName: 'VAMC - Parnassus' },
            { id: { id: 'yellow' }, routeShortName: 'Yellow', routeLongName: '16th BART - MCB - 20th/Alabama - SFGH' }
          ]
        };

        var comparator = function (a, b) {
          if (a.id.id < b.id.id) {
            return -1;
          }
          return 1;
        };

        expect(data.routes.sort(comparator)).to.deep.equal(expectedResults.routes);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/routes')
      .replyWithFile(200, __dirname + '/../fixtures/shuttleRoutes.json');

      shuttle.routes(mockReq, mockRes);
    });
  });

  describe('stops()', function () {
    it('should return all stops if no options specified', function (done) {
      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        var expectedResults = {'stops':[
        {'id':{id:'Parnassus',agencyId:'ucsf'},'stopName':'Parnassus Campus','stopLat':37.763174,'stopLon':-122.459176},
        {'id':{id:'MB',agencyId:'ucsf'},'stopName':'Mission Bay Campus','stopLat':37.76793,'stopLon':-122.391009},
        {'id':{id:'hospital',agencyId:'ucsf'},'stopName':'Mission Bay Hospital','stopLat':37.766373,'stopLon':-122.391379},
        {'id':{id:'16thbart',agencyId:'ucsf'},'stopName':'16th St. BART','stopLat':37.765128,'stopLon':-122.419402},
        {'id':{id:'75behr',agencyId:'ucsf'},'stopName':'Aldea Housing','stopLat':37.758793,'stopLon':-122.454181},
        {'id':{id:'3360 Geary',agencyId:'ucsf'},'stopName':'3360 Geary','stopLat':37.78161,'stopLon':-122.455075},
        {'id':{id:'100 Buchanan',agencyId:'ucsf'},'stopName':'Buchanan Dental Center','stopLat':37.770791,'stopLon':-122.426684},
        {'id':{id:'sfgh',agencyId:'ucsf'},'stopName':'SFGH','stopLat':37.7548539352877,'stopLon':-122.40492649376392},
        {'id':{id:'caltrain',agencyId:'ucsf'},'stopName':'Caltrain','stopLat':37.7769459,'stopLon':-122.395165},
        {'id':{id:'mcb',agencyId:'ucsf'},'stopName':'Mission Center Building','stopLat':37.767326,'stopLon':-122.414519},
        {'id':{id:'parkezar',agencyId:'ucsf'},'stopName':'Kezar Lot','stopLat':37.767188,'stopLon':-122.453403},
        {'id':{id:'lhts',agencyId:'ucsf'},'stopName':'Laurel Heights','stopLat':37.786592,'stopLon':-122.448552},
        {'id':{id:'2300 Harrison',agencyId:'ucsf'},'stopName':'20th & Alabama','stopLat':37.759072,'stopLon':-122.411562},
        {'id':{id:'veteran',agencyId:'ucsf'},'stopName':'VA Medical Center','stopLat':37.782019,'stopLon':-122.504996},
        {'id':{id:'surgedown',agencyId:'ucsf'},'stopName':'Surge/Woods','stopLat':37.760757,'stopLon':-122.456163},
        {'id':{id:'chinbasn',agencyId:'ucsf'},'stopName':'China Basin','stopLat':37.776594,'stopLon':-122.39223},
        {'id':{id:'654minn',agencyId:'ucsf'},'stopName':'654 Minnesota','stopLat':37.761834,'stopLon':-122.390661},
        {'id':{id:'499ill',agencyId:'ucsf'},'stopName':'499 Illinois','stopLat':37.7659378,'stopLon':-122.3878759},
        {'id':{id:'mtzion',agencyId:'ucsf'},'stopName':'Mt. Zion','stopLat':37.78524781704753,'stopLon':-122.439474016428}
        ]};
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/stops')
      .replyWithFile(200, __dirname + '/../fixtures/shuttleStops.json');

      shuttle.stops(mockReq, mockRes);
    });

    it('should return just the blue stops if a routeId is specified', function (done) {
      var mockReq = {query: {routeId: 'blue'}};
      var mockRes = {json: function (data) {
        var expectedResults = {
          stops:[
          {'id':{id:'parlppi',agencyId:'ucsf'}, stopName:'401 Parnassus (LPPI)', stopLat:37.7638174033811, stopLon:-122.45648592710495, parentStation:'Parnassus'},
          {'id':{id:'missb4we',agencyId:'ucsf'}, stopName:'Mission Bay (west side of street)', stopLat:37.76793, stopLon:-122.391009, parentStation:'MB'},
          {'id':{id:'sfgh',agencyId:'ucsf'}, stopName:'SFGH', stopLat:37.7548539352877, stopLon:-122.40492649376392},
          {'id':{id:'mtzion',agencyId:'ucsf'}, stopName:'Mt. Zion', stopLat:37.78524781704753, stopLon:-122.439474016428},
          {'id':{id:'hospital',agencyId:'ucsf'}, stopName:'Mission Bay Hospital', stopLat:37.766373, stopLon:-122.391379}
          ],
          route:{
            id:{id:'blue'},routeShortName:'Blue'
          }
        };
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
        .get('/otp/routers/default/index/routes/ucsf%3Ablue/stops?detail=true&refs=true')
        .replyWithFile(200, __dirname + '/../fixtures/shuttleStopsBlue.json');

      shuttle.stops(mockReq, mockRes);
    });

    it('should report an error if HTTP response code is not 200 or 404', function (done) {
      var errorLogged = false;
      var errorSent = false;

      eventEmitter.once('errorLogged', function () {
        errorLogged = true;
        if (errorSent) {
          done();
        }
      });

      eventEmitter.once('errorSent', function () {
        errorSent = true;
        if (errorLogged) {
          done();
        }
      });

      revert = shuttle.__set__('logger', function (value) {
        expect(value).to.equal('shuttle/stops error: code 400');
        eventEmitter.emit('errorLogged');
      });

      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        var expectedResults = {error: 'shuttle/stops error: code 400'};
        expect(data).to.deep.equal(expectedResults);
        eventEmitter.emit('errorSent');
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/stops')
      .reply(400, 'FOUR ZERO ZERO');

      shuttle.stops(mockReq, mockRes);
    });

    it('should return an empty array for stops if the JSON does not contain the required property', function (done) {
      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        var expectedResults = {stops: []};
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/stops')
      .replyWithFile(200, __dirname + '/../fixtures/borkedShuttleStops.json');

      shuttle.stops(mockReq, mockRes);
    });

    it('should return an empty array for stops if JSON is empty array', function (done) {
      var mockReq = {query: {routeId: 'blue'}};
      var mockRes = {json: function (data) {
        var expectedResults = {stops: []};
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/routes/ucsf%3Ablue/stops?detail=true&refs=true')
      .replyWithFile(200, __dirname + '/../fixtures/borkedShuttleStopsBlue.json');

      shuttle.stops(mockReq, mockRes);
    });

    it('should return an empty array for stops if JSON is borked', function (done) {
      revert = shuttle.__set__('logger', function () {});

      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        var expectedResults = {stops: []};
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/stops')
      .reply(200, '{');

      shuttle.stops(mockReq, mockRes);
    });

    it('should return an empty array for stops and empty object for route if required property is an object without route and stops properties', function (done) {
      var mockReq = {query: {routeId: 'magenta'}};
      var mockRes = {json: function (data) {
        var expectedResults = {stops: [], route:{}};
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/routes/ucsf%3Amagenta/stops?detail=true&refs=true')
      .reply(404, __dirname + '/../fixtures/borkedShuttleStopsMagenta.json');

      shuttle.stops(mockReq, mockRes);
    });
  });
});

<commit_msg>more unhappy path checking<commit_after>/*jshint expr: true*/

var rewire = require('rewire');

var events = require('events');
var eventEmitter = new events.EventEmitter();

var nock = require('nock');

var shuttle = rewire('../../routes/shuttle.js');
var revert;

var Code = require('code');
var Lab = require('lab');
var lab = exports.lab = Lab.script();

var expect = Code.expect;
var describe = lab.experiment;
var it = lab.test;

var beforeEach = lab.beforeEach;

describe('exports', function () {
  beforeEach(function (done) {
    eventEmitter.removeAllListeners();
    nock.disableNetConnect();
    if (typeof revert === 'function') {
      revert();
    }
    done();
  });

  it('should have properties for stops(), routes(), times(), plans(), and predictions()', function (done) {
    expect(typeof shuttle.stops).to.equal('function');
    expect(typeof shuttle.routes).to.equal('function');
    expect(typeof shuttle.times).to.equal('function');
    expect(typeof shuttle.plan).to.equal('function');
    expect(typeof shuttle.predictions).to.equal('function');
    done();
  });

  describe('times()', function () {
    it('should return times for route at stop, omitting dropoff-only times', function (done) {
      var mockReq = {query: {routeId: 'black', stopId: 'lhts', startTime: '1427698800000'}};
      var mockRes = {json: function (data) {
        expect(data.times instanceof Array).to.be.true;
        expect(data.times.length).to.equal(39);
        expect(data.times[0].time).to.equal(1427722200);
        // expect(data.times[0].direction).to.be.null;
        // TODO: test that results are sorted
        done();
      }};

      nock('http://localhost:8080')
        .get('/otp/routers/default/index/stops/ucsf%3Alhts/stoptimes/20150330?details=true&refs=true')
        .replyWithFile(200, __dirname + '/../fixtures/shuttleTimes.json');

      shuttle.times(mockReq, mockRes);
    });
  });

  describe('routes()', function () {
    it('should return JSON for routes', function (done) {
      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        var expectedResults = {
          routes: [
            { id: { id: 'black' }, routeShortName: 'Black', routeLongName: 'Parnassus - Mt. Zion - Laurel Heights' },
            { id: { id: 'blue' }, routeShortName: 'Blue', routeLongName: 'Parnassus - SFGH - Mission Bay - Mt. Zion' },
            { id: { id: 'bronze' }, routeShortName: 'Bronze', routeLongName: 'Aldea - ACC - Library - 6th - Dental - LPPI' },
            { id: { id: 'gold' }, routeShortName: 'Gold', routeLongName: 'Parnassus - Mt. Zion - Mission Bay - SFGH' },
            { id: { id: 'green' }, routeShortName: 'Green', routeLongName: 'Mission Bay - China Basin - 654 Minnesota' },
            { id: { id: 'grey' }, routeShortName: 'Grey', routeLongName: 'Parnassus - Mission Bay' },
            { id: { id: 'lime' }, routeShortName: 'Lime', routeLongName: 'Parnassus - 55 Laguna Parking - BDC - MCB' },
            { id: { id: 'pink' }, routeShortName: 'Pink', routeLongName: 'Parnassus E/R - Kezar' },
            { id: { id: 'purple' }, routeShortName: 'Purple', routeLongName: 'Parnassus (Library) - 3360 Geary - Mt. Zion - 3360 Geary' },
            { id: { id: 'red' }, routeShortName: 'Red', routeLongName: 'Mission Bay - MCB - 16th St BART' },
            { id: { id: 'tan' }, routeShortName: 'Tan', routeLongName: 'Parnassus - Laurel Heights - Mt. Zion' },
            { id: { id: 'va' }, routeShortName: 'VA', routeLongName: 'VAMC - Parnassus' },
            { id: { id: 'yellow' }, routeShortName: 'Yellow', routeLongName: '16th BART - MCB - 20th/Alabama - SFGH' }
          ]
        };

        var comparator = function (a, b) {
          if (a.id.id < b.id.id) {
            return -1;
          }
          return 1;
        };

        expect(data.routes.sort(comparator)).to.deep.equal(expectedResults.routes);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/routes')
      .replyWithFile(200, __dirname + '/../fixtures/shuttleRoutes.json');

      shuttle.routes(mockReq, mockRes);
    });
  });

  describe('stops()', function () {
    it('should return all stops if no options specified', function (done) {
      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        var expectedResults = {'stops':[
        {'id':{id:'Parnassus',agencyId:'ucsf'},'stopName':'Parnassus Campus','stopLat':37.763174,'stopLon':-122.459176},
        {'id':{id:'MB',agencyId:'ucsf'},'stopName':'Mission Bay Campus','stopLat':37.76793,'stopLon':-122.391009},
        {'id':{id:'hospital',agencyId:'ucsf'},'stopName':'Mission Bay Hospital','stopLat':37.766373,'stopLon':-122.391379},
        {'id':{id:'16thbart',agencyId:'ucsf'},'stopName':'16th St. BART','stopLat':37.765128,'stopLon':-122.419402},
        {'id':{id:'75behr',agencyId:'ucsf'},'stopName':'Aldea Housing','stopLat':37.758793,'stopLon':-122.454181},
        {'id':{id:'3360 Geary',agencyId:'ucsf'},'stopName':'3360 Geary','stopLat':37.78161,'stopLon':-122.455075},
        {'id':{id:'100 Buchanan',agencyId:'ucsf'},'stopName':'Buchanan Dental Center','stopLat':37.770791,'stopLon':-122.426684},
        {'id':{id:'sfgh',agencyId:'ucsf'},'stopName':'SFGH','stopLat':37.7548539352877,'stopLon':-122.40492649376392},
        {'id':{id:'caltrain',agencyId:'ucsf'},'stopName':'Caltrain','stopLat':37.7769459,'stopLon':-122.395165},
        {'id':{id:'mcb',agencyId:'ucsf'},'stopName':'Mission Center Building','stopLat':37.767326,'stopLon':-122.414519},
        {'id':{id:'parkezar',agencyId:'ucsf'},'stopName':'Kezar Lot','stopLat':37.767188,'stopLon':-122.453403},
        {'id':{id:'lhts',agencyId:'ucsf'},'stopName':'Laurel Heights','stopLat':37.786592,'stopLon':-122.448552},
        {'id':{id:'2300 Harrison',agencyId:'ucsf'},'stopName':'20th & Alabama','stopLat':37.759072,'stopLon':-122.411562},
        {'id':{id:'veteran',agencyId:'ucsf'},'stopName':'VA Medical Center','stopLat':37.782019,'stopLon':-122.504996},
        {'id':{id:'surgedown',agencyId:'ucsf'},'stopName':'Surge/Woods','stopLat':37.760757,'stopLon':-122.456163},
        {'id':{id:'chinbasn',agencyId:'ucsf'},'stopName':'China Basin','stopLat':37.776594,'stopLon':-122.39223},
        {'id':{id:'654minn',agencyId:'ucsf'},'stopName':'654 Minnesota','stopLat':37.761834,'stopLon':-122.390661},
        {'id':{id:'499ill',agencyId:'ucsf'},'stopName':'499 Illinois','stopLat':37.7659378,'stopLon':-122.3878759},
        {'id':{id:'mtzion',agencyId:'ucsf'},'stopName':'Mt. Zion','stopLat':37.78524781704753,'stopLon':-122.439474016428}
        ]};
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/stops')
      .replyWithFile(200, __dirname + '/../fixtures/shuttleStops.json');

      shuttle.stops(mockReq, mockRes);
    });

    it('should return just the blue stops if a routeId is specified', function (done) {
      var mockReq = {query: {routeId: 'blue'}};
      var mockRes = {json: function (data) {
        var expectedResults = {
          stops:[
          {'id':{id:'parlppi',agencyId:'ucsf'}, stopName:'401 Parnassus (LPPI)', stopLat:37.7638174033811, stopLon:-122.45648592710495, parentStation:'Parnassus'},
          {'id':{id:'missb4we',agencyId:'ucsf'}, stopName:'Mission Bay (west side of street)', stopLat:37.76793, stopLon:-122.391009, parentStation:'MB'},
          {'id':{id:'sfgh',agencyId:'ucsf'}, stopName:'SFGH', stopLat:37.7548539352877, stopLon:-122.40492649376392},
          {'id':{id:'mtzion',agencyId:'ucsf'}, stopName:'Mt. Zion', stopLat:37.78524781704753, stopLon:-122.439474016428},
          {'id':{id:'hospital',agencyId:'ucsf'}, stopName:'Mission Bay Hospital', stopLat:37.766373, stopLon:-122.391379}
          ],
          route:{
            id:{id:'blue'},routeShortName:'Blue'
          }
        };
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
        .get('/otp/routers/default/index/routes/ucsf%3Ablue/stops?detail=true&refs=true')
        .replyWithFile(200, __dirname + '/../fixtures/shuttleStopsBlue.json');

      shuttle.stops(mockReq, mockRes);
    });

    it('should report an error if HTTP response code is not 200 or 404', function (done) {
      var errorLogged = false;
      var errorSent = false;

      eventEmitter.once('errorLogged', function () {
        errorLogged = true;
        if (errorSent) {
          done();
        }
      });

      eventEmitter.once('errorSent', function () {
        errorSent = true;
        if (errorLogged) {
          done();
        }
      });

      revert = shuttle.__set__('logger', function (value) {
        expect(value).to.equal('shuttle/stops error: code 400');
        eventEmitter.emit('errorLogged');
      });

      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        var expectedResults = {error: 'shuttle/stops error: code 400'};
        expect(data).to.deep.equal(expectedResults);
        eventEmitter.emit('errorSent');
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/stops')
      .reply(400, 'FOUR ZERO ZERO');

      shuttle.stops(mockReq, mockRes);
    });

    it('should return an empty array for stops if the JSON does not contain the required property', function (done) {
      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        var expectedResults = {stops: []};
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/stops')
      .replyWithFile(200, __dirname + '/../fixtures/borkedShuttleStops.json');

      shuttle.stops(mockReq, mockRes);
    });

    it('should return an empty array for stops if JSON is empty array', function (done) {
      var mockReq = {query: {routeId: 'blue'}};
      var mockRes = {json: function (data) {
        var expectedResults = {stops: []};
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/routes/ucsf%3Ablue/stops?detail=true&refs=true')
      .replyWithFile(200, __dirname + '/../fixtures/borkedShuttleStopsBlue.json');

      shuttle.stops(mockReq, mockRes);
    });

    it('should return an empty array for stops if JSON is borked', function (done) {
      revert = shuttle.__set__('logger', function () {});

      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        var expectedResults = {stops: []};
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/stops')
      .reply(200, '{');

      shuttle.stops(mockReq, mockRes);
    });

    it('should return an empty array for stops and empty object for route if required property is an object without route and stops properties', function (done) {
      var mockReq = {query: {routeId: 'magenta'}};
      var mockRes = {json: function (data) {
        var expectedResults = {stops: [], route:{}};
        expect(data).to.deep.equal(expectedResults);
        done();
      }};

      nock('http://localhost:8080')
      .get('/otp/routers/default/index/routes/ucsf%3Amagenta/stops?detail=true&refs=true')
      .reply(404, __dirname + '/../fixtures/borkedShuttleStopsMagenta.json');

      shuttle.stops(mockReq, mockRes);
    });

    it('should log and return an error if there is an http error event', function (done) {
      var logged = false;
      revert = shuttle.__set__('logger', function (message) {
        expect(message.slice(0, 21)).to.equal('shuttle/stops error: ');
        expect(message.length).to.be.greaterThan(20);
        logged = true;
      });

      var mockReq = {query: {}};
      var mockRes = {json: function (data) {
        expect(typeof data.error).to.equal('string');
        expect(data.error.length).to.be.greaterThan(5);
        expect(logged).to.equal(true);
        done();
      }};

      shuttle.stops(mockReq, mockRes);
    });
  });
});

<|endoftext|>