<commit_before>var polygon = require('turf-polygon');

/**
 * Takes a bounding box and a cell size in degrees and creates a {@link FeatureCollection} of flat-topped
 * hexagons aligned in an "odd-q" vertical grid as
 * described in [Hexagonal Grids](http://www.redblobgames.com/grids/hexagons/)
 *
 * @module turf/hex
 * @param {number[]} bbox in [minX, minY, maxX, maxY] order
 * @param {number} size size of cells in degrees
 * @return {FeatureCollection} output
 * @example
 * var hexgrid = turf.hex([
 *   7.2669410, 43.695307,
 *   7.2862529, 43.706476
 * ], 0.001);
 * //=hexgrid
 */
module.exports = hexgrid;

//Precompute cosines and sines of angles used in hexagon creation
// for performance gain
var cosines = [];
var sines = [];
for (var i = 0; i < 6; i++) {
  var angle = 2 * Math.PI/6 * i;
  cosines.push(Math.cos(angle));
  sines.push(Math.sin(angle));
}

//Center should be [x, y]
function hexagon(center, radius) {
  var vertices = [];

  for (var i = 0; i < 6; i++) {
    var x = center[0] + radius * cosines[i];
    var y = center[1] + radius * sines[i];

    vertices.push([x,y]);
  }

  //first and last vertex must be the same
  vertices.push(vertices[0]);

  return polygon([vertices]);
}

function hexgrid(bbox, radius) {
  var xmin = bbox[0];
  var ymin = bbox[1];
  var xmax = bbox[2];
  var ymax = bbox[3];

  var fc = {
    type: 'FeatureCollection',
    features: []
  };

  var hex_width = radius * 2;
  var hex_height = Math.sqrt(3)/2 * hex_width;

  var box_width = xmax - xmin;
  var box_height = ymax - ymin;

  var x_interval = 3/4 * hex_width;
  var y_interval = hex_height;

  var x_span = box_width / (hex_width - radius/2);
  var x_count = Math.ceil(x_span);
  if (Math.round(x_span) === x_count) {
    x_count++;
  }

  var x_adjust = ((x_count * x_interval - radius/2) - box_width)/2 - radius/2;

  var y_count = Math.ceil(box_height / hex_height);

  var y_adjust = (box_height - y_count * hex_height)/2;

  var hasOffsetY = y_count * hex_height - box_height > hex_height/2;
  if (hasOffsetY) {
    y_adjust -= hex_height/4;
  }

  for (var x = 0; x < x_count; x++) {
    for (var y = 0; y <= y_count; y++) {

      var isOdd = x % 2 === 1;
      if (y === 0 && isOdd) {
        continue;
      }

      if (y === 0 && hasOffsetY) {
        continue;
      }

      var center_x = x * x_interval + xmin - x_adjust;
      var center_y = y * y_interval + ymin + y_adjust;

      if (isOdd) {
        center_y -= hex_height/2;
      }

      fc.features.push(hexagon([center_x, center_y], radius));
    }
  }

  return fc;
}
<commit_msg>Small style fixes in example<commit_after>var polygon = require('turf-polygon');

/**
 * Takes a bounding box and a cell size in degrees and creates a {@link FeatureCollection} of flat-topped
 * hexagons aligned in an "odd-q" vertical grid as
 * described in [Hexagonal Grids](http://www.redblobgames.com/grids/hexagons/)
 *
 * @module turf/hex
 * @param {Array<number>} bbox bounding box in [minX, minY, maxX, maxY] order
 * @param {Number} size size of cells in degrees
 * @return {FeatureCollection} a FeatureCollection of hexagonal Polygon features in a grid
 * @example
 * var bbox = [7.2669410, 43.695307, 7.2862529, 43.706476];
 * var size = 0.001;
 * var hexgrid = turf.hex(bbox, size);
 *
 * //=hexgrid
 */
module.exports = hexgrid;

//Precompute cosines and sines of angles used in hexagon creation
// for performance gain
var cosines = [];
var sines = [];
for (var i = 0; i < 6; i++) {
  var angle = 2 * Math.PI/6 * i;
  cosines.push(Math.cos(angle));
  sines.push(Math.sin(angle));
}

//Center should be [x, y]
function hexagon(center, radius) {
  var vertices = [];

  for (var i = 0; i < 6; i++) {
    var x = center[0] + radius * cosines[i];
    var y = center[1] + radius * sines[i];

    vertices.push([x,y]);
  }

  //first and last vertex must be the same
  vertices.push(vertices[0]);

  return polygon([vertices]);
}

function hexgrid(bbox, radius) {
  var xmin = bbox[0];
  var ymin = bbox[1];
  var xmax = bbox[2];
  var ymax = bbox[3];

  var fc = {
    type: 'FeatureCollection',
    features: []
  };

  var hex_width = radius * 2;
  var hex_height = Math.sqrt(3)/2 * hex_width;

  var box_width = xmax - xmin;
  var box_height = ymax - ymin;

  var x_interval = 3/4 * hex_width;
  var y_interval = hex_height;

  var x_span = box_width / (hex_width - radius/2);
  var x_count = Math.ceil(x_span);
  if (Math.round(x_span) === x_count) {
    x_count++;
  }

  var x_adjust = ((x_count * x_interval - radius/2) - box_width)/2 - radius/2;

  var y_count = Math.ceil(box_height / hex_height);

  var y_adjust = (box_height - y_count * hex_height)/2;

  var hasOffsetY = y_count * hex_height - box_height > hex_height/2;
  if (hasOffsetY) {
    y_adjust -= hex_height/4;
  }

  for (var x = 0; x < x_count; x++) {
    for (var y = 0; y <= y_count; y++) {

      var isOdd = x % 2 === 1;
      if (y === 0 && isOdd) {
        continue;
      }

      if (y === 0 && hasOffsetY) {
        continue;
      }

      var center_x = x * x_interval + xmin - x_adjust;
      var center_y = y * y_interval + ymin + y_adjust;

      if (isOdd) {
        center_y -= hex_height/2;
      }

      fc.features.push(hexagon([center_x, center_y], radius));
    }
  }

  return fc;
}
<|endoftext|>


<commit_before>/*
 * deep-clone
 * @author Garrett Reed <garrett@garrettreed.co> 2016
 * MIT Licensed
 *
 * Suports:
 *   Primitives: null, string, number, function (inherits prototype)
 *   Collections: object, array
 *
 * @param {object} target Receiving object
 * @param {object/array} obj Object to clone
 * @return {object/array} the clone
 *
 */
var deepClone = (function() {
    'use strict';

    var _isPrimitive = function(value) {
        if (value === null) {
            return true;
        }

        switch (typeof value) {
            case 'string':
            case 'number':
            case 'boolean':
            case 'undefined':
            case 'function':
                return true;
            default:
                return false;
        }
    };

    var _isArray = function(value) {
        return Object.prototype.toString.call(value) === '[object Array]';
    };

    var _clone = function(target, obj) {
        for (var key in obj) {
            if (_isPrimitive(obj[key])) {
                target[key] = obj[key];
                if (typeof target[key] === 'function') {
                    target[key].prototype = Object.create(obj[key].prototype);
                }
            } else if (_isArray(obj[key])) {
                target[key] = [];
                deepClone(target[key], obj[key]);
            } else {
                target[key] = Object.create(Object.getPrototypeOf(obj[key]));
                _clone(target[key], obj[key]);
            }
        }
        return target;
    };

    return _clone;
})();
<commit_msg>Change recursive call to private function<commit_after>/*
 * deep-clone
 * @author Garrett Reed <garrett@garrettreed.co> 2016
 * MIT Licensed
 *
 * Suports:
 *   Primitives: null, string, number, function (inherits prototype)
 *   Collections: object, array
 *
 * @param {object} target Receiving object
 * @param {object/array} obj Object to clone
 * @return {object/array} the clone
 *
 */
var deepClone = (function() {
    'use strict';

    var _isPrimitive = function(value) {
        if (value === null) {
            return true;
        }

        switch (typeof value) {
            case 'string':
            case 'number':
            case 'boolean':
            case 'undefined':
            case 'function':
                return true;
            default:
                return false;
        }
    };

    var _isArray = function(value) {
        return Object.prototype.toString.call(value) === '[object Array]';
    };

    var _clone = function(target, obj) {
        for (var key in obj) {
            if (_isPrimitive(obj[key])) {
                target[key] = obj[key];
                if (typeof target[key] === 'function') {
                    target[key].prototype = Object.create(obj[key].prototype);
                }
            } else if (_isArray(obj[key])) {
                target[key] = [];
                _clone(target[key], obj[key]);
            } else {
                target[key] = Object.create(Object.getPrototypeOf(obj[key]));
                _clone(target[key], obj[key]);
            }
        }
        return target;
    };

    return _clone;
})();
<|endoftext|>


<commit_before>'use strict';

const Metalsmith = require('metalsmith')
const jade = require('metalsmith-jade')
const sass = require('metalsmith-sass')
const browserSync = require('metalsmith-browser-sync')
const markdown = require('metalsmith-markdown')
const layouts = require('metalsmith-layouts')
const permalinks = require('metalsmith-permalinks')
const babel = require('metalsmith-babel')
const bourbon = require('node-bourbon')
const path = require('path')
const postcss = require('metalsmith-postcss')
const autoprefixer = require('autoprefixer')
const copy = require('metalsmith-copy')
const each = require('metalsmith-each')

const updatePaths = function(file, filename){
  if(filename.substr(filename.length-5, filename.length) === '.html' && filename.substr(0, 5) !== 'docs/') {
    console.log(`Change filename ${filename} to ${filename.substr(0, filename.length-5)}`);
    return filename = filename.substr(0, filename.length-5);
  }
  return filename;
};

Metalsmith(__dirname)
  .use(markdown({
    smartypants: true,
    gfm: true,
    tables: true
  }))
  // .use(layouts({
  //   engine: 'jade',
  //   directory: './layouts'
  // }))
  .use(jade({
    pretty: true
  }))
  .use(sass({
    outputStyle: 'expanded',
    includePaths: [
      '/node_modules/',
      path.join(__dirname, 'node_modules/support-for/sass')
     ].concat(bourbon.includePaths)
  }))
  .use(postcss([
    autoprefixer({ browsers: ['last 4 versions'] })
  ]))
  .use(babel({
    presets: ['es2015']
  }))
  .use(copy({
    pattern: 'assets/*',
    directory: 'assets'
  }))
  // .use(permalinks('documentation/:title'))
  .use((() => {
    if(!process.env.CI) {
      return browserSync({
        server: {
          baseDir: './build',
          middleware: function(req, res, next) {
            if (req.originalUrl.indexOf('.') === -1) {
              var file = './build' + req.originalUrl;
              require('fs').exists(file, function(exists) {
                if (exists) req.url;
                next();
              });
            } else {
              next();
            }
          }
        },
        files: ['./src/**/*']
      });
    }
  })())
  .use(each(updatePaths))
  .build((err) => {
    if (err) throw err
  })<commit_msg>*bump*<commit_after>'use strict';

const Metalsmith = require('metalsmith')
const jade = require('metalsmith-jade')
const sass = require('metalsmith-sass')
const browserSync = require('metalsmith-browser-sync')
const markdown = require('metalsmith-markdown')
const layouts = require('metalsmith-layouts')
const permalinks = require('metalsmith-permalinks')
const babel = require('metalsmith-babel')
const bourbon = require('node-bourbon')
const path = require('path')
const postcss = require('metalsmith-postcss')
const autoprefixer = require('autoprefixer')
const copy = require('metalsmith-copy')
const each = require('metalsmith-each')

const updatePaths = function(file, filename){
  if(filename.substr(filename.length-5, filename.length) === '.html' && filename.substr(0, 5) !== 'docs/') {
    console.log(`Change filename ${filename} to ${filename.substr(0, filename.length-5)}`);
    return filename = filename.substr(0, filename.length-5);
  }
  return filename;
};

Metalsmith(__dirname)
  .use(markdown({
    smartypants: true,
    gfm: true,
    tables: true
  }))
  // .use(layouts({
  //   engine: 'jade',
  //   directory: './layouts'
  // }))
  .use(jade({
    pretty: true
  }))
  .use(sass({
    outputStyle: 'expanded',
    includePaths: [
      '/node_modules/',
      path.join(__dirname, 'node_modules/support-for/sass')
     ].concat(bourbon.includePaths)
  }))
  .use(postcss([
    autoprefixer({ browsers: ['last 4 versions'] })
  ]))
  .use(babel({
    presets: ['es2015']
  }))
  .use(copy({
    pattern: 'assets/*',
    directory: 'assets'
  }))
  // .use(permalinks('documentation/:title'))
  .use(each(updatePaths))
  .use((() => {
    if(!process.env.CI) {
      return browserSync({
        server: {
          baseDir: './build',
          middleware: function(req, res, next) {
            if (req.originalUrl.indexOf('.') === -1) {
              var file = './build' + req.originalUrl;
              require('fs').exists(file, function(exists) {
                if (exists) req.url;
                next();
              });
            } else {
              next();
            }
          }
        },
        files: ['./src/**/*']
      });
    }
  })())
  .build((err) => {
    if (err) throw err
  })<|endoftext|>


<commit_before>'use strict';

var ReactClickDragMixin = require('react-clickdrag-mixin');
var clamp = require('clamp');
var React = require('react');

var KEYS = {
    UP: 38,
    DOWN: 40,
    ENTER: 13
};

var NumberEditor = React.createClass({

    mixins: [ReactClickDragMixin],

    propTypes: {
        min: React.PropTypes.number,
        max: React.PropTypes.number,
        step: React.PropTypes.number,
        stepModifier: React.PropTypes.number,
        decimals: React.PropTypes.number,
        initialValue: React.PropTypes.number,
        className: React.PropTypes.string,
        onValueChange: React.PropTypes.func
    },

    getDefaultProps: function() {
        return {
            min: -Number.MAX_VALUE,
            max: Number.MAX_VALUE,
            step: 1,
            stepModifier: 10,
            decimals: 0,
            initialValue: 0,
            className: '',
            onValueChange: function() {}
        };
    },

    getInitialState: function() {
        return {
            startEditing: false,
            startDragging: false,
            wasUsingSpecialKeys: false,
            value: this.props.initialValue,
            valueStr: String(this.props.initialValue),
            dragStartValue: this.props.initialValue
        };
    },

    componentDidMount: function() {
        this._changeValue(this.state.value);
    },

    _changeValue: function(value) {
        // Using the formatted value converted as a number assure that value == valueStr (with the right number of decimals)
        var newVal = clamp(Number(value.toFixed(this.props.decimals)), this.props.min, this.props.max);
        var formattedValue = newVal.toFixed(this.props.decimals);

        this.setState({
            value: newVal,
            valueStr: formattedValue
        });

        this.props.onValueChange(newVal);
    },

    _getStepValue: function(e, step) {
        if(e.metaKey || e.ctrlKey)
            step /= this.props.stepModifier;
        else if(e.shiftKey)
            step *= this.props.stepModifier;

        return step;
    },

    _onKeyDown: function(e) {
        var step = this._getStepValue(e, this.props.step);

        var value = this.state.value;
        var key = e.which;

        if(key == KEYS.UP) {
            e.preventDefault();
            this._changeValue(value + step);
        }
        else if(key == KEYS.DOWN) {
            e.preventDefault();
            this._changeValue(value - step);
        }
        else if(key == KEYS.ENTER) {
            if(this.state.startEditing) {
                // stop editing + save value
                this._onBlur();
            }
            else {
                this.setState({
                    startEditing: true
                });
            }
        }
    },

    _onDoubleClick: function(e) {
        this.setState({
            startEditing: true
        });
    },

    _onChange: function(e) {
        // Update only valueStr to get the right display during editing
        this.setState({
            valueStr: e.target.value
        });
    },

    _onBlur: function(e) {
        // valueStr could have changed by _onChange, so we force to update the value
        this._changeValue(Number(this.state.valueStr));

        this.setState({
            startEditing: false
        });
    },

    _onDragStart: function(e, pos) {
        this.setState({
            startDragging: true,
            dragStartValue: this.state.value
        });
    },
    _onDragStop: function() {
        this.setState({
            startDragging: false
        });
    },
    _onDragMove: function(e, deltaPos) {
        e.preventDefault();

        // If a special key is used and wasn't use before,
        // we have to set the new Mouse Position and new Drag Start value
        var isUsingSpecialKeys = e.metaKey || e.ctrlKey || e.shiftKey;
        if(isUsingSpecialKeys != this.state.wasUsingSpecialKeys) {
            this.setMousePosition(e.clientX, e.clientY);
            this.setState({
                wasUsingSpecialKeys: isUsingSpecialKeys,
                dragStartValue: this.state.value
            })
            return;
        }

        var step = this._getStepValue(e, this.props.step);
        this._changeValue(this.state.dragStartValue + deltaPos.x * (step/2));
    },

    render: function() {
        var cursor = 'ew-resize';
        var readOnly = true;
        if(this.state.startEditing) {
            cursor = 'auto';
            readOnly = false;
        }

        document.body.style.cursor = (this.state.startDragging) ? 'ew-resize' : 'auto';

        return React.createElement('input', {
            type: 'text',
            className: this.props.className,
            readOnly: readOnly,
            value: this.state.valueStr,
            style: { cursor: cursor },
            onKeyDown: this._onKeyDown,
            onDoubleClick: this._onDoubleClick,
            onChange: this._onChange,
            onBlur: this._onBlur
        });
    }
});

module.exports = NumberEditor;
<commit_msg>Don't break serverside rendering<commit_after>'use strict';

var ReactClickDragMixin = require('react-clickdrag-mixin');
var clamp = require('clamp');
var React = require('react');

var KEYS = {
    UP: 38,
    DOWN: 40,
    ENTER: 13
};

var NumberEditor = React.createClass({

    mixins: [ReactClickDragMixin],

    propTypes: {
        min: React.PropTypes.number,
        max: React.PropTypes.number,
        step: React.PropTypes.number,
        stepModifier: React.PropTypes.number,
        decimals: React.PropTypes.number,
        initialValue: React.PropTypes.number,
        className: React.PropTypes.string,
        onValueChange: React.PropTypes.func
    },

    getDefaultProps: function() {
        return {
            min: -Number.MAX_VALUE,
            max: Number.MAX_VALUE,
            step: 1,
            stepModifier: 10,
            decimals: 0,
            initialValue: 0,
            className: '',
            onValueChange: function() {}
        };
    },

    getInitialState: function() {
        return {
            startEditing: false,
            startDragging: false,
            wasUsingSpecialKeys: false,
            value: this.props.initialValue,
            valueStr: String(this.props.initialValue),
            dragStartValue: this.props.initialValue
        };
    },

    componentDidMount: function() {
        this._changeValue(this.state.value);
    },

    _changeValue: function(value) {
        // Using the formatted value converted as a number assure that value == valueStr (with the right number of decimals)
        var newVal = clamp(Number(value.toFixed(this.props.decimals)), this.props.min, this.props.max);
        var formattedValue = newVal.toFixed(this.props.decimals);

        this.setState({
            value: newVal,
            valueStr: formattedValue
        });

        this.props.onValueChange(newVal);
    },

    _getStepValue: function(e, step) {
        if(e.metaKey || e.ctrlKey)
            step /= this.props.stepModifier;
        else if(e.shiftKey)
            step *= this.props.stepModifier;

        return step;
    },

    _onKeyDown: function(e) {
        var step = this._getStepValue(e, this.props.step);

        var value = this.state.value;
        var key = e.which;

        if(key == KEYS.UP) {
            e.preventDefault();
            this._changeValue(value + step);
        }
        else if(key == KEYS.DOWN) {
            e.preventDefault();
            this._changeValue(value - step);
        }
        else if(key == KEYS.ENTER) {
            if(this.state.startEditing) {
                // stop editing + save value
                this._onBlur();
            }
            else {
                this.setState({
                    startEditing: true
                });
            }
        }
    },

    _onDoubleClick: function(e) {
        this.setState({
            startEditing: true
        });
    },

    _onChange: function(e) {
        // Update only valueStr to get the right display during editing
        this.setState({
            valueStr: e.target.value
        });
    },

    _onBlur: function(e) {
        // valueStr could have changed by _onChange, so we force to update the value
        this._changeValue(Number(this.state.valueStr));

        this.setState({
            startEditing: false
        });
    },

    _onDragStart: function(e, pos) {
        this.setState({
            startDragging: true,
            dragStartValue: this.state.value
        });
    },
    _onDragStop: function() {
        this.setState({
            startDragging: false
        });
    },
    _onDragMove: function(e, deltaPos) {
        e.preventDefault();

        // If a special key is used and wasn't use before,
        // we have to set the new Mouse Position and new Drag Start value
        var isUsingSpecialKeys = e.metaKey || e.ctrlKey || e.shiftKey;
        if(isUsingSpecialKeys != this.state.wasUsingSpecialKeys) {
            this.setMousePosition(e.clientX, e.clientY);
            this.setState({
                wasUsingSpecialKeys: isUsingSpecialKeys,
                dragStartValue: this.state.value
            })
            return;
        }

        var step = this._getStepValue(e, this.props.step);
        this._changeValue(this.state.dragStartValue + deltaPos.x * (step/2));
    },

    render: function() {
        var cursor = 'ew-resize';
        var readOnly = true;
        if(this.state.startEditing) {
            cursor = 'auto';
            readOnly = false;
        }

        if (this.isMounted()) {
          document.body.style.cursor = (this.state.startDragging) ? 'ew-resize' : 'auto';
        }

        return React.createElement('input', {
            type: 'text',
            className: this.props.className,
            readOnly: readOnly,
            value: this.state.valueStr,
            style: { cursor: cursor },
            onKeyDown: this._onKeyDown,
            onDoubleClick: this._onDoubleClick,
            onChange: this._onChange,
            onBlur: this._onBlur
        });
    }
});

module.exports = NumberEditor;
<|endoftext|>


<commit_before>var schedule = require('node-schedule');
var GPIO = require('onoff').Gpio;
var config = require('./config/config.js')
//console.log(config)

//Need four jobs to control on-off operations of two Lights.
var ruleLightOne_On = new schedule.RecurrenceRule();
var ruleLightOne_Off = new schedule.RecurrenceRule();
var ruleLightTwo_On = new schedule.RecurrenceRule();
var ruleLightTwo_Off = new schedule.RecurrenceRule();

//Two jobs to control aquarium filter pump
var rulePump_On = new schedule.RecurrenceRule();
var rulePump_Off = new schedule.RecurrenceRule();

var ON = 0;
var OFF = 1;

//Create two lights corresponding to GPIO 2 & 3
var light1 = new GPIO(2, 'out');
var light2 = new GPIO(3, 'out');

//Create pump corresponding to GPIO 4
var pump = new GPIO(4, 'out');

var date = new Date();
var hour = date.getHours();

if(hour >= config.ruleLightOne_On.hour && hour =< config.ruleLightOne_Off.hour){
  //Activate light 1
  light1.writeSync(ON);
  console.log('Aquarium Lights - ' + date + ' Light One turned on');
} else {
  light1.writeSync(OFF);
  console.log('Aquarium Lights - ' + date + ' Light One turned off');
}

if(hour >= config.ruleLightTwo_On.hour && hour =< config.ruleLightTwo_Off.hour){
  //Activate light 2
  light2.writeSync(ON);
  console.log('Aquarium Lights - ' + date + ' Light Two turned on');
} else {
  light2.writeSync(OFF);
  console.log('Aquarium Lights - ' + date + ' Light Two turned off');
}

if(hour >= config.rulePump_On.hour && hour =< config.rulePump_Off.hour){
  //Activate light 2
  pump.writeSync(ON);
  console.log('Aquarium Pump - ' + date + ' Filter pump turned on');
} else {
  pump.writeSync(OFF);
  console.log('Aquarium Pump - ' + date + ' Filter pump turned off');
}

console.log('Aquarium lights - Pins activated. Scheduling Jobs');

//Light One on at 1000 hrs every day
ruleLightOne_On.minute = config.ruleLightOne_On.minute;
ruleLightOne_On.hour = config.ruleLightOne_On.hour;
schedule.scheduleJob(ruleLightOne_On, function(){
  console.log('Aquarium Lights - ' + new Date() + ' Light One turned on');
  light1.writeSync(ON);
});

//Light One off at 2000 hrs every day
ruleLightOne_Off.minute = config.ruleLightOne_Off.minute;
ruleLightOne_Off.hour = config.ruleLightOne_Off.hour;
schedule.scheduleJob(ruleLightOne_Off, function(){
  console.log('Aquarium Lights - ' + new Date() + ' Light One turned off');
  light1.writeSync(OFF);
});

//Light Two on at 1200 hrs every day
ruleLightTwo_On.minute = config.ruleLightTwo_On.minute;
ruleLightTwo_On.hour = config.ruleLightTwo_On.hour;
schedule.scheduleJob(ruleLightTwo_On, function(){
  console.log('Aquarium Lights - ' + new Date() + ' Light Two turned on');
  light2.writeSync(ON);
});

//Light Two off at 2200 hrs every day
ruleLightTwo_Off.minute = config.ruleLightTwo_Off.minute;
ruleLightTwo_Off.hour = config.ruleLightTwo_Off.hour;
schedule.scheduleJob(ruleLightTwo_Off, function(){
  console.log('Aquarium Lights - ' + new Date() + ' Light Two turned off');
  light2.writeSync(OFF);
});

//Pump turned on at 1000 hrs every day
rulePump_On.minute = config.rulePump_On.minute;
rulePump_On.hour = config.rulePump_On.hour;
schedule.scheduleJob(rulePump_On, function(){
  console.log('Aquarium Pump - ' + new Date() + ' Filter pump turned on');
  pump.writeSync(ON);
});

//Pump turned off at 2200 hrs every day
rulePump_Off.minute = config.rulePump_On.minute;
rulePump_Off.hour = config.rulePump_On.hour;
schedule.scheduleJob(rulePump_Off, function(){
  console.log('Aquarium Pump - ' + new Date() + ' Filter pump turned off');
  pump.writeSync(OFF);
});

console.log('Aquarium Lights - Jobs Scheduled');

//process.on('SIGINT', function (){
  //light1.unexport();
  //light2.unexport();
//});
<commit_msg>index changes<commit_after>var schedule = require('node-schedule');
var GPIO = require('onoff').Gpio;
var config = require('./config/config.js')
//console.log(config)

//Need four jobs to control on-off operations of two Lights.
var ruleLightOne_On = new schedule.RecurrenceRule();
var ruleLightOne_Off = new schedule.RecurrenceRule();
var ruleLightTwo_On = new schedule.RecurrenceRule();
var ruleLightTwo_Off = new schedule.RecurrenceRule();

//Two jobs to control aquarium filter pump
var rulePump_On = new schedule.RecurrenceRule();
var rulePump_Off = new schedule.RecurrenceRule();

var ON = 0;
var OFF = 1;

//Create two lights corresponding to GPIO 2 & 3
var light1 = new GPIO(2, 'out');
var light2 = new GPIO(3, 'out');

//Create pump corresponding to GPIO 4
var pump = new GPIO(4, 'out');

var date = new Date();
var hour = date.getHours();

if(hour >= config.ruleLightOne_On.hour && hour <= config.ruleLightOne_Off.hour){
  //Activate light 1
  light1.writeSync(ON);
  console.log('Aquarium Lights - ' + date + ' Light One turned on');
} else {
  light1.writeSync(OFF);
  console.log('Aquarium Lights - ' + date + ' Light One turned off');
}

if(hour >= config.ruleLightTwo_On.hour && hour <= config.ruleLightTwo_Off.hour){
  //Activate light 2
  light2.writeSync(ON);
  console.log('Aquarium Lights - ' + date + ' Light Two turned on');
} else {
  light2.writeSync(OFF);
  console.log('Aquarium Lights - ' + date + ' Light Two turned off');
}

if(hour >= config.rulePump_On.hour && hour <= config.rulePump_Off.hour){
  //Activate light 2
  pump.writeSync(ON);
  console.log('Aquarium Pump - ' + date + ' Filter pump turned on');
} else {
  pump.writeSync(OFF);
  console.log('Aquarium Pump - ' + date + ' Filter pump turned off');
}

console.log('Aquarium lights - Pins activated. Scheduling Jobs');

//Light One on at 1000 hrs every day
ruleLightOne_On.minute = config.ruleLightOne_On.minute;
ruleLightOne_On.hour = config.ruleLightOne_On.hour;
schedule.scheduleJob(ruleLightOne_On, function(){
  console.log('Aquarium Lights - ' + new Date() + ' Light One turned on');
  light1.writeSync(ON);
});

//Light One off at 2000 hrs every day
ruleLightOne_Off.minute = config.ruleLightOne_Off.minute;
ruleLightOne_Off.hour = config.ruleLightOne_Off.hour;
schedule.scheduleJob(ruleLightOne_Off, function(){
  console.log('Aquarium Lights - ' + new Date() + ' Light One turned off');
  light1.writeSync(OFF);
});

//Light Two on at 1200 hrs every day
ruleLightTwo_On.minute = config.ruleLightTwo_On.minute;
ruleLightTwo_On.hour = config.ruleLightTwo_On.hour;
schedule.scheduleJob(ruleLightTwo_On, function(){
  console.log('Aquarium Lights - ' + new Date() + ' Light Two turned on');
  light2.writeSync(ON);
});

//Light Two off at 2200 hrs every day
ruleLightTwo_Off.minute = config.ruleLightTwo_Off.minute;
ruleLightTwo_Off.hour = config.ruleLightTwo_Off.hour;
schedule.scheduleJob(ruleLightTwo_Off, function(){
  console.log('Aquarium Lights - ' + new Date() + ' Light Two turned off');
  light2.writeSync(OFF);
});

//Pump turned on at 1000 hrs every day
rulePump_On.minute = config.rulePump_On.minute;
rulePump_On.hour = config.rulePump_On.hour;
schedule.scheduleJob(rulePump_On, function(){
  console.log('Aquarium Pump - ' + new Date() + ' Filter pump turned on');
  pump.writeSync(ON);
});

//Pump turned off at 2200 hrs every day
rulePump_Off.minute = config.rulePump_On.minute;
rulePump_Off.hour = config.rulePump_On.hour;
schedule.scheduleJob(rulePump_Off, function(){
  console.log('Aquarium Pump - ' + new Date() + ' Filter pump turned off');
  pump.writeSync(OFF);
});

console.log('Aquarium Lights - Jobs Scheduled');

//process.on('SIGINT', function (){
  //light1.unexport();
  //light2.unexport();
//});
<|endoftext|>


<commit_before>/*
 *	Date: 2015-05-23
 */

var captureCallback = {};

var ErrorCode = {

    CaptureError.CAPTURE_INTERNAL_ERR: "The camera or microphone failed to capture image or sound.",
    CaptureError.CAPTURE_APPLICATION_BUSY: "The camera or audio capture application is currently serving another capture request.",
    CaptureError.CAPTURE_INVALID_ARGUMENT: "Invalid use of the API (e.g., the value of limit is less than one).",
    CaptureError.CAPTURE_NO_MEDIA_FILES: "The user exits the camera or audio capture application before capturing anything.",
    CaptureError.CAPTURE_NOT_SUPPORTED: "The requested capture operation is not supported."
}

	function captureSuccess(mediaFiles) {
		captureCallback(mediaFiles[0]);
/*        var i, len;
        for (i = 0, len = mediaFiles.length; i < len; i += 1) {
            uploadFile(mediaFiles[i]);
        }
*/
    }

    // Called if something bad happens.
    //
    function captureError(error) {
		alert(ErrorCode[error.code]);
/*        var msg = 'An error occurred during capture: ' + error.code;
        navigator.notification.alert(msg, null, 'Uh oh!');
*/
    }

    // A button will call this function
    //
    function captureVideo(callback) {
		captureCallback = callback;
        // Launch device video recording application,
        // allowing user to capture 1 video clips
        navigator.device.capture.captureVideo(captureSuccess, captureError, {limit: 1});
    }
<commit_msg>change array type<commit_after>/*
 *	Date: 2015-05-23
 */

var captureCallback = {};

var ErrorCode = [
"The camera or microphone failed to capture image or sound.",
"The camera or audio capture application is currently serving another capture request.",
"Invalid use of the API (e.g., the value of limit is less than one).",
"The user exits the camera or audio capture application before capturing anything.",
"The requested capture operation is not supported."
];

	function captureSuccess(mediaFiles) {
		captureCallback(mediaFiles[0]);
/*        var i, len;
        for (i = 0, len = mediaFiles.length; i < len; i += 1) {
            uploadFile(mediaFiles[i]);
        }
*/
    }

    // Called if something bad happens.
    //
    function captureError(error) {
		alert(ErrorCode[error.code]);
/*        var msg = 'An error occurred during capture: ' + error.code;
        navigator.notification.alert(msg, null, 'Uh oh!');
*/
    }

    // A button will call this function
    //
    function captureVideo(callback) {
		captureCallback = callback;
        // Launch device video recording application,
        // allowing user to capture 1 video clips
        navigator.device.capture.captureVideo(captureSuccess, captureError, {limit: 1});
    }
<|endoftext|>


<commit_before>'use strict';
const os = require('os');

const nameMap = {
	17: 'High Sierra',
	16: 'Sierra',
	15: 'El Capitan',
	14: 'Yosemite',
	13: 'Mavericks',
	12: 'Mountain Lion',
	11: 'Lion',
	10: 'Snow Leopard',
	9: 'Leopard',
	8: 'Tiger',
	7: 'Panther',
	6: 'Jaguar',
	5: 'Puma'
};

module.exports = release => {
	release = (release || os.release()).split('.')[0];
	return {
		name: nameMap[release],
		version: '10.' + (Number(release) - 4)
	};
};
<commit_msg>Add macOS 10.14<commit_after>'use strict';
const os = require('os');

const nameMap = {
	18: 'Mojave',
	17: 'High Sierra',
	16: 'Sierra',
	15: 'El Capitan',
	14: 'Yosemite',
	13: 'Mavericks',
	12: 'Mountain Lion',
	11: 'Lion',
	10: 'Snow Leopard',
	9: 'Leopard',
	8: 'Tiger',
	7: 'Panther',
	6: 'Jaguar',
	5: 'Puma'
};

module.exports = release => {
	release = (release || os.release()).split('.')[0];
	return {
		name: nameMap[release],
		version: '10.' + (Number(release) - 4)
	};
};
<|endoftext|>


<commit_before>export default class {
  constructor (win, keys) {
    this.keys = keys
    this.win = win
    this.id = 'gamepad-key'

    this.buttons = []
    for (var key in this.keys) {
      this.buttons[this.keys[key]] = {pressed: false}
    }

    this.onkey = function (event) {
      if (event.which in this.keys) {
        let pressed
        if (event.type === 'keyup') {
          pressed = true
        } else if (event.type === 'keydown') {
          pressed = false
        }
        this.buttons[this.keys[event.which]].pressed = pressed
        this.timestamp = event.timeStamp
        event.preventDefault()
      }
    }.bind(this)

    this.connect()
  }

  connect () {
    this.connected = true
    this.win.addEventListener('keydown', this.onkey)
    this.win.addEventListener('keyup', this.onkey)
  }

  disconnect () {
    this.connected = false
    this.win.removeEventListener('keydown', this.onkey)
    this.win.removeEventListener('keyup', this.onkey)
  }
}
<commit_msg>Change id.<commit_after>export default class {
  constructor (win, keys) {
    this.keys = keys
    this.win = win
    this.id = 'keypad'

    this.buttons = []
    for (var key in this.keys) {
      this.buttons[this.keys[key]] = {pressed: false}
    }

    this.onkey = function (event) {
      if (event.which in this.keys) {
        let pressed
        if (event.type === 'keyup') {
          pressed = true
        } else if (event.type === 'keydown') {
          pressed = false
        }
        this.buttons[this.keys[event.which]].pressed = pressed
        this.timestamp = event.timeStamp
        event.preventDefault()
      }
    }.bind(this)

    this.connect()
  }

  connect () {
    this.connected = true
    this.win.addEventListener('keydown', this.onkey)
    this.win.addEventListener('keyup', this.onkey)
  }

  disconnect () {
    this.connected = false
    this.win.removeEventListener('keydown', this.onkey)
    this.win.removeEventListener('keyup', this.onkey)
  }
}
<|endoftext|>


<commit_before>var Promise = require('bluebird');
var git = require('nodegit');
var moment = require('moment');
var _ = require('lodash');

var config = {
    // Maximum time diff between 2 subsequent commits in minutes which are
    // counted to be in the same coding "session"
    maxCommitDiffInMinutes: 240,

    // How many minutes should be added for the first commit of coding session
    firstCommitAdditionInMinutes: 120
}

function main() {
    commits('.').then(function(commits) {
        var work = {
            total: {
                hours: estimateHours(_.pluck(commits, 'date')),
                commits: commits.length
            }
        };

        console.log(JSON.stringify(work, undefined, 2));
    }).catch(function(e) {
        console.error(e.stack);
    });
}

// Estimates spent working hours based on commit dates
function estimateHours(dates) {
    if (dates.length < 2) {
        return 0;
    }

    // Oldest commit first, newest last
    var sortedDates = dates.sort().reverse();
    var hours = _.reduce(dates, function(hours, date, index) {
        var previousDate = dates[index - 1];
        var diffInMinutes = (date - previousDate) / 1000 / 60;

        // Check if commits are counted to be in same coding session
        if (diffInMinutes < config.maxCommitDiffInMinutes) {
            return hours + (diffInMinutes / 60);
        }

        // The date difference is too big to be inside single coding session
        // The work of first commit of a session cannot be seen in git history,
        // so we make a blunt estimate of it
        return hours + (config.firstCommitAdditionInMinutes / 60);
    }, 0);

    return Math.round(hours);
}

// Promisify nodegit's API of getting all commits in repository
function commits(gitPath) {
    return new Promise(function(resolve, reject) {
        git.Repo.open(gitPath, function(err, repo) {
            if (err) {
                reject(err);
                return;
            }

            repo.getMaster(function(err, branch) {
                if (err) {
                    reject(err);
                    return;
                }

                var history = branch.history();
                var commits = [];

                history.on("commit", function(commit) {
                    var commitData = {
                        sha: commit.sha(),
                        date: commit.date(),
                        message: commit.message(),
                        author: {
                            name: commit.author().name(),
                            email: commit.author().email()
                        }
                    }

                    commits.push(commitData);
                });

                history.on("end", function() {
                    resolve(commits);
                });

                // Start emitting events.
                history.start();
            });
        });
    });
}

main();
<commit_msg>Fix lint errors<commit_after>var Promise = require('bluebird');
var git = require('nodegit');
var moment = require('moment');
var _ = require('lodash');

var config = {
    // Maximum time diff between 2 subsequent commits in minutes which are
    // counted to be in the same coding "session"
    maxCommitDiffInMinutes: 240,

    // How many minutes should be added for the first commit of coding session
    firstCommitAdditionInMinutes: 120
};

function main() {
    commits('.').then(function(commits) {
        var work = {
            total: {
                hours: estimateHours(_.pluck(commits, 'date')),
                commits: commits.length
            }
        };

        console.log(JSON.stringify(work, undefined, 2));
    }).catch(function(e) {
        console.error(e.stack);
    });
}

// Estimates spent working hours based on commit dates
function estimateHours(dates) {
    if (dates.length < 2) {
        return 0;
    }

    // Oldest commit first, newest last
    var sortedDates = dates.sort().reverse();
    var hours = _.reduce(dates, function(hours, date, index) {
        var previousDate = dates[index - 1];
        var diffInMinutes = (date - previousDate) / 1000 / 60;

        // Check if commits are counted to be in same coding session
        if (diffInMinutes < config.maxCommitDiffInMinutes) {
            return hours + (diffInMinutes / 60);
        }

        // The date difference is too big to be inside single coding session
        // The work of first commit of a session cannot be seen in git history,
        // so we make a blunt estimate of it
        return hours + (config.firstCommitAdditionInMinutes / 60);
    }, 0);

    return Math.round(hours);
}

// Promisify nodegit's API of getting all commits in repository
function commits(gitPath) {
    return new Promise(function(resolve, reject) {
        git.Repo.open(gitPath, function(err, repo) {
            if (err) {
                reject(err);
                return;
            }

            repo.getMaster(function(err, branch) {
                if (err) {
                    reject(err);
                    return;
                }

                var history = branch.history();
                var commits = [];

                history.on("commit", function(commit) {
                    var commitData = {
                        sha: commit.sha(),
                        date: commit.date(),
                        message: commit.message(),
                        author: {
                            name: commit.author().name(),
                            email: commit.author().email()
                        }
                    };

                    commits.push(commitData);
                });

                history.on("end", function() {
                    resolve(commits);
                });

                // Start emitting events.
                history.start();
            });
        });
    });
}

main();
<|endoftext|>


<commit_before>module.exports = wrap
wrap.runMain = runMain

var Module = require('module')
var fs = require('fs')
var cp = require('child_process')
var ChildProcess = cp.ChildProcess
var assert = require('assert')
var crypto = require('crypto')
var mkdirp = require('mkdirp')
var rimraf = require('rimraf')
var path = require('path')
var signalExit = require('signal-exit')
var homedir = require('os-homedir')() + '/.node-spawn-wrap-'
var winRebase = require('./lib/win-rebase')
var which = require('which')

var cmdname = path.basename(process.execPath, '.exe')

var shim = '#!' + process.execPath + '\n' +
  fs.readFileSync(__dirname + '/shim.js')

var isWindows = require('./lib/is-windows')()

var pathRe = /^PATH=/
if (isWindows) pathRe = /^PATH=/i

var colon = isWindows ? ';' : ':'

function wrap (argv, env, workingDir) {
  if (!ChildProcess) {
    var child = cp.spawn(process.execPath, [])
    ChildProcess = child.constructor
    child.kill('SIGKILL')
  }

  // spawn_sync available since Node v0.11
  var spawnSyncBinding, spawnSync
  try {
    spawnSyncBinding = process.binding('spawn_sync')
  } catch (e) {}

  // if we're passed in the working dir, then it means that setup
  // was already done, so no need.
  var doSetup = !workingDir
  if (doSetup) {
    workingDir = setup(argv, env)
  }
  var spawn = ChildProcess.prototype.spawn
  if (spawnSyncBinding) {
    spawnSync = spawnSyncBinding.spawn
  }

  function unwrap () {
    if (doSetup) {
      rimraf.sync(workingDir)
    }
    ChildProcess.prototype.spawn = spawn
    if (spawnSyncBinding) {
      spawnSync = spawnSyncBinding.spawn
    }
  }

  if (spawnSyncBinding) {
    spawnSyncBinding.spawn = wrappedSpawnFunction(spawnSync, workingDir)
  }
  ChildProcess.prototype.spawn = wrappedSpawnFunction(spawn, workingDir)

  return unwrap
}

function wrappedSpawnFunction (fn, workingDir) {
  return wrappedSpawn

  function wrappedSpawn (options) {
    var pathEnv
    var cmdi, c, re, match, exe

    // handle case where node/iojs is exec'd
    // this doesn't handle EVERYTHING, but just the most common
    // case of doing `exec(process.execPath + ' file.js')
    var file = path.basename(options.file, '.exe')
    if (file === 'dash' ||
        file === 'sh' ||
        file === 'bash' ||
        file === 'zsh') {
      cmdi = options.args.indexOf('-c')
      if (cmdi !== -1) {
        c = options.args[cmdi + 1]
        re = /^\s*((?:[^\= ]*\=[^\=\s]*\s*)*)([^\s]+)/
        match = c.match(re)
        if (match) {
          exe = path.basename(match[2])
          if (exe === 'iojs' ||
              exe === 'node' ||
              exe === cmdname) {
            c = c.replace(re, '$1 ' + workingDir + '/node')
            options.args[cmdi + 1] = c
          } else if (exe === 'npm' && !isWindows) {
            var npmPath = whichOrUndefined('npm')

            if (npmPath) {
              c = c.replace(re, '$1 ' + workingDir + '/node ' + npmPath)
              options.args[cmdi + 1] = c
            }
          }
        }
      }
    } else if (isWindows && (
        file === path.basename(process.env.comspec) ||
        file === 'cmd'
      )) {
      cmdi = options.args.indexOf('/c')
      if (cmdi !== -1) {
        options.args[cmdi + 1] = winRebase(options.args[cmdi + 1], workingDir + '/node.cmd')
      }
    } else if (file === 'node' || file === 'iojs' || cmdname === file) {
      // make sure it has a main script.
      // otherwise, just let it through.
      var a = 0
      var hasMain = false
      for (var a = 1; !hasMain && a < options.args.length; a++) {
        switch (options.args[a]) {
          case '-i':
          case '--interactive':
          case '--eval':
          case '-e':
          case '-pe':
            hasMain = false
            a = options.args.length
            continue

          case '-r':
          case '--require':
            a += 1
            continue

          default:
            if (options.args[a].match(/^-/)) {
              continue
            } else {
              hasMain = true
              a = options.args.length
              break
            }
        }
      }

      if (hasMain) {
        options.file = workingDir + '/' + file
        options.args[0] = workingDir + '/' + file
      }

    } else {
      try {
        var resolved = which.sync(options.file)
      } catch (er) {}
      if (resolved) {
        var shebang = fs.readFileSync(resolved, 'utf8')
        var match = shebang.match(/^#!([^\r\n]+)/)
        if (match) {
          var shebangbin = match[1].split(' ')[0]
          var maybeNode = path.basename(shebangbin)
          if (maybeNode === 'node' || maybeNode === 'iojs' || cmdname === maybeNode) {

            options.file = shebangbin
            options.args = [shebangbin, workingDir + '/' + maybeNode]
              .concat(resolved)
              .concat(match[1].split(' ').slice(1))
              .concat(options.args)
          }
        }
      }
    }

    for (var i = 0; i < options.envPairs.length; i++) {
      var ep = options.envPairs[i]
      if (ep.match(pathRe)) {
        pathEnv = ep.substr(5)
        var k = ep.substr(0, 5)
        options.envPairs[i] = k + workingDir + colon + pathEnv
      }
    }
    if (!pathEnv) {
      options.envPairs.push((isWindows ? 'Path=' : 'PATH=') + workingDir)
    }

    if (file === 'npm' && !isWindows) {
      var npmPath = whichOrUndefined('npm')

      if (npmPath) {
        options.args[0] = npmPath

        options.file = workingDir + '/node'
        options.args.unshift(workingDir + '/node')
      }
    }

    if (isWindows) fixWindowsBins(workingDir, options)

    return fn.call(this, options)
  }
}

function whichOrUndefined (executable) {
  var path
  try {
    path = which.sync(executable)
  } catch (er) {}
  return path
}

// by default Windows will reference the full
// path to the node.exe or iojs.exe as the bin,
// we should instead point spawn() at our .cmd shim.
function fixWindowsBins (workingDir, options) {
  var re = /.*\b(node|iojs)(\.exe)?$/
  if (options.file.match(re)) {
    options.file = process.execPath
    var shim = workingDir + '/node'
    options.args.splice(0, 1, options.file, workingDir + '/node')
  }
}

function setup (argv, env) {
  if (argv && typeof argv === 'object' && !env && !Array.isArray(argv)) {
    env = argv
    argv = []
  }

  if (!argv && !env) {
    throw new Error('at least one of "argv" and "env" required')
  }

  if (argv) {
    assert(Array.isArray(argv), 'argv must be array')
  } else {
    argv = []
  }

  if (env) {
    assert(typeof env === 'object', 'env must be an object')
  } else {
    env = {}
  }

  // For stuff like --use_strict or --harmony, we need to inject
  // the argument *before* the wrap-main.
  var execArgv = []
  for (var i = 0; i < argv.length; i++) {
    if (argv[i].match(/^-/)) {
      execArgv.push(argv[i])
      if (argv[i] === '-r' || argv[i] === '--require') {
        execArgv.push(argv[++i])
      }
    } else {
      break
    }
  }
  if (execArgv.length) {
    if (execArgv.length === argv.length) {
      argv.length = 0
    } else {
      argv = argv.slice(execArgv.length)
    }
  }

  var settings = JSON.stringify({
    module: __filename,
    deps: {
      foregroundChild: require.resolve('foreground-child'),
      signalExit: require.resolve('signal-exit'),
    },
    argv: argv,
    execArgv: execArgv,
    env: env,
    root: process.pid
  }, null, 2) + '\n'

  var workingDir = homedir + process.pid + '-' +
    crypto.randomBytes(6).toString('hex')

  signalExit(function () {
    rimraf.sync(workingDir)
  })

  mkdirp.sync(workingDir)
  workingDir = fs.realpathSync(workingDir)
  if (isWindows) {
    var cmdShim =
      '@echo off\r\n' +
      'SETLOCAL\r\n' +
      'SET PATHEXT=%PATHEXT:;.JS;=;%\r\n' +
      '"' + process.execPath + '"' + ' "%~dp0\\.\\node" %*\r\n'

    fs.writeFileSync(workingDir + '/node.cmd', cmdShim)
    fs.chmodSync(workingDir + '/node.cmd', '0755')
    fs.writeFileSync(workingDir + '/iojs.cmd', cmdShim)
    fs.chmodSync(workingDir + '/iojs.cmd', '0755')
  }
  fs.writeFileSync(workingDir + '/node', shim)
  fs.chmodSync(workingDir + '/node', '0755')
  fs.writeFileSync(workingDir + '/iojs', shim)
  fs.chmodSync(workingDir + '/iojs', '0755')
  if (cmdname !== 'iojs' && cmdname !== 'node') {
    fs.writeFileSync(workingDir + '/' + cmdname, shim)
    fs.chmodSync(workingDir + '/' + cmdname, '0755')
  }
  fs.writeFileSync(workingDir + '/settings.json', settings)

  return workingDir
}

function runMain () {
  process.argv.splice(1, 1)
  process.argv[1] = path.resolve(process.argv[1])
  Module.runMain()
}
<commit_msg>Fixups for the recent shebang changes<commit_after>module.exports = wrap
wrap.runMain = runMain

var Module = require('module')
var fs = require('fs')
var cp = require('child_process')
var ChildProcess = cp.ChildProcess
var assert = require('assert')
var crypto = require('crypto')
var mkdirp = require('mkdirp')
var rimraf = require('rimraf')
var path = require('path')
var signalExit = require('signal-exit')
var homedir = require('os-homedir')() + '/.node-spawn-wrap-'
var winRebase = require('./lib/win-rebase')
var which = require('which')

var cmdname = path.basename(process.execPath, '.exe')

var shim = '#!' + process.execPath + '\n' +
  fs.readFileSync(__dirname + '/shim.js')

var isWindows = require('./lib/is-windows')()

var pathRe = /^PATH=/
if (isWindows) pathRe = /^PATH=/i

var colon = isWindows ? ';' : ':'

function wrap (argv, env, workingDir) {
  if (!ChildProcess) {
    var child = cp.spawn(process.execPath, [])
    ChildProcess = child.constructor
    child.kill('SIGKILL')
  }

  // spawn_sync available since Node v0.11
  var spawnSyncBinding, spawnSync
  try {
    spawnSyncBinding = process.binding('spawn_sync')
  } catch (e) {}

  // if we're passed in the working dir, then it means that setup
  // was already done, so no need.
  var doSetup = !workingDir
  if (doSetup) {
    workingDir = setup(argv, env)
  }
  var spawn = ChildProcess.prototype.spawn
  if (spawnSyncBinding) {
    spawnSync = spawnSyncBinding.spawn
  }

  function unwrap () {
    if (doSetup) {
      rimraf.sync(workingDir)
    }
    ChildProcess.prototype.spawn = spawn
    if (spawnSyncBinding) {
      spawnSync = spawnSyncBinding.spawn
    }
  }

  if (spawnSyncBinding) {
    spawnSyncBinding.spawn = wrappedSpawnFunction(spawnSync, workingDir)
  }
  ChildProcess.prototype.spawn = wrappedSpawnFunction(spawn, workingDir)

  return unwrap
}

function wrappedSpawnFunction (fn, workingDir) {
  return wrappedSpawn

  function wrappedSpawn (options) {
    var pathEnv
    var cmdi, c, re, match, exe

    // handle case where node/iojs is exec'd
    // this doesn't handle EVERYTHING, but just the most common
    // case of doing `exec(process.execPath + ' file.js')
    var file = path.basename(options.file, '.exe')
    if (file === 'dash' ||
        file === 'sh' ||
        file === 'bash' ||
        file === 'zsh') {
      cmdi = options.args.indexOf('-c')
      if (cmdi !== -1) {
        c = options.args[cmdi + 1]
        re = /^\s*((?:[^\= ]*\=[^\=\s]*\s*)*)([^\s]+)/
        match = c.match(re)
        if (match) {
          exe = path.basename(match[2])
          if (exe === 'iojs' ||
              exe === 'node' ||
              exe === cmdname) {
            c = c.replace(re, '$1 ' + workingDir + '/node')
            options.args[cmdi + 1] = c
          } else if (exe === 'npm' && !isWindows) {
            var npmPath = whichOrUndefined('npm')

            if (npmPath) {
              c = c.replace(re, '$1 ' + workingDir + '/node ' + npmPath)
              options.args[cmdi + 1] = c
            }
          }
        }
      }
    } else if (isWindows && (
        file === path.basename(process.env.comspec) ||
        file === 'cmd'
      )) {
      cmdi = options.args.indexOf('/c')
      if (cmdi !== -1) {
        options.args[cmdi + 1] = winRebase(options.args[cmdi + 1], workingDir + '/node.cmd')
      }
    } else if (file === 'node' || file === 'iojs' || cmdname === file) {
      // make sure it has a main script.
      // otherwise, just let it through.
      var a = 0
      var hasMain = false
      for (var a = 1; !hasMain && a < options.args.length; a++) {
        switch (options.args[a]) {
          case '-i':
          case '--interactive':
          case '--eval':
          case '-e':
          case '-pe':
            hasMain = false
            a = options.args.length
            continue

          case '-r':
          case '--require':
            a += 1
            continue

          default:
            if (options.args[a].match(/^-/)) {
              continue
            } else {
              hasMain = true
              a = options.args.length
              break
            }
        }
      }

      if (hasMain) {
        options.file = workingDir + '/' + file
        options.args[0] = workingDir + '/' + file
      }

    } else {
      try {
        var resolved = which.sync(options.file)
      } catch (er) {}
      if (resolved) {
        var shebang = fs.readFileSync(resolved, 'utf8')
        var match = shebang.match(/^#!([^\r\n]+)/)
        if (match) {
          var shebangbin = match[1].split(' ')[0]
          var maybeNode = path.basename(shebangbin)
          if (maybeNode === 'node' || maybeNode === 'iojs' || cmdname === maybeNode) {
            file = options.file = shebangbin
            options.args = [shebangbin, workingDir + '/' + maybeNode]
              .concat(resolved)
              .concat(match[1].split(' ').slice(1))
              .concat(options.args.slice(1))
          }
        }
      }
    }

    for (var i = 0; i < options.envPairs.length; i++) {
      var ep = options.envPairs[i]
      if (ep.match(pathRe)) {
        pathEnv = ep.substr(5)
        var k = ep.substr(0, 5)
        options.envPairs[i] = k + workingDir + colon + pathEnv
      }
    }
    if (!pathEnv) {
      options.envPairs.push((isWindows ? 'Path=' : 'PATH=') + workingDir)
    }

    if (file === 'npm' && !isWindows) {
      var npmPath = whichOrUndefined('npm')

      if (npmPath) {
        options.args[0] = npmPath

        options.file = workingDir + '/node'
        options.args.unshift(workingDir + '/node')
      }
    }

    if (isWindows) fixWindowsBins(workingDir, options)

    return fn.call(this, options)
  }
}

function whichOrUndefined (executable) {
  var path
  try {
    path = which.sync(executable)
  } catch (er) {}
  return path
}

// by default Windows will reference the full
// path to the node.exe or iojs.exe as the bin,
// we should instead point spawn() at our .cmd shim.
function fixWindowsBins (workingDir, options) {
  var re = /.*\b(node|iojs)(\.exe)?$/
  if (options.file.match(re)) {
    options.file = process.execPath
    var shim = workingDir + '/node'
    options.args.splice(0, 1, options.file, workingDir + '/node')
  }
}

function setup (argv, env) {
  if (argv && typeof argv === 'object' && !env && !Array.isArray(argv)) {
    env = argv
    argv = []
  }

  if (!argv && !env) {
    throw new Error('at least one of "argv" and "env" required')
  }

  if (argv) {
    assert(Array.isArray(argv), 'argv must be array')
  } else {
    argv = []
  }

  if (env) {
    assert(typeof env === 'object', 'env must be an object')
  } else {
    env = {}
  }

  // For stuff like --use_strict or --harmony, we need to inject
  // the argument *before* the wrap-main.
  var execArgv = []
  for (var i = 0; i < argv.length; i++) {
    if (argv[i].match(/^-/)) {
      execArgv.push(argv[i])
      if (argv[i] === '-r' || argv[i] === '--require') {
        execArgv.push(argv[++i])
      }
    } else {
      break
    }
  }
  if (execArgv.length) {
    if (execArgv.length === argv.length) {
      argv.length = 0
    } else {
      argv = argv.slice(execArgv.length)
    }
  }

  var settings = JSON.stringify({
    module: __filename,
    deps: {
      foregroundChild: require.resolve('foreground-child'),
      signalExit: require.resolve('signal-exit'),
    },
    argv: argv,
    execArgv: execArgv,
    env: env,
    root: process.pid
  }, null, 2) + '\n'

  var workingDir = homedir + process.pid + '-' +
    crypto.randomBytes(6).toString('hex')

  signalExit(function () {
    rimraf.sync(workingDir)
  })

  mkdirp.sync(workingDir)
  workingDir = fs.realpathSync(workingDir)
  if (isWindows) {
    var cmdShim =
      '@echo off\r\n' +
      'SETLOCAL\r\n' +
      'SET PATHEXT=%PATHEXT:;.JS;=;%\r\n' +
      '"' + process.execPath + '"' + ' "%~dp0\\.\\node" %*\r\n'

    fs.writeFileSync(workingDir + '/node.cmd', cmdShim)
    fs.chmodSync(workingDir + '/node.cmd', '0755')
    fs.writeFileSync(workingDir + '/iojs.cmd', cmdShim)
    fs.chmodSync(workingDir + '/iojs.cmd', '0755')
  }
  fs.writeFileSync(workingDir + '/node', shim)
  fs.chmodSync(workingDir + '/node', '0755')
  fs.writeFileSync(workingDir + '/iojs', shim)
  fs.chmodSync(workingDir + '/iojs', '0755')
  if (cmdname !== 'iojs' && cmdname !== 'node') {
    fs.writeFileSync(workingDir + '/' + cmdname, shim)
    fs.chmodSync(workingDir + '/' + cmdname, '0755')
  }
  fs.writeFileSync(workingDir + '/settings.json', settings)

  return workingDir
}

function runMain () {
  process.argv.splice(1, 1)
  process.argv[1] = path.resolve(process.argv[1])
  Module.runMain()
}
<|endoftext|>


<commit_before>require('coffee-script');
require('coffee-script/register');
var server = require('./server');
server.startServer();
<commit_msg>Have index.js check node version is >= 4 before continuing, for #3495<commit_after>var majorVersion = parseInt(process.versions.node.split('.')[0]);
if (majorVersion < 4) {
  console.error('Server requires Node v4 or higher. Your version:', process.version);
  process.exit(1);
}
if (majorVersion === 4) {
  console.warn('WARNING: You are using Node v4. Please upgrade to Node v5. Your version:', process.versions.node);
}
require('coffee-script');
require('coffee-script/register');
var server = require('./server');
server.startServer();
<|endoftext|>


<commit_before>$(function() {
    $('#carousel-example-generic').height($(window).height()-$('#panel-title').height());
});

$(window).resize(function(){
    $('#carousel-example-generic').height($(window).height()-$('#panel-title').height());
});<commit_msg>Add logic to handle vertical screens<commit_after>function setCarouselSize() {
    var wWidth = $(window).width();
    var wHeight = $(window).height();

    if (wHeight > wWidth) {
        var containerHeight = wHeight * $('.img-cartoon').width() / wWidth;
    } else {
        $('#carousel-example-generic').height($(window).height()-$('#panel-title').height());
    }
}

$(function() {
    setCarouselSize();
});

$(window).resize(function(){
    setCarouselSize();
});<|endoftext|>


<commit_before>var through = require('through2'),
	gutil   = require('gulp-util'),
	fs      = require('fs'),
	path    = require('path'),
	imports = [],
	appRoot = path.dirname(module.parent.filename);

const PLUGIN_NAME = 'gulp-importjs';

function importStream(content) {
	var stream = through();
	stream.write(content);
	return stream;
}

function importJS(appDir) {

	// Allow passing of a new app root
	if(typeof appDir === 'string'){
		appRoot = appDir;
	}

	var stream = through.obj(function(file, enc, callback) {

		// Reset the imports object
		imports = [];

		if (file.isNull()) {
			// Do nothing
		}

		if (file.isBuffer()) {
			file.contents = new Buffer(replaceImports(file.contents.toString()));
		}

		if (file.isStream()) {
			file.contents = file.contents.pipe(importStream(new Buffer(replaceImports(file.contents.toString()))));
		}

		this.push(file);
		return callback();
	});

	return stream;
}

var re = /^@import [\'\"](.+)[\'\"];$/mi;

function replaceImports(content) {

	while ((match = re.exec(content)) !== null) {

		var fileName = appRoot + match[1];
		var match    = match[0].toString();

		// Check if the file we're trying to import exists
		if (fs.existsSync(fileName)) {

			// Check if the file was already imported somewhere
			if (imports.indexOf(fileName) === -1) {

				// Add the file to the imports list
				imports.push(fileName);

				// Read the imported file
				// *** Replace dollar signs so submatches don't get replaced
				importContents = fs.readFileSync(fileName, 'utf8').replace(/\$/g, '$$$$');

				// Recursively import files
				importContents = replaceImports(importContents);

				// Place the imported content into the file
				content = content.replace(re, importContents + "\n", "mi");
			}

			// The file was already imported, comment out the line
			else {
				content = content.replace(re, "// Already included: " + fileName + "\n");
			}

		}

		// The file does not exist, print out the error
		else {
			content = content.replace(re, "// Import file does not exist: " + fileName + "\n");
		}

	}

	return content;
}

module.exports = importJS;<commit_msg>Now throws gutil error on file not found error; also imports file even with whitespace after<commit_after>var through = require('through2'),
	gutil   = require('gulp-util'),
	fs      = require('fs'),
	path    = require('path'),
	imports = [],
	PluginError = gutil.PluginError,
	appRoot = path.dirname(module.parent.filename);

const PLUGIN_NAME = 'gulp-importjs';

function importStream(content) {
	var stream = through();
	stream.write(content);
	return stream;
}

function importJS(appDir) {
	// Allow passing of a new app root
	if(typeof appDir === 'string'){
		appRoot = appDir;
	}

	var stream = through.obj(function(file, enc, callback) {
		// Reset the imports object
		imports = [];

		if (file.isNull()) {
			// Do nothing
		}
		var compiled = null;
		if (file.isBuffer()) {
			compiled = replaceImports(file.contents.toString());
			if (compiled.err) {
				return callback(compiled.err);
			}
			file.contents = new Buffer(compiled.result);
		}

		if (file.isStream()) {
			compiled = replaceImports(file.contents.toString());
			if (compiled.err) {
				return callback(compiled.err);
			}
			file.contents = file.contents.pipe(importStream(new Buffer(compiled.result)));
		}

		this.push(file);
		return callback();
	});

	return stream;
}

//group - escaped tic, escaped quote, then anything, then escaped tic or escaped quote, then semicolon, then (optional) whitespace
var re = /^@import [\'\"](.+)[\'\"];[\s]*$/mi;

/**
 * @return {Object}         2 properties : err (optional) and result
 */
function replaceImports(content) {
	var err = null;
	while ((match = re.exec(content)) !== null) {
		match = match.map(function (argument) {
			return argument.trim();
		});
		var fileName = appRoot + match[1].trim();
		var match    = match[0].toString();
		// Check if the file we're trying to import exists
		if (fs.existsSync(fileName)) {
			// Check if the file was already imported somewhere
			if (imports.indexOf(fileName) === -1) {

				// Add the file to the imports list
				imports.push(fileName);

				// Read the imported file
				// *** Replace dollar signs so submatches don't get replaced
				importContents = fs.readFileSync(fileName, 'utf8').replace(/\$/g, '$$$$');

				// Recursively import files
				var recursiveResults = replaceImports(importContents);
				if (recursiveResults.err) {
					err = recursiveResults.err;
					break;
				}
				importContents = recursiveResults.result; //replaceImports(importContents);

				// Place the imported content into the file
				content = content.replace(re, importContents + "\n", "mi");
			}

			// The file was already imported, comment out the line
			else {
				content = content.replace(re, "// Already included: " + fileName + "\n");
			}

		}

		// The file does not exist, print out the error
		else {
			content = content.replace(re, "// Import file does not exist: " + fileName + "\n");
			err = new PluginError('gulp-importjs', ' Import file does not exist: ' + fileName + '\n');
			break;
		}

	}
	return {
		result 	: content,
		err 	: err
	};
}

module.exports = importJS;<|endoftext|>


<commit_before>'use strict'
/**
 * i18n-light object.
 * @type {Object}
 */
var i18n = {}

/**
 * method used to initialize all instance variables.
 * a.k.a the excuse to document instance variables.
 * @return {i18n}   the instance.
 */
i18n._init = function _init () {
  /**
   * i18n-light version.
   * @type {String}
   */
  this.version = '0.5.2'

  /**
   * indicates whether i18n-light should fallback to the defaultLocale if a
   * dictionary path isn't found.
   * @type {Boolean}
   */
  this._fallback = true

  /**
   * indicates whether i18n-light should keep old dictionary contexts once the
   * current locale is changed.
   * @type {Boolean}
   */
  this._cache = true

  /**
   * indicates whether i18n-light should override existant dictionary contexts
   * or not when a locale changes.
   * @type {Boolean}
   */
  this._refresh = false

  /**
   * the dictionaries files extension.
   * @type {String}
   */
  this._extension = '.js'

  /**
   * this is the locale which i18n-light will fallback if the provided
   * dictionary path isn't found on the current locale dictionary.
   * @type {String}
   */
  this._defaultLocale = null

  /**
   * this is the directory where i18n-light will be searching dictionaries from.
   * @type {String}
   */
  this._dir = null

  /**
   * object which i18n-light will be using to store locale dictionaries
   * contexts.
   * @type {Object}
   */
  this._context = {}

  /**
   * the current locale.
   * @type {String}
   */
  this._currentLocale = null

  /**
   * custom resolver for dictionary contexts. this function is only used by
   * i18n-light if the instance is not configured with `dir` or `context` and
   * is used when i18n-light needs a dictionary context for a locale. i18n-light
   * passes the locale name as an argument and waits for json.
   * @type {Object}
   */
  this._resolve = null

  return this
}

/**
 * method used to intialize the i18n-light instance. can be considered as the
 * object constructor.
 * @param  {Object}   opts    configuration object.
 * @return {i18n}     the instance.
 */
i18n.configure = function configure (opts) {
  this._init()

  this._fallback = (opts.fallback !== undefined)
    ? opts.fallback : this._fallback

  this._cache = (opts.cache !== undefined)
    ? opts.cache : this._cache

  this._refresh = (opts.refresh !== undefined)
    ? opts.refresh : this._refresh

  this._extension =
    this._tidyExtension((opts.extension || this._extension))

  if (opts.defaultLocale) {
    this._defaultLocale = opts.defaultLocale
  } else {
    throw new Error('Please provide a default locale which i18n-light will ' +
      'fallback using the \'defaultLocale\' attribute.')
  }

  if (opts.dir) {
    this._dir = this._tidyDir(opts.dir)
  } else if (opts.context) {
    this._context = opts.context
  } else if (opts.resolve) {
    this._resolve = opts.resolve
  } else {
    throw new Error('Please provide the directory where your dictionaries ' +
      'are located using the \'dir\' attribute or the dictionary context ' +
      'itself using \'context\'')
  }

  this.resetLocale()
  return this
}

/**
 * method used to format the extension string into a valid extension. this is
 * done by including a '.' if the extension string isn't already prefixed with
 * one.
 * @param {String}    extension   an extension prefixed with '.'
 */
i18n._tidyExtension = function _tidyExtension (extension) {
  if (extension[0] !== '.') extension = '.' + extension
  return extension
}

/**
 * method used to make sure that the 'dir' path has a trailing '/'.
 * @param  {String} path the path to be given to 'dir'.
 * @return {String}      a path ending with a '/'.
 */
i18n._tidyDir = function _tidyDir (path) {
  if (path[path.length - 1] !== '/') path += '/'
  return path
}

/**
 * i18n-light middleware function.
 * @return {Function}     middleware
 */
i18n.init = function init () {
  var self = this
  return function (req, res, next) {
    self.resetLocale()
    res.i18n = self
    res.locals.i18n = self
    next()
  }
}

/**
 * method used to reset the current locale back to the default locale.
 * @param {Boolean}   refresh     indicates whether the dictionary context of
 *                                the default locale should be updated or not.
 * @return {i18n}     the instance.
 */
i18n.resetLocale = function resetLocale (refresh) {
  return this.setLocale(this._defaultLocale, refresh)
}

/**
 * method used to change the current locale.
 * @param {String}    locale      the new locale.
 * @param {Boolean}   refresh     indicates whether the dictionary context of
 *                                the current locale should be updated or not.
 * @return {i18n}     the instance
 */
i18n.setLocale = function setLocale (locale, refresh) {
  // change the current locale.
  this._currentLocale = locale

  /*
   * i18n-light should only retrieve the locale dictionary context if:
   *     1. there is no cached dictionary for the new locale.
   *     2. refresh is true.
   *     3. refresh is undefined and this._refresh is true.
   */
  if (!(this.isCached(this._currentLocale))) {
    if (!(this._cache)) {
      // clear cache only if this._cache === false
      this.clearCache()
    }
    // retrieve the current locale's dictionary since it not cached.
    this.refreshContext()
  } else {
    /**
     * indicates whether to refresh the current locale's dictionary context or
     * not. if refresh is not passed i18n-light should fallback to this._refresh
     * @type {Boolean}
     */
    refresh = (refresh !== undefined) ? refresh : this._refresh

    /**
     * object which will contain the dictionary context of the current locale if
     * this._cache === false (i.e. reset this._context) and refresh === false
     * (i.e. keep the current locale dicionary context). this is done because
     * when this.clearCache() is executed, i18n-light completly destroys
     * this._context and thus losing the current locale's context making us
     * unable to restore the locale's dictionary.
     * @type {Object}
     */
    var context = null

    /*
      as stated i18n-light will only keep the current locale's dictionary if
      refresh === false and this.cache === false.
     */
    if (!(refresh) && !(this._cache)) {
      context = this._context[this._currentLocale]
    }

    /*
      once we have the current locale's context we can clear the cache if
      this._cache === false.
     */
    if (!(this._cache)) this.clearCache()

    if (refresh) {
      /*
        if refresh === true, i18n-light will retrieve the updated dictionary
        context.
       */
      this.refreshContext()
    } else if (!(this._cache)) {
      /*
        if user chooses to keep current dictionary context and to clear the
        cache i18n-light will use the 'context' object.
       */
      this._context[this._currentLocale] = context
    }
    /*
      else i18n-light doesn't care because user chose to keep the same
      dictionary context (refresh === false) and not to reset the cache
      (this.cache === true). :D
     */
  }
  return this
}

/**
 * method used to return the current locale i18n-light is using.
 * @return {String}     the current locale.
 */
i18n.getLocale = function getLocale () {
  return this._currentLocale
}

/**
 * method used to change the default locale of an i18n-light instance.
 * @param {i18n} locale   the instance.
 */
i18n.setDefaultLocale = function setDefaultLocale (locale) {
  this._defaultLocale = locale
  return this
}

/**
 * method used to refresh the dictionary context of i18n-light.
 * @param  {String}     locale    the name of the locale which i18n-light will
 *                                update its dictionary context.
 * @return {i18n}       the instance.
 */
i18n.refreshContext = function refreshContext (locale) {
  locale = (typeof locale === 'string') ? locale : this._currentLocale

  if (this._dir) {
    var path = this._dir + locale + this._extension

    this._context[locale] =
      JSON.parse(require('fs').readFileSync(path, 'utf-8'))
  } else if (this._resolve !== null) {
    this._context[locale] = JSON.parse(JSON.stringify(this._resolve(locale)))
  }

  return this
}

/**
 * method used to get the dictionary context of a particular locale.
 * @param  {String}   locale    the locale name.
 * @return {Object}   The dictionary context
 */
i18n._getContext = function _getContext (locale) {
  return this._context[locale]
}

/**
 * method used to clear the context object cached data.
 * @param  {Boolean}    refresh    indicates whether to retrieve the dictionary
 *                                 context of the current locale.
 * @return {i18n}       the instance.
 */
i18n.clearCache = function clearCache (refresh) {
  this._context = {}
  if (refresh) this.refreshContext()
  return this
}

/**
 * method used to determine whether a locale has cached dictionary context or
 * not.
 * @param  {String}     locale    the locale name
 * @return {Boolean}    True if it has, false otherwise
 */
i18n.isCached = function isCached (locale) {
  return !(this._context[locale] === undefined)
}

/**
 * method used to translate a phrase.
 * @param  {String}     path    the path of the localized phrase within the
 *                              dictionary context.
 * @return {String}     the translated quantitative phrase
 */
i18n.__ = function __ (path) {
  /*
    translating the phrase while using sprintf to include placeholders.
   */
  var args = Array.prototype.slice.call(arguments, 1)
  return require('sprintf-js').vsprintf(this._translate(path), args)
}

/**
 * method used to translate a quantitative phrase. note that the i18n-light uses
 * the last parameter to determine the quantity.
 * @param  {String}     path    the path of the localized phrase within the
 *                              dictionary context.
 * @return {String}     the translated quantitative phrase.
 */
i18n.__n = function __n (path) {
  /**
   * the quantity. if the last parameter isn't a number, i18n-light will
   * consider it as a 0.
   * @type {number}
   */
  var amount = (!isNaN(arguments[arguments.length - 1]))
    ? Number(arguments[arguments.length - 1]) : 0

  /*
    based on the value of amount i18n-light will be appending a node to the
    current path.
   */
  if (amount === 0) {
    path += '.zero'
  } else if (amount === 1) {
    path += '.one'
  } else {
    path += '.many'
  }

  /*
    translating the quantitative phrase while using sprintf to include
    placeholders.
   */
  var args = Array.prototype.slice.call(arguments, 1, arguments.length - 1)
  return require('sprintf-js').vsprintf(this._translate(path), args)
}

/**
 * method used to go through the dictionary context of the locales to retrieve
 * a localized phrase.
 * @param  {String}   path    the path of the localized phrase within the
 *                            dictionary context.
 * @param  {Boolean}  def     indicates wether to loop the current locale or
 *                            the default locale.
 * @return {String}   the localized phrase or the path provided if path is
 *                    invalid.
 */
i18n._translate = function _translate (path, def) {
  /**
   * the name of the locale i18n-light will be using for the
   * translation.
   * @type {String}
   */
  var locale = (def) ? this._defaultLocale : this._currentLocale

  /*
    if the locale being used for the translation is not cached, i18n-light
    should retrieve.
   */
  if (this._context[locale] === undefined) this.refreshContext(locale)

  /**
   * the dictionary context of the locale, i18n-light will be using for the
   * translation.
   * @type {Object}
   */
  var obj = this._getContext(locale)

  /**
   * splitting the path to an array.
   * @type {Array[String]}
   */
  var pathArr = path.split('.')
  /*
    i18n-light will be looping through each node of the path given and while
    traversing the dictionary context of the current or default locale.
   */
  for (var i = 0; i < pathArr.length; i++) {
    /**
     * this represent a key of the dictionary context being traversed.
     * @type {String}
     */
    var node = pathArr[i]

    /**
     * indicates whether it is the last loop or not. if so we will be expecting
     * that typeof node === 'string'
     * @type {Boolean}
     */
    var last = (i === (pathArr.length - 1))

    /**
     * indicates whether 'node' is valid or not. a 'node' is valid if:
     *   1. it exists as a key inside 'obj'.
     *   2. it should be an object if it isn't in the last loop.
     *   3. it shouldn't be an object if it is at the last loop.
     * @type {Boolean}
     */
    var valid = (obj[node] !== undefined) && ((typeof obj[node] === 'object' &&
        !(last)) || (typeof obj[node] !== 'object' && last))

    if (valid) {
      /*
        the next thing to do is to determine whether we should return the
        localized string (if we are at the last loop) or setup the 'obj' for
        the next loop (preparing it for 'i18n-light' journey in finding the
        phrase).
       */
      if (last) {
        path = obj[node]
      } else {
        obj = obj[node]
      }
    } else if ((locale !== this._defaultLocale) && this._fallback) {
      /*
        if 'node' doesn't cater for all the rules mentioned above, i18n-light
        will try the path on the default locale if:
          1. the current locale being traversed is not the default locale
             (since it will cause an infinite loop o.o) and
          2. the user has chosen to make use of this functionality by passing
              fallback = true.
       */
      path = this._translate(path, true)
    } else break
  }
  return path
}

module.exports = Object.create(i18n)
<commit_msg>Fix comment.<commit_after>'use strict'
/**
 * i18n-light object.
 * @type {Object}
 */
var i18n = {}

/**
 * method used to initialize all instance variables.
 * a.k.a the excuse to document instance variables.
 * @return {i18n}   the instance.
 */
i18n._init = function _init () {
  /**
   * i18n-light version.
   * @type {String}
   */
  this.version = '0.5.2'

  /**
   * indicates whether i18n-light should fallback to the defaultLocale if a
   * dictionary path isn't found.
   * @type {Boolean}
   */
  this._fallback = true

  /**
   * indicates whether i18n-light should keep old dictionary contexts once the
   * current locale is changed.
   * @type {Boolean}
   */
  this._cache = true

  /**
   * indicates whether i18n-light should override existant dictionary contexts
   * or not when a locale changes.
   * @type {Boolean}
   */
  this._refresh = false

  /**
   * the dictionaries files extension.
   * @type {String}
   */
  this._extension = '.js'

  /**
   * this is the locale which i18n-light will fallback if the provided
   * dictionary path isn't found on the current locale dictionary.
   * @type {String}
   */
  this._defaultLocale = null

  /**
   * this is the directory where i18n-light will be searching dictionaries from.
   * @type {String}
   */
  this._dir = null

  /**
   * object which i18n-light will be using to store locale dictionaries
   * contexts.
   * @type {Object}
   */
  this._context = {}

  /**
   * the current locale.
   * @type {String}
   */
  this._currentLocale = null

  /**
   * custom resolver for dictionary contexts. this function is only used by
   * i18n-light if the instance is not configured with `dir` or `context` and
   * is used when i18n-light needs a dictionary context for a locale. i18n-light
   * passes the locale name as an argument and waits for json.
   * @type {Object}
   */
  this._resolve = null

  return this
}

/**
 * method used to intialize the i18n-light instance. can be considered as the
 * object constructor.
 * @param  {Object}   opts    configuration object.
 * @return {i18n}     the instance.
 */
i18n.configure = function configure (opts) {
  this._init()

  this._fallback = (opts.fallback !== undefined)
    ? opts.fallback : this._fallback

  this._cache = (opts.cache !== undefined)
    ? opts.cache : this._cache

  this._refresh = (opts.refresh !== undefined)
    ? opts.refresh : this._refresh

  this._extension =
    this._tidyExtension((opts.extension || this._extension))

  if (opts.defaultLocale) {
    this._defaultLocale = opts.defaultLocale
  } else {
    throw new Error('Please provide a default locale which i18n-light will ' +
      'fallback using the \'defaultLocale\' attribute.')
  }

  if (opts.dir) {
    this._dir = this._tidyDir(opts.dir)
  } else if (opts.context) {
    this._context = opts.context
  } else if (opts.resolve) {
    this._resolve = opts.resolve
  } else {
    throw new Error('Please provide the directory where your dictionaries ' +
      'are located using the \'dir\' attribute or the dictionary context ' +
      'itself using \'context\'')
  }

  this.resetLocale()
  return this
}

/**
 * method used to format the extension string into a valid extension. this is
 * done by including a '.' if the extension string isn't already prefixed with
 * one.
 * @param {String}    extension   an extension prefixed with '.'
 */
i18n._tidyExtension = function _tidyExtension (extension) {
  if (extension[0] !== '.') extension = '.' + extension
  return extension
}

/**
 * method used to make sure that the 'dir' path has a trailing '/'.
 * @param  {String} path the path to be given to 'dir'.
 * @return {String}      a path ending with a '/'.
 */
i18n._tidyDir = function _tidyDir (path) {
  if (path[path.length - 1] !== '/') path += '/'
  return path
}

/**
 * i18n-light middleware function.
 * @return {Function}     middleware
 */
i18n.init = function init () {
  var self = this
  return function (req, res, next) {
    self.resetLocale()
    res.i18n = self
    res.locals.i18n = self
    next()
  }
}

/**
 * method used to reset the current locale back to the default locale.
 * @param {Boolean}   refresh     indicates whether the dictionary context of
 *                                the default locale should be updated or not.
 * @return {i18n}     the instance.
 */
i18n.resetLocale = function resetLocale (refresh) {
  return this.setLocale(this._defaultLocale, refresh)
}

/**
 * method used to change the current locale.
 * @param {String}    locale      the new locale.
 * @param {Boolean}   refresh     indicates whether the dictionary context of
 *                                the current locale should be updated or not.
 * @return {i18n}     the instance
 */
i18n.setLocale = function setLocale (locale, refresh) {
  // change the current locale.
  this._currentLocale = locale

  /*
   * i18n-light should only retrieve the locale dictionary context if:
   *     1. there is no cached dictionary for the new locale.
   *     2. refresh is true.
   *     3. refresh is undefined and this._refresh is true.
   */
  if (!(this.isCached(this._currentLocale))) {
    if (!(this._cache)) {
      // clear cache only if this._cache === false
      this.clearCache()
    }
    // retrieve the current locale's dictionary since it not cached.
    this.refreshContext()
  } else {
    /**
     * indicates whether to refresh the current locale's dictionary context or
     * not. if refresh is not passed i18n-light should fallback to this._refresh
     * @type {Boolean}
     */
    refresh = (refresh !== undefined) ? refresh : this._refresh

    /**
     * object which will contain the dictionary context of the current locale if
     * this._cache === false (i.e. reset this._context) and refresh === false
     * (i.e. keep the current locale dicionary context). this is done because
     * when this.clearCache() is executed, i18n-light completly destroys
     * this._context and thus losing the current locale's context making us
     * unable to restore the locale's dictionary.
     * @type {Object}
     */
    var context = null

    /*
      as stated i18n-light will only keep the current locale's dictionary if
      refresh === false and this.cache === false.
     */
    if (!(refresh) && !(this._cache)) {
      context = this._context[this._currentLocale]
    }

    /*
      once we have the current locale's context we can clear the cache if
      this._cache === false.
     */
    if (!(this._cache)) this.clearCache()

    if (refresh) {
      /*
        if refresh === true, i18n-light will retrieve the updated dictionary
        context.
       */
      this.refreshContext()
    } else if (!(this._cache)) {
      /*
        if user chooses to keep current dictionary context and to clear the
        cache i18n-light will use the 'context' object.
       */
      this._context[this._currentLocale] = context
    }
    /*
      else i18n-light doesn't care because user chose to keep the same
      dictionary context (refresh === false) and not to reset the cache
      (this.cache === true). :D
     */
  }
  return this
}

/**
 * method used to return the current locale i18n-light is using.
 * @return {String}     the current locale.
 */
i18n.getLocale = function getLocale () {
  return this._currentLocale
}

/**
 * method used to change the default locale of an i18n-light instance.
 * @param {i18n} locale   the instance.
 */
i18n.setDefaultLocale = function setDefaultLocale (locale) {
  this._defaultLocale = locale
  return this
}

/**
 * method used to refresh the dictionary context of i18n-light.
 * @param  {String}     locale    the name of the locale which i18n-light will
 *                                update its dictionary context.
 * @return {i18n}       the instance.
 */
i18n.refreshContext = function refreshContext (locale) {
  locale = (typeof locale === 'string') ? locale : this._currentLocale

  if (this._dir) {
    var path = this._dir + locale + this._extension

    this._context[locale] =
      JSON.parse(require('fs').readFileSync(path, 'utf-8'))
  } else if (this._resolve !== null) {
    this._context[locale] = JSON.parse(JSON.stringify(this._resolve(locale)))
  }

  return this
}

/**
 * method used to get the dictionary context of a particular locale.
 * @param  {String}   locale    the locale name.
 * @return {Object}   The dictionary context
 */
i18n._getContext = function _getContext (locale) {
  return this._context[locale]
}

/**
 * method used to clear the context object cached data.
 * @param  {Boolean}    refresh    indicates whether to retrieve the dictionary
 *                                 context of the current locale.
 * @return {i18n}       the instance.
 */
i18n.clearCache = function clearCache (refresh) {
  this._context = {}
  if (refresh) this.refreshContext()
  return this
}

/**
 * method used to determine whether a locale has cached dictionary context or
 * not.
 * @param  {String}     locale    the locale name
 * @return {Boolean}    True if it has, false otherwise
 */
i18n.isCached = function isCached (locale) {
  return !(this._context[locale] === undefined)
}

/**
 * method used to translate a phrase.
 * @param  {String}     path    the path of the localized phrase within the
 *                              dictionary context.
 * @return {String}     the translated quantitative phrase
 */
i18n.__ = function __ (path) {
  /*
    translating the phrase while using sprintf to include placeholders.
   */
  var args = Array.prototype.slice.call(arguments, 1)
  return require('sprintf-js').vsprintf(this._translate(path), args)
}

/**
 * method used to translate a quantitative phrase. note that the i18n-light uses
 * the last parameter to determine the quantity.
 * @param  {String}     path    the path of the localized phrase within the
 *                              dictionary context.
 * @return {String}     the translated quantitative phrase.
 */
i18n.__n = function __n (path) {
  /**
   * the quantity. if the last parameter isn't a number, i18n-light will
   * consider it as a 0.
   * @type {number}
   */
  var amount = (!isNaN(arguments[arguments.length - 1]))
    ? Number(arguments[arguments.length - 1]) : 0

  /*
    based on the value of amount i18n-light will be appending a node to the
    current path.
   */
  if (amount === 0) {
    path += '.zero'
  } else if (amount === 1) {
    path += '.one'
  } else {
    path += '.many'
  }

  /*
    translating the quantitative phrase while using sprintf to include
    placeholders.
   */
  var args = Array.prototype.slice.call(arguments, 1, arguments.length - 1)
  return require('sprintf-js').vsprintf(this._translate(path), args)
}

/**
 * method used to go through the dictionary context of the locales to retrieve
 * a localized phrase.
 * @param  {String}   path    the path of the localized phrase within the
 *                            dictionary context.
 * @param  {Boolean}  def     indicates wether to loop the current locale or
 *                            the default locale.
 * @return {String}   the localized phrase or the path provided if path is
 *                    invalid.
 */
i18n._translate = function _translate (path, def) {
  /**
   * the name of the locale i18n-light will be using for the translation.
   * @type {String}
   */
  var locale = (def) ? this._defaultLocale : this._currentLocale

  /*
    if the locale being used for the translation is not cached, i18n-light
    should retrieve.
   */
  if (this._context[locale] === undefined) this.refreshContext(locale)

  /**
   * the dictionary context of the locale, i18n-light will be using for the
   * translation.
   * @type {Object}
   */
  var obj = this._getContext(locale)

  /**
   * splitting the path to an array.
   * @type {Array[String]}
   */
  var pathArr = path.split('.')
  /*
    i18n-light will be looping through each node of the path given and while
    traversing the dictionary context of the current or default locale.
   */
  for (var i = 0; i < pathArr.length; i++) {
    /**
     * this represent a key of the dictionary context being traversed.
     * @type {String}
     */
    var node = pathArr[i]

    /**
     * indicates whether it is the last loop or not. if so we will be expecting
     * that typeof node === 'string'
     * @type {Boolean}
     */
    var last = (i === (pathArr.length - 1))

    /**
     * indicates whether 'node' is valid or not. a 'node' is valid if:
     *   1. it exists as a key inside 'obj'.
     *   2. it should be an object if it isn't in the last loop.
     *   3. it shouldn't be an object if it is at the last loop.
     * @type {Boolean}
     */
    var valid = (obj[node] !== undefined) && ((typeof obj[node] === 'object' &&
        !(last)) || (typeof obj[node] !== 'object' && last))

    if (valid) {
      /*
        the next thing to do is to determine whether we should return the
        localized string (if we are at the last loop) or setup the 'obj' for
        the next loop (preparing it for 'i18n-light' journey in finding the
        phrase).
       */
      if (last) {
        path = obj[node]
      } else {
        obj = obj[node]
      }
    } else if ((locale !== this._defaultLocale) && this._fallback) {
      /*
        if 'node' doesn't cater for all the rules mentioned above, i18n-light
        will try the path on the default locale if:
          1. the current locale being traversed is not the default locale
             (since it will cause an infinite loop o.o) and
          2. the user has chosen to make use of this functionality by passing
              fallback = true.
       */
      path = this._translate(path, true)
    } else break
  }
  return path
}

module.exports = Object.create(i18n)
<|endoftext|>