<commit_before>var isInteger = require('is-integer');
var assign = require('object-assign');
var _s = require('underscore.string');

var aggregators = require('./lib/aggregators');
var utils = require('./lib/utils');

/**
 * @param {object} obj
 * @param {string} parameterName
 * @param {any} defaultValue
 * @param {(object|undefined)} options
 */
var defineParameter = function defineParameter(obj, parameterName, defaultValue, options) {
  options = assign({
    validate: function(value) {
      return true;
    },
    format: function(value) {
      return value.toString();
    },
    isHumanizedGetter: true
  }, options || {});

  var privatePropName = '_' + _s.camelize(parameterName, true);
  var classifiedPropName = _s.classify(parameterName);
  // e.g. 'maxHp'   -> 'getMaxHp'
  //      'isEnemy' -> 'isEnemy'
  var getterName = 'get' + classifiedPropName;
  if (
    options.isHumanizedGetter &&
    /^(is|has|can|should|will)/.test(parameterName)
  ) {
    getterName = _s.camelize(parameterName, true);
  }

  //
  // NOTE:
  //
  // Can not use Object.definePeoperty,
  //   because defined getter/setter can not mix-in other object.
  // I want to use like the following:
  //
  // ```
  // var parameters = {};
  // defineParameter(parameters, 'maxHp');
  // defineParameter(parameters, 'attack');
  // defineParameter(parameters, 'defense');
  //
  // var creature = {};
  // mixin(creature, mixin);
  // var skill = {};
  // mixin(skill, mixin);
  // var equipment = {};
  // mixin(equipment, mixin);
  // ```
  //

  // getRawMaxHp
  obj['getRaw' + classifiedPropName] = function getRaw() {
    return this[privatePropName];
  };

  // getMaxHp (or isFooBar or canFooBar etc)
  obj[getterName] = function get() {
    return this['getRaw' + classifiedPropName]();
  };

  // setMaxHp
  obj['set' + classifiedPropName] = function set(value) {
    if (!options.validate(value)) {
      throw new Error('`' + value + '` is invalid parameter');
    }
    this[privatePropName] = value;
  };

  // validateMaxHp
  obj['validate' + classifiedPropName] = options.validate;

  // displayMaxHp
  obj['display' + classifiedPropName] = function display() {
    return options.format(this[getterName]());
  };

  // set default value with validation
  obj['set' + classifiedPropName](defaultValue);
};

var defineNumberParameter = function defineNumberParameter(obj, parameterName, options) {
  options = assign({
    default: 0.0,
    min: null,
    max: null,
    isIntegerOnly: false
  }, options || {});

  var customOptionKeys = ['default', 'min', 'max', 'isIntegerOnly'];
  var customOptions = utils.pickKeys(options, customOptionKeys);
  options = utils.omitKeys(options, customOptionKeys);

  options.validate = function validate(value) {
    return (
      typeof value === 'number' && !isNaN(value) &&
      (customOptions.min === null || customOptions.min <= value) &&
      (customOptions.max === null || customOptions.max >= value) &&
      (!customOptions.isIntegerOnly || isInteger(value))
    );
  };

  defineParameter(obj, parameterName, customOptions.default, options);
};

var defineIntegerParameter = function defineIntegerParameter(obj, parameterName, options) {
  defineNumberParameter(obj, parameterName, assign({}, options, { isIntegerOnly: true }));
};

var defineRateParameter = function defineRateParameter(obj, parameterName, options) {
  options = assign({
    default: 1.0
  }, options || {}, {
    min: 0.0
  });
  defineNumberParameter(obj, parameterName, options);
};

var defineChanceParameter = function defineChanceParameter(obj, parameterName, options) {
  options = assign({
    default: 0.0,
  }, options || {}, {
    min: 0.0,
    max: 1.0
  });
  defineNumberParameter(obj, parameterName, options);
};

var defineBooleanParameter = function defineBooleanParameter(obj, parameterName, options) {
  options = assign({
    default: false
  }, options || {});

  var customOptionKeys = ['default'];
  var customOptions = utils.pickKeys(options, customOptionKeys);
  options = utils.omitKeys(options, customOptionKeys);

  options.validate = function validate(value) {
    return value === true || value === false;
  };

  defineParameter(obj, parameterName, customOptions.default, options);
};

module.exports = {
  defineParameter: defineParameter,
  defineNumberParameter: defineNumberParameter,
  defineIntegerParameter: defineIntegerParameter,
  defineRateParameter: defineRateParameter,
  defineChanceParameter: defineChanceParameter,
  defineBooleanParameter: defineBooleanParameter,
  aggregators: aggregators
};
<commit_msg>Fix jsdoc<commit_after>var isInteger = require('is-integer');
var assign = require('object-assign');
var _s = require('underscore.string');

var aggregators = require('./lib/aggregators');
var utils = require('./lib/utils');

/**
 * @param {Object} obj
 * @param {string} parameterName
 * @param {*} defaultValue
 * @param {(Object|undefined)} options
 */
var defineParameter = function defineParameter(obj, parameterName, defaultValue, options) {
  options = assign({
    validate: function(value) {
      return true;
    },
    format: function(value) {
      return value.toString();
    },
    isHumanizedGetter: true
  }, options || {});

  var privatePropName = '_' + _s.camelize(parameterName, true);
  var classifiedPropName = _s.classify(parameterName);
  // e.g. 'maxHp'   -> 'getMaxHp'
  //      'isEnemy' -> 'isEnemy'
  var getterName = 'get' + classifiedPropName;
  if (
    options.isHumanizedGetter &&
    /^(is|has|can|should|will)/.test(parameterName)
  ) {
    getterName = _s.camelize(parameterName, true);
  }

  //
  // NOTE:
  //
  // Can not use Object.definePeoperty,
  //   because defined getter/setter can not mix-in other object.
  // I want to use like the following:
  //
  // ```
  // var parameters = {};
  // defineParameter(parameters, 'maxHp');
  // defineParameter(parameters, 'attack');
  // defineParameter(parameters, 'defense');
  //
  // var creature = {};
  // mixin(creature, mixin);
  // var skill = {};
  // mixin(skill, mixin);
  // var equipment = {};
  // mixin(equipment, mixin);
  // ```
  //

  // getRawMaxHp
  obj['getRaw' + classifiedPropName] = function getRaw() {
    return this[privatePropName];
  };

  // getMaxHp (or isFooBar or canFooBar etc)
  obj[getterName] = function get() {
    return this['getRaw' + classifiedPropName]();
  };

  // setMaxHp
  obj['set' + classifiedPropName] = function set(value) {
    if (!options.validate(value)) {
      throw new Error('`' + value + '` is invalid parameter');
    }
    this[privatePropName] = value;
  };

  // validateMaxHp
  obj['validate' + classifiedPropName] = options.validate;

  // displayMaxHp
  obj['display' + classifiedPropName] = function display() {
    return options.format(this[getterName]());
  };

  // set default value with validation
  obj['set' + classifiedPropName](defaultValue);
};

var defineNumberParameter = function defineNumberParameter(obj, parameterName, options) {
  options = assign({
    default: 0.0,
    min: null,
    max: null,
    isIntegerOnly: false
  }, options || {});

  var customOptionKeys = ['default', 'min', 'max', 'isIntegerOnly'];
  var customOptions = utils.pickKeys(options, customOptionKeys);
  options = utils.omitKeys(options, customOptionKeys);

  options.validate = function validate(value) {
    return (
      typeof value === 'number' && !isNaN(value) &&
      (customOptions.min === null || customOptions.min <= value) &&
      (customOptions.max === null || customOptions.max >= value) &&
      (!customOptions.isIntegerOnly || isInteger(value))
    );
  };

  defineParameter(obj, parameterName, customOptions.default, options);
};

var defineIntegerParameter = function defineIntegerParameter(obj, parameterName, options) {
  defineNumberParameter(obj, parameterName, assign({}, options, { isIntegerOnly: true }));
};

var defineRateParameter = function defineRateParameter(obj, parameterName, options) {
  options = assign({
    default: 1.0
  }, options || {}, {
    min: 0.0
  });
  defineNumberParameter(obj, parameterName, options);
};

var defineChanceParameter = function defineChanceParameter(obj, parameterName, options) {
  options = assign({
    default: 0.0,
  }, options || {}, {
    min: 0.0,
    max: 1.0
  });
  defineNumberParameter(obj, parameterName, options);
};

var defineBooleanParameter = function defineBooleanParameter(obj, parameterName, options) {
  options = assign({
    default: false
  }, options || {});

  var customOptionKeys = ['default'];
  var customOptions = utils.pickKeys(options, customOptionKeys);
  options = utils.omitKeys(options, customOptionKeys);

  options.validate = function validate(value) {
    return value === true || value === false;
  };

  defineParameter(obj, parameterName, customOptions.default, options);
};

module.exports = {
  defineParameter: defineParameter,
  defineNumberParameter: defineNumberParameter,
  defineIntegerParameter: defineIntegerParameter,
  defineRateParameter: defineRateParameter,
  defineChanceParameter: defineChanceParameter,
  defineBooleanParameter: defineBooleanParameter,
  aggregators: aggregators
};
<|endoftext|>


<commit_before>'use strict'

var express = require('express')
var ExpressRouter = express.Router

ExpressRouter.prototype = ExpressRouter

var methods = require('methods')
var slice = Array.prototype.slice

var PROTO = '__proto__'

var HEADER_CONTENT_TYPE = 'Content-Type'

function defer (promise) {
  promise.then(null, function (err) {
    setImmediate(function () {
      throw err
    })
  })
}

function Response (contentType, body) {
  this.contentType = contentType
  this.body = body
}

Router.Response = Response

module.exports = Router

function Router () {
  var expressRouter = new ExpressRouter()
  expressRouter[PROTO] = Router.prototype
  return expressRouter
}

Router.prototype[PROTO] = ExpressRouter

function promisify (handler, shouldRespond) {
  if (typeof handler.handler === 'function') {
    // it's already middleware:
    return handler
  }
  return function (req, res, next) {
    function onFulfilled (result) {
      if (result instanceof Response) {
        if (!res.get(HEADER_CONTENT_TYPE)) {
          res.set(HEADER_CONTENT_TYPE, res.contentType)
        }
        return res.send(result.body)
      } else if (shouldRespond) {
        return res.json(result)
      }
      next()
    }

    var result
    try {
      result = handler(req, res)
    } catch (ex) {
      if (ex === 'route') return next('route')
      return next(ex)
    }

    if (result && typeof result.then === 'function') {
      defer(result.then(onFulfilled, next))
    } else {
      onFulfilled(result)
    }
  }
}

// create Router#VERB functions
methods.concat('all').forEach(function (method) {
  Router.prototype[method] = function (path) {
    var route = ExpressRouter.route.call(this, path)
    var handlers = slice.call(arguments, 1)
    var middlewareHandlers = handlers.map(function (handler) {
      return promisify(handler, true)
    })
    route[method].apply(route, middlewareHandlers)
    return this
  }
})

Router.prototype.error = function (handler) {
  var middleware = function (err, req, res, next) {
    var result = handler(err, req, res)
    if (result && typeof result.then === 'function') {
      defer(result.then(function (result) {
        res.json(result)
      }, next))
    } else {
      res.json(result)
    }
  }

  return ExpressRouter.use.call(this, middleware)
}

Router.prototype.param = function (paramName, handler) {
  var middleware = promisify(handler, false)
  return ExpressRouter.param.call(this, paramName, middleware)
}

Router.prototype.use = function (arg1) {
  if (typeof arg1 === 'string') {
    return ExpressRouter.use.apply(this, arguments)
  }
  var middleware = promisify(arg1, false)
  return ExpressRouter.use.call(this, middleware)
}
<commit_msg>Fix content-type value<commit_after>'use strict'

var express = require('express')
var ExpressRouter = express.Router

ExpressRouter.prototype = ExpressRouter

var methods = require('methods')
var slice = Array.prototype.slice

var PROTO = '__proto__'

var HEADER_CONTENT_TYPE = 'Content-Type'

function defer (promise) {
  promise.then(null, function (err) {
    setImmediate(function () {
      throw err
    })
  })
}

function Response (contentType, body) {
  this.contentType = contentType
  this.body = body
}

Router.Response = Response

module.exports = Router

function Router () {
  var expressRouter = new ExpressRouter()
  expressRouter[PROTO] = Router.prototype
  return expressRouter
}

Router.prototype[PROTO] = ExpressRouter

function promisify (handler, shouldRespond) {
  if (typeof handler.handler === 'function') {
    // it's already middleware:
    return handler
  }
  return function (req, res, next) {
    function onFulfilled (result) {
      if (result instanceof Response) {
        if (!res.get(HEADER_CONTENT_TYPE)) {
          res.set(HEADER_CONTENT_TYPE, result.contentType)
        }
        return res.send(result.body)
      } else if (shouldRespond) {
        return res.json(result)
      }
      next()
    }

    var result
    try {
      result = handler(req, res)
    } catch (ex) {
      if (ex === 'route') return next('route')
      return next(ex)
    }

    if (result && typeof result.then === 'function') {
      defer(result.then(onFulfilled, next))
    } else {
      onFulfilled(result)
    }
  }
}

// create Router#VERB functions
methods.concat('all').forEach(function (method) {
  Router.prototype[method] = function (path) {
    var route = ExpressRouter.route.call(this, path)
    var handlers = slice.call(arguments, 1)
    var middlewareHandlers = handlers.map(function (handler) {
      return promisify(handler, true)
    })
    route[method].apply(route, middlewareHandlers)
    return this
  }
})

Router.prototype.error = function (handler) {
  var middleware = function (err, req, res, next) {
    var result = handler(err, req, res)
    if (result && typeof result.then === 'function') {
      defer(result.then(function (result) {
        res.json(result)
      }, next))
    } else {
      res.json(result)
    }
  }

  return ExpressRouter.use.call(this, middleware)
}

Router.prototype.param = function (paramName, handler) {
  var middleware = promisify(handler, false)
  return ExpressRouter.param.call(this, paramName, middleware)
}

Router.prototype.use = function (arg1) {
  if (typeof arg1 === 'string') {
    return ExpressRouter.use.apply(this, arguments)
  }
  var middleware = promisify(arg1, false)
  return ExpressRouter.use.call(this, middleware)
}
<|endoftext|>


<commit_before>

var _ = require('underscore');
var async = require('async');
var influx  = require('influx');

var charm = require('charm')();

charm.pipe(process.stdout);
charm.on('^C', function () {
   charm.down(2).foreground('white');
    process.exit();
});

//emitter.setMaxListeners(100);
var logBuffer = [];

var MongoClient = require('mongodb').MongoClient
    , Server = require('mongodb').Server;

var collectionsInProgres  = {};
var collectionsIndex = 0;
var collectionsCount = 0;

var configuration =
{
    influxserver : {
        user        : 'root',
        password    : 'root',
        hostname    : 'localhost',
        port        : 8086
    },
    influxdb : {
        user        : 'dbuser',
        password    : '',
        hostname    : 'localhost',
        port        : 8086,
        database    : 'default'

    },
    mongodb : {
        user        : '',
        password    : '',
        hostname    : 'localhost',
        port        : 27017,
        database    : 'default',
        querylimit  : 100000
    },
    logging         : true,
    limit           : 2,
    insertlimit     : 100,
    emptySeries     : false

};

var influxServer, influxDB, mongoClient, mongodb;

var drawInterval = false;

var Mongo2Influx = function(options)
{

    if (options.influxdb)
        _.extend(configuration.influxdb,options.influxdb);

    if (options.influxserver)
        _.extend(configuration.influxserver,options.influxserver);

    if (options.mongodb)
        _.extend(configuration.mongodb,options.mongodb);

    if (options.limit) configuration.limit = options.limit;
    if (options.logging) configuration.logging = options.logging;
    if (options.emptySeries) configuration.emptySeries = options.emptySeries;
    if (options.insertlimit) configuration.insertlimit = options.insertlimit;

};

Mongo2Influx.prototype.connect = function (cb)
{

    influxServer = influx(
        configuration.influxserver.hostname,
        configuration.influxserver.port,
        configuration.influxserver.user,
        configuration.influxserver.password,
        configuration.influxserver.database
    );

    influxDB = influx(
        configuration.influxdb.hostname,
        configuration.influxdb.port,
        configuration.influxdb.user,
        configuration.influxdb.password,
        configuration.influxdb.database
    );
    mongoClient = new MongoClient(new Server(configuration.mongodb.hostname, configuration.mongodb.port));

    mongoClient.open(function ( err, mongoClient ) {
        if (err) {
            return cb(err);
        }
        mongodb = mongoClient.db(configuration.mongodb.database);
        return cb(null);

    });
};

var drawing=false;
Mongo2Influx.prototype.draw = function()
{
    if (drawing) return;
    charm.reset();

    drawing = true;
    if (!configuration.logging) return;
    charm.foreground('white');
    charm.write('--=[log]=---------------------------\n');
     _.each(logBuffer,function(line)
    {
        charm.column(0);
        charm.write(line);
        charm.down();
    });
    charm.down(18-logBuffer.length);
    charm.column(0);
    var progress = 100 / collectionsCount * collectionsIndex;
    charm.write('Overall progress ').foreground('green').write(Math.round(progress)+'%');
    charm.foreground('white').write('('+collectionsIndex+'/'+collectionsCount+')');
    charm.down();
    charm.down();
    charm.column(0);
    charm.write('--=[current collections]=---------------------------\n');
    _.each(collectionsInProgres,function(col,name)
    {
        charm.column(0);
        charm.write(name);
        charm.column(30);
        charm.write(col.state);

        charm.column(45);
        charm.foreground('green');
        charm.write(Math.round(col.progress)+'%');
        charm.foreground('white');
        charm.column(50);
        var ips = Math.round(col.ips).toString();
        if (0 != ips)
        {
            charm.foreground('blue').write(ips).write(' inserts/sec');
            charm.foreground('white');
        }
        charm.down();
    })
    charm.column(0);
    drawing = false;

}

Mongo2Influx.prototype.log = function ()
{
    if (configuration.logging) {
        var date = new Date();
        var line = date.getHours()+':'+date.getMinutes()+':'+date.getSeconds();
        line += ': '+_.values(arguments).join(' ');
        logBuffer.push(line);
        while (15 < logBuffer.length) logBuffer.shift();
    }
};

Mongo2Influx.prototype.updateCollection = function(collectionName,values)
{
    _.extend(collectionsInProgres[collectionName],values);
//    this.draw();
}

Mongo2Influx.prototype.migrateCollection = function(prepareFunction, collection,callbackCollections)
{
    var self = this;
    var collectionName = collection.collectionName;
    var startDump = new Date();

    self.countItems(collection,function(err,itemCount)
    {
        if (err) return callbackCollections(err);
        var jobCount = Math.ceil(itemCount/configuration.mongodb.querylimit);
        var mongoJobs = [];
        for (var i=0; i<jobCount;++i)
            mongoJobs.push(i*configuration.mongodb.querylimit);

        var rowsSkipped = 0;

        async.eachSeries(mongoJobs,function(mongoOffset,callbackFind)
        {

            self.updateCollection(collectionName,{state : 'reading'});
            collection.find().limit(configuration.mongodb.querylimit).skip(mongoOffset).toArray(function(err, results) {
                if (!err && _.isArray(results))
                {
                    self.log('reading results from',collectionName,results.length,'rows, took',(new Date()-startDump),'ms');
                    self.updateCollection(collectionName,{state : 'inserting'});

                    var index =0;
                    var lastIndex =0;

                    var startMigration = new Date();

                    var jobCount = Math.ceil(results.length/configuration.insertlimit);
                    var jobs = [];
                    for (var i=0; i<jobCount;++i)
                        jobs.push(i*configuration.insertlimit);

                    var bench = function()
                    {
                        var inserts = index-lastIndex;
                        lastIndex=index;
                        var diff = (new Date()-startMigration) / 1000;
                        var ips = Math.round(inserts/ diff);
//                        self.log('collection',collectionName,'item #',index,'@',ips,'inserts/sec');
                        startMigration = new Date();
                        var progress = 100 / itemCount * (index+mongoOffset);

                        self.updateCollection(collectionName,{state : 'inserting',progress : progress,ips: ips,item:index});
                    };

                    var statInterval = setInterval(bench,500);

                    async.eachSeries(jobs,function(offset,cb){
                        var data = [];
                        var offsetLimit = offset + configuration.insertlimit -1;
                        if (offsetLimit >= results.length) offsetLimit = results.length-1;

                        for (var i=offset;i<=offsetLimit;++i)
                        {
                            var row = prepareFunction(results[i]);
                            if (!row.time) {
                                rowsSkipped++;
                            } else {
                                data.push(row);
                            }
                        }

                        influxDB.writePoints(collectionName, data , {pool : false}, function(err) {
                            if (err)
                            {
                                return cb(err)
                            }
                            else {
                                index += data.length;
                                delete(data);
                                return cb();
                            }
                        });
                    },function(err)
                    {
                        clearInterval(statInterval);
                        callbackFind(err);
                    });
                } else {
                    results = null;
                    delete(results);
                    callbackFind(err);
                }
            });
        },function(err)
        {
            if (err)
            {
                self.log('error migrating collection',collectionName);

            } else {
                var successRate = 100 / itemCount * (itemCount-rowsSkipped);
                self.log('collection',collectionName,'done, skipped',rowsSkipped,'rows, successrate:',successRate,'%');
            }
            delete(collectionsInProgres[collectionName]);
            callbackCollections(err);
        });
    });
};

Mongo2Influx.prototype.countItems = function (collection,callback)
{
    collection.count(function(err,count)
    {
        callback(err,count);
    });
};

Mongo2Influx.prototype.migrateCollections = function( prepareFunction, options, collections, callback )
{
    var self = this;
    self.log('found',collections.length,'collection');
    async.eachLimit(collections,configuration.limit,function( collection, callbackCollections )
    {
        collectionsIndex++;
        var collectionName = collection.collectionName;
        if ( -1 !== collectionName.indexOf('system')) return callbackCollections();
        self.log('next collection: ',collectionName);

        collectionsInProgres[collectionName] = {
            state       : '',
            progress    : 0,
            ips         : 0,
            item        : 0
        };
        if (true === configuration.emptySeries)
        {
            self.emptySeries(collection.collectionName,function()
            {
                self.migrateCollection(prepareFunction, collection,callbackCollections);
            })
        } else {
            self.migrateCollection(prepareFunction, collection,callbackCollections);
        }
    },callback);
};

Mongo2Influx.prototype.emptySeries = function(collectionName,callback)
{
    var self = this;
    var start = new Date();
    self.log('Truncating influx series',collectionName);
    self.updateCollection(collectionName,{state : 'truncating'});

    influxDB.readPoints('DELETE FROM '+collectionName+' WHERE time < now();',function(err)
    {
        var diff = new Date()-start;
        self.updateCollection(collectionName,{state : 'truncated'});

        self.log('Truncating influx series',collectionName,'took',diff,'ms');
        callback(err);
    });
};

Mongo2Influx.prototype.migrate = function ( prepareFunction, options, callback )
{
    if (!mongodb)
    {
        return callback('mongodb is not connected');
    }

    if ('function' == typeof options)
        callback = options;

    if ('function' != typeof prepareFunction)
        return callback('missing prepare function');
    var self = this;
    drawInterval = setInterval(self.draw,500);
    collectionsIndex = 0;
    mongodb.collections(function(err,collections)
    {
        if (err)
        {
            callback(err);
        } else {
            collectionsCount = collections.length;
            self.migrateCollections(prepareFunction,options, collections,function(err)
            {
                clearInterval(drawInterval);
                callback(err);
            });
        }
    });
};

module.exports = Mongo2Influx;<commit_msg>code cleanup<commit_after>

var _ = require('underscore');
var async = require('async');
var influx  = require('influx');

var charm = require('charm')();

charm.pipe(process.stdout);
charm.on('^C', function () {
   charm.down(2).column(0).foreground('white');
   process.exit();
});

var logBuffer = [];

var MongoClient = require('mongodb').MongoClient
    , Server = require('mongodb').Server;

var collectionsInProgres  = {};
var collectionsIndex = 0;
var collectionsCount = 0;

var configuration =
{
    influxserver : {
        user        : 'root',
        password    : 'root',
        hostname    : 'localhost',
        port        : 8086
    },
    influxdb : {
        user        : 'dbuser',
        password    : '',
        hostname    : 'localhost',
        port        : 8086,
        database    : 'default'

    },
    mongodb : {
        user        : '',
        password    : '',
        hostname    : 'localhost',
        port        : 27017,
        database    : 'default',
        querylimit  : 100000
    },
    logging         : true,
    limit           : 2,
    insertlimit     : 100,
    emptySeries     : false

};

var influxServer, influxDB, mongoClient, mongodb;

var drawInterval = false;

var Mongo2Influx = function(options)
{

    if (options.influxdb)
        _.extend(configuration.influxdb,options.influxdb);

    if (options.influxserver)
        _.extend(configuration.influxserver,options.influxserver);

    if (options.mongodb)
        _.extend(configuration.mongodb,options.mongodb);

    if (options.limit) configuration.limit = options.limit;
    if (options.logging) configuration.logging = options.logging;
    if (options.emptySeries) configuration.emptySeries = options.emptySeries;
    if (options.insertlimit) configuration.insertlimit = options.insertlimit;

};

Mongo2Influx.prototype.connect = function (cb)
{

    influxServer = influx(
        configuration.influxserver.hostname,
        configuration.influxserver.port,
        configuration.influxserver.user,
        configuration.influxserver.password,
        configuration.influxserver.database
    );

    influxDB = influx(
        configuration.influxdb.hostname,
        configuration.influxdb.port,
        configuration.influxdb.user,
        configuration.influxdb.password,
        configuration.influxdb.database
    );
    mongoClient = new MongoClient(new Server(configuration.mongodb.hostname, configuration.mongodb.port));

    mongoClient.open(function ( err, mongoClient ) {
        if (err) {
            return cb(err);
        }
        mongodb = mongoClient.db(configuration.mongodb.database);
        return cb(null);

    });
};

Mongo2Influx.prototype.draw = function()
{
    charm.reset();

    if (!configuration.logging) return;
    charm.foreground('white');
    charm.write('--=[log]=---------------------------\n');
     _.each(logBuffer,function(line)
    {
        charm.column(0);
        charm.write(line);
        charm.down();
    });
    charm.down(18-logBuffer.length);
    charm.column(0);
    var progress = 100 / collectionsCount * collectionsIndex;
    charm.write('Overall progress ').foreground('green').write(Math.round(progress)+'%');
    charm.foreground('white').write('('+collectionsIndex+'/'+collectionsCount+')');
    charm.down();
    charm.down();
    charm.column(0);
    charm.write('--=[current collections]=---------------------------\n');
    _.each(collectionsInProgres,function(col,name)
    {
        charm.column(0);
        charm.write(name);
        charm.column(30);
        charm.write(col.state);

        charm.column(45);
        charm.foreground('green');
        charm.write(Math.round(col.progress)+'%');
        charm.foreground('white');
        charm.column(50);
        var ips = Math.round(col.ips).toString();
        if (0 != ips)
        {
            charm.foreground('blue').write(ips).write(' inserts/sec');
            charm.foreground('white');
        }
        charm.down();
    });
    charm.column(0);

};

Mongo2Influx.prototype.log = function ()
{
    if (configuration.logging) {
        var date = new Date();
        var line = date.getHours()+':'+date.getMinutes()+':'+date.getSeconds();
        line += ': '+_.values(arguments).join(' ');
        logBuffer.push(line);
        while (15 < logBuffer.length) logBuffer.shift();
    }
};

Mongo2Influx.prototype.updateCollection = function(collectionName,values)
{
    _.extend(collectionsInProgres[collectionName],values);
};

Mongo2Influx.prototype.migrateCollection = function(prepareFunction, collection,callbackCollections)
{
    var self = this;
    var collectionName = collection.collectionName;
    var startDump = new Date();

    self.countItems(collection,function(err,itemCount)
    {
        if (err) return callbackCollections(err);
        var jobCount = Math.ceil(itemCount/configuration.mongodb.querylimit);
        var mongoJobs = [];
        for (var i=0; i<jobCount;++i)
            mongoJobs.push(i*configuration.mongodb.querylimit);

        var rowsSkipped = 0;

        async.eachSeries(mongoJobs,function(mongoOffset,callbackFind)
        {

            self.updateCollection(collectionName,{state : 'reading'});
            collection.find().limit(configuration.mongodb.querylimit).skip(mongoOffset).toArray(function(err, results) {
                if (!err && _.isArray(results))
                {
                    self.log('reading results from',collectionName,results.length,'rows, took',(new Date()-startDump),'ms');
                    self.updateCollection(collectionName,{state : 'inserting'});

                    var index =0;
                    var lastIndex =0;

                    var startMigration = new Date();

                    var jobCount = Math.ceil(results.length/configuration.insertlimit);
                    var jobs = [];
                    for (var i=0; i<jobCount;++i)
                        jobs.push(i*configuration.insertlimit);

                    var bench = function()
                    {
                        var inserts = index-lastIndex;
                        lastIndex=index;
                        var diff = (new Date()-startMigration) / 1000;
                        var ips = Math.round(inserts/ diff);
                        startMigration = new Date();
                        var progress = 100 / itemCount * (index+mongoOffset);
                        self.updateCollection(collectionName,{state : 'inserting',progress : progress,ips: ips,item:index});
                    };

                    var statInterval = setInterval(bench,500);

                    async.eachSeries(jobs,function(offset,cb){
                        var data = [];
                        var offsetLimit = offset + configuration.insertlimit -1;
                        if (offsetLimit >= results.length) offsetLimit = results.length-1;

                        for (var i=offset;i<=offsetLimit;++i)
                        {
                            var row = prepareFunction(results[i]);
                            if (!row.time) {
                                rowsSkipped++;
                            } else {
                                data.push(row);
                            }
                        }

                        influxDB.writePoints(collectionName, data , {pool : false}, function(err) {
                            if (err)
                            {
                                return cb(err)
                            }
                            else {
                                index += data.length;
                                delete(data);
                                return cb();
                            }
                        });
                    },function(err)
                    {
                        clearInterval(statInterval);
                        return callbackFind(err);
                    });
                } else {
                    results = null;
                    delete(results);
                    return callbackFind(err);
                }
            });
        },function(err)
        {
            if (err)
            {
                self.log('error migrating collection',collectionName);

            } else {
                var successRate = 100 / itemCount * (itemCount-rowsSkipped);
                self.log('collection',collectionName,'done, skipped',rowsSkipped,'rows, successrate:',successRate,'%');
            }
            delete(collectionsInProgres[collectionName]);
            callbackCollections(err);
        });
    });
};

Mongo2Influx.prototype.countItems = function (collection,callback)
{
    collection.count(function(err,count)
    {
        callback(err,count);
    });
};

Mongo2Influx.prototype.migrateCollections = function( prepareFunction, options, collections, callback )
{
    var self = this;
    self.log('found',collections.length,'collection');
    async.eachLimit(collections,configuration.limit,function( collection, callbackCollections )
    {
        collectionsIndex++;
        var collectionName = collection.collectionName;
        if ( -1 !== collectionName.indexOf('system')) return callbackCollections();
        self.log('next collection: ',collectionName);

        collectionsInProgres[collectionName] = {
            state       : '',
            progress    : 0,
            ips         : 0,
            item        : 0
        };
        if (true === configuration.emptySeries)
        {
            self.emptySeries(collection.collectionName,function()
            {
                self.migrateCollection(prepareFunction, collection,callbackCollections);
            })
        } else {
            self.migrateCollection(prepareFunction, collection,callbackCollections);
        }
    },callback);
};

Mongo2Influx.prototype.emptySeries = function(collectionName,callback)
{
    var self = this;
    var start = new Date();
    self.log('Truncating influx series',collectionName);
    self.updateCollection(collectionName,{state : 'truncating'});

    influxDB.query('DELETE FROM '+collectionName+' WHERE time < now();',function(err)
    {
        var diff = new Date()-start;
        self.updateCollection(collectionName,{state : 'truncated'});

        self.log('Truncating influx series',collectionName,'took',diff,'ms');
        callback(err);
    });
};

Mongo2Influx.prototype.migrate = function ( prepareFunction, options, callback )
{
    if (!mongodb)
    {
        return callback('mongodb is not connected');
    }

    if ('function' == typeof options)
        callback = options;

    if ('function' != typeof prepareFunction)
        return callback('missing prepare function');
    var self = this;
    drawInterval = setInterval(self.draw,500);
    collectionsIndex = 0;
    mongodb.collections(function(err,collections)
    {
        if (err)
        {
            callback(err);
        } else {
            collectionsCount = collections.length;
            self.migrateCollections(prepareFunction,options, collections,function(err)
            {
                clearInterval(drawInterval);
                callback(err);
            });
        }
    });
};

module.exports = Mongo2Influx;<|endoftext|>


<commit_before>var child = require("child_process"),
    mime = require("mime"),
    path = require("path");

var shaRe = /^[0-9a-f]{40}$/,
    emailRe = /^<.*@.*>$/;

function readBlob(repository, revision, file, callback) {
  var git = child.spawn("git", ["cat-file", "blob", revision + ":" + file], {cwd: repository}),
      data = [],
      exit;

  git.stdout.on("data", function(chunk) {
    data.push(chunk);
  });

  git.on("exit", function(code) {
    exit = code;
  });

  git.on("close", function() {
    if (exit > 0) return callback(error(exit));
    callback(null, Buffer.concat(data));
  });

  git.stdin.end();
}

exports.readBlob = readBlob;

exports.getBranches = function(repository, callback) {
  child.exec("git branch -l", {cwd: repository}, function(error, stdout) {
    if (error) return callback(error);
    callback(null, stdout.split(/\n/).slice(0, -1).map(function(s) { return s.slice(2); }));
  });
};

exports.getSha = function(repository, revision, callback) {
  child.exec("git rev-parse '" + revision.replace(/'/g, "'\''") + "'", {cwd: repository}, function(error, stdout) {
    if (error) return callback(error);
    callback(null, stdout.trim());
  });
};

exports.getBranchCommits = function(repository, callback) {
  child.exec("git for-each-ref refs/heads/ --format='%(objectname)\t%(refname:short)\t%(authordate:iso8601)\t%(authoremail)'", {cwd: repository}, function(error, stdout) {
    if (error) return callback(error);
    callback(null, stdout.split("\n").map(function(line) {
      var fields = line.split("\t"),
          sha = fields[0],
          ref = fields[1],
          date = new Date(fields[2]),
          author = fields[3];
      if (!shaRe.test(sha) || isNaN(date) || !emailRe.test(author)) return;
      return {
        sha: sha,
        ref: ref,
        date: date,
        author: author.substring(1, author.length - 1)
      };
    }).filter(function(commit) {
      return commit;
    }));
  });
};

exports.getCommit = function(repository, revision, callback) {
  if (arguments.length < 3) callback = revision, revision = null;
  child.exec("git for-each-ref --count 1 --sort=-authordate 'refs/heads/" + (revision ? revision.replace(/'/g, "'\''") : "") + "' --format='%(objectname)\n%(authordate:iso8601)'", {cwd: repository}, function(error, stdout) {
    if (error) return callback(error);
    var lines = stdout.split("\n"),
        sha = lines[0],
        date = new Date(lines[1]);
    if (!shaRe.test(sha) || isNaN(date)) return void callback(new Error("unable to get commit"));
    callback(null, {
      sha: sha,
      date: date
    });
  });
};

exports.getRelatedCommits = function(repository, branch, sha, callback) {
  if (!shaRe.test(sha)) return callback(new Error("invalid SHA"));
  child.exec("git log --format='%H' '" + branch.replace(/'/g, "'\''") + "' | grep -C1 " + sha, {cwd: repository}, function(error, stdout) {
    if (error) return callback(error);
    var shas = stdout.split(/\n/),
        i = shas.indexOf(sha);

    callback(null, {
      previous: shas[i + 1],
      next: shas[i - 1]
    });
  });
};

exports.route = function() {
  var repository = defaultRepository,
      revision = defaultRevision,
      file = defaultFile,
      type = defaultType;

  function route(request, response) {
    var repository_,
        revision_,
        file_;

    if ((repository_ = repository(request.url)) == null
        || (revision_ = revision(request.url)) == null
        || (file_ = file(request.url)) == null) return serveNotFound();

    readBlob(repository_, revision_, file_, function(error, data) {
      if (error) return error.code === 128 ? serveNotFound() : serveError(error);
      response.writeHead(200, {
        "Content-Type": type(file_),
        "Cache-Control": "public, max-age=300"
      });
      response.end(data);
    });

    function serveError(error) {
      response.writeHead(500, {"Content-Type": "text/plain"});
      response.end(error + "");
    }

    function serveNotFound() {
      response.writeHead(404, {"Content-Type": "text/plain"});
      response.end("File not found.");
    }
  }

  route.repository = function(_) {
    if (!arguments.length) return repository;
    repository = functor(_);
    return route;
  };

  route.sha = // sha is deprecated; use revision instead
  route.revision = function(_) {
    if (!arguments.length) return revision;
    revision = functor(_);
    return route;
  };

  route.file = function(_) {
    if (!arguments.length) return file;
    file = functor(_);
    return route;
  };

  route.type = function(_) {
    if (!arguments.length) return type;
    type = functor(_);
    return route;
  };

  return route;
};

function functor(_) {
  return typeof _ === "function" ? _ : function() { return _; };
}

function defaultRepository() {
  return path.join(__dirname, "repository");
}

function defaultRevision(url) {
  return decodeURIComponent(url.substring(1, url.indexOf("/", 1)));
}

function defaultFile(url) {
  return decodeURIComponent(url.substring(url.indexOf("/", 1) + 1));
}

function defaultType(file) {
  var type = mime.lookup(file, "text/plain");
  return text(type) ? type + "; charset=utf-8" : type;
}

function text(type) {
  return /^(text\/)|(application\/(javascript|json)|image\/svg$)/.test(type);
}

function error(code) {
  var e = new Error;
  e.code = code;
  return e;
}
<commit_msg>Sort by descending author date.<commit_after>var child = require("child_process"),
    mime = require("mime"),
    path = require("path");

var shaRe = /^[0-9a-f]{40}$/,
    emailRe = /^<.*@.*>$/;

function readBlob(repository, revision, file, callback) {
  var git = child.spawn("git", ["cat-file", "blob", revision + ":" + file], {cwd: repository}),
      data = [],
      exit;

  git.stdout.on("data", function(chunk) {
    data.push(chunk);
  });

  git.on("exit", function(code) {
    exit = code;
  });

  git.on("close", function() {
    if (exit > 0) return callback(error(exit));
    callback(null, Buffer.concat(data));
  });

  git.stdin.end();
}

exports.readBlob = readBlob;

exports.getBranches = function(repository, callback) {
  child.exec("git branch -l", {cwd: repository}, function(error, stdout) {
    if (error) return callback(error);
    callback(null, stdout.split(/\n/).slice(0, -1).map(function(s) { return s.slice(2); }));
  });
};

exports.getSha = function(repository, revision, callback) {
  child.exec("git rev-parse '" + revision.replace(/'/g, "'\''") + "'", {cwd: repository}, function(error, stdout) {
    if (error) return callback(error);
    callback(null, stdout.trim());
  });
};

exports.getBranchCommits = function(repository, callback) {
  child.exec("git for-each-ref refs/heads/ --sort=-authordate --format='%(objectname)\t%(refname:short)\t%(authordate:iso8601)\t%(authoremail)'", {cwd: repository}, function(error, stdout) {
    if (error) return callback(error);
    callback(null, stdout.split("\n").map(function(line) {
      var fields = line.split("\t"),
          sha = fields[0],
          ref = fields[1],
          date = new Date(fields[2]),
          author = fields[3];
      if (!shaRe.test(sha) || isNaN(date) || !emailRe.test(author)) return;
      return {
        sha: sha,
        ref: ref,
        date: date,
        author: author.substring(1, author.length - 1)
      };
    }).filter(function(commit) {
      return commit;
    }));
  });
};

exports.getCommit = function(repository, revision, callback) {
  if (arguments.length < 3) callback = revision, revision = null;
  child.exec("git for-each-ref --count 1 --sort=-authordate 'refs/heads/" + (revision ? revision.replace(/'/g, "'\''") : "") + "' --format='%(objectname)\n%(authordate:iso8601)'", {cwd: repository}, function(error, stdout) {
    if (error) return callback(error);
    var lines = stdout.split("\n"),
        sha = lines[0],
        date = new Date(lines[1]);
    if (!shaRe.test(sha) || isNaN(date)) return void callback(new Error("unable to get commit"));
    callback(null, {
      sha: sha,
      date: date
    });
  });
};

exports.getRelatedCommits = function(repository, branch, sha, callback) {
  if (!shaRe.test(sha)) return callback(new Error("invalid SHA"));
  child.exec("git log --format='%H' '" + branch.replace(/'/g, "'\''") + "' | grep -C1 " + sha, {cwd: repository}, function(error, stdout) {
    if (error) return callback(error);
    var shas = stdout.split(/\n/),
        i = shas.indexOf(sha);

    callback(null, {
      previous: shas[i + 1],
      next: shas[i - 1]
    });
  });
};

exports.route = function() {
  var repository = defaultRepository,
      revision = defaultRevision,
      file = defaultFile,
      type = defaultType;

  function route(request, response) {
    var repository_,
        revision_,
        file_;

    if ((repository_ = repository(request.url)) == null
        || (revision_ = revision(request.url)) == null
        || (file_ = file(request.url)) == null) return serveNotFound();

    readBlob(repository_, revision_, file_, function(error, data) {
      if (error) return error.code === 128 ? serveNotFound() : serveError(error);
      response.writeHead(200, {
        "Content-Type": type(file_),
        "Cache-Control": "public, max-age=300"
      });
      response.end(data);
    });

    function serveError(error) {
      response.writeHead(500, {"Content-Type": "text/plain"});
      response.end(error + "");
    }

    function serveNotFound() {
      response.writeHead(404, {"Content-Type": "text/plain"});
      response.end("File not found.");
    }
  }

  route.repository = function(_) {
    if (!arguments.length) return repository;
    repository = functor(_);
    return route;
  };

  route.sha = // sha is deprecated; use revision instead
  route.revision = function(_) {
    if (!arguments.length) return revision;
    revision = functor(_);
    return route;
  };

  route.file = function(_) {
    if (!arguments.length) return file;
    file = functor(_);
    return route;
  };

  route.type = function(_) {
    if (!arguments.length) return type;
    type = functor(_);
    return route;
  };

  return route;
};

function functor(_) {
  return typeof _ === "function" ? _ : function() { return _; };
}

function defaultRepository() {
  return path.join(__dirname, "repository");
}

function defaultRevision(url) {
  return decodeURIComponent(url.substring(1, url.indexOf("/", 1)));
}

function defaultFile(url) {
  return decodeURIComponent(url.substring(url.indexOf("/", 1) + 1));
}

function defaultType(file) {
  var type = mime.lookup(file, "text/plain");
  return text(type) ? type + "; charset=utf-8" : type;
}

function text(type) {
  return /^(text\/)|(application\/(javascript|json)|image\/svg$)/.test(type);
}

function error(code) {
  var e = new Error;
  e.code = code;
  return e;
}
<|endoftext|>


<commit_before>/*!
 * customize <https://github.com/nknapp/ride-over>
 *
 * Copyright (c) 2015 Nils Knappmeier.
 * Released under the MIT license.
 */

'use strict'

/**
 * Use the `debug`-module to provide debug output if needed
 */
var debug = require('debug')('customize:base')
var debugState = require('debug')('customize:state')
var Q = require('q')
var deep = require('q-deep')
var _ = require('lodash')

/**
 *
 * @param config
 * @param parentConfig
 * @param {object<function>} engines
 * @constructor
 */
function Customize (config, parentConfig, engines) {
  var _config = _.merge({}, parentConfig, config, customOverrider)
  deep(_config).done(function (config) {
    debugState('New configuration', config)
  })

  /**
   * Register an engine with a default config
   * @param {string} id the identifier of the engine (also within the config)
   * @param {function} engine
   */
  this.registerEngine = function (id, engine) {
    debug("Registering engine '" + id + "'")
    if (!_.isString(id)) {
      throw new Error('Engine-id must be a string, but is ' + id)
    }
    if (id.substr(0, 1) === '_') {
      throw new Error("Engine-id may not start with an underscore ('_')")
    }
    if (_.isUndefined(engine['run'])) {
      throw new Error('Engine needs a run method')
    }

    // This is only allowed if now engine with the same id exists.
    if (!(_.isUndefined(engines[id]) && _.isUndefined(_config[id]))) {
      var error = new Error("Engine '" + id + "' already registered.", 'ERR_ENGINE_EXISTS')
      error.engine = engines[id]
      error.config = _config[id]
      throw error
    }

    var _engines = _.clone(engines)
    _engines[id] = engine
    var _defaultConfig = {}
    _defaultConfig[id] = engine.defaultConfig
    return new Customize(_defaultConfig, _config, _engines)

  }

  /**
   * Creates a new instance of Customize. The config of the current Customize
   * are used as default values and are overridden by the config provided as parameter.
   * @param {object} config config overriding the config of this builder
   * @return {Customize} new Builder instance
   */
  this.merge = function (config) {
    if (_.isUndefined(config)) {
      throw new Error("Cannot merge undefined 'config'")
    }

    debug('Calling merge', config)

    // Assert that for each key in the other configuration, there is an engine present
    // Apply engine preprocessor to each config
    var preprocessedConfig = _.mapValues(config, function (value, key) {
      var engine = engines[key]
      if (_.isUndefined(engine)) {
        throw new Error("Engine '" + key + "' not found. Refusing to store configuration")
      }
      // Load preprocessor with identity as default
      var preprocessor = engine.preprocessConfig || _.identity
      return preprocessor(Q(value)).then(function (config) {
        debug('Merging preprocessed config', config)
        return config
      })
    })
    return new Customize(preprocessedConfig, _config, engines)
  }

  /**
   * Inherit configuration config from another module.
   * `require("Customize-modulename")` usually return a function(builder)
   * and this functions needs to be passed in here.
   * A new Customize will be returned that overrides the current config
   * with config from the builderFunction's result.
   * @param {function} builderFunction  that receives a Customize as paramater
   *  and returns a Customize with changed configuration.
   * @return {Customize} the result of the builderFunction
   */
  this.load = function (builderFunction) {
    if (builderFunction.package) {
      console.log('Loading', builderFunction.package.name, builderFunction.package.version)
    }
    return builderFunction(this)
  }

  /**
   * Build the configured Bootprint-instance.
   * @return {Promise<object>} a promise for the whole configuration
   */
  this.build = function () {
    return deep(_config).then(function (config) {
      debug('Building', config)
      return config
    })
  }

  /**
   * Run each engine with its part of the config.
   */
  this.run = function () {
    return this.build().then(function (resolvedConfig) {
      var result = _.mapValues(engines, function (engine, key) {
        return engine.run(resolvedConfig[key])
      })
      return deep(result)
    })
  }

}

/**
 * Create a new Customize object with
 * @returns {Customize}
 */
module.exports = function () {
  return new Customize({}, {}, {})
}

/**
 * @readonly
 */
module.exports.withParent = require('./lib/withParent')

/**
 * @readonly
 */
module.exports.leaf = require('./lib/leaf')

/**
 * Customize has predefined override rules for merging configs.
 *
 * * If the overriding object has a `_ro_custom_overrider` function-property,
 *   it is called to perform the merger.
 * * Arrays are concatenated
 * * Promises are resolved and the results are merged
 *
 *
 * @param a
 * @param b
 * @param propertyName
 * @returns {*}
 */
function customOverrider (a, b, propertyName) {
  if (_.isUndefined(b)) {
    return a
  }

  if (_.isUndefined(a)) {
    // Invoke default overrider
    return undefined
  }

  // Some objects have custom overriders
  if (_.isFunction(b._customize_custom_overrider)) {
    return b._customize_custom_overrider(a, b, propertyName)
  }

  // Arrays should be concatenated
  if (_.isArray(a)) {
    return a.concat(b)
  }

  // Merge values resolving promises, if they are not leaf-promises
  if (Q.isPromiseAlike(a) || Q.isPromiseAlike(b)) {
    return Q.all([a, b]).spread(function (_a, _b) {
      // Merge the promise results
      return _.merge({}, {x: _a}, {x: _b}, customOverrider).x
    })
  }

}

/**
 * @readonly
 * @type {customOverrider}
 */
module.exports.overrider = customOverrider
<commit_msg>Handle non-promise return-values from `preprocessConfig`<commit_after>/*!
 * customize <https://github.com/nknapp/ride-over>
 *
 * Copyright (c) 2015 Nils Knappmeier.
 * Released under the MIT license.
 */

'use strict'

/**
 * Use the `debug`-module to provide debug output if needed
 */
var debug = require('debug')('customize:base')
var debugState = require('debug')('customize:state')
var Q = require('q')
var deep = require('q-deep')
var _ = require('lodash')

/**
 *
 * @param config
 * @param parentConfig
 * @param {object<function>} engines
 * @constructor
 */
function Customize (config, parentConfig, engines) {
  var _config = _.merge({}, parentConfig, config, customOverrider)
  deep(_config).done(function (config) {
    debugState('New configuration', config)
  })

  /**
   * Register an engine with a default config
   * @param {string} id the identifier of the engine (also within the config)
   * @param {function} engine
   */
  this.registerEngine = function (id, engine) {
    debug("Registering engine '" + id + "'")
    if (!_.isString(id)) {
      throw new Error('Engine-id must be a string, but is ' + id)
    }
    if (id.substr(0, 1) === '_') {
      throw new Error("Engine-id may not start with an underscore ('_')")
    }
    if (_.isUndefined(engine['run'])) {
      throw new Error('Engine needs a run method')
    }

    // This is only allowed if now engine with the same id exists.
    if (!(_.isUndefined(engines[id]) && _.isUndefined(_config[id]))) {
      var error = new Error("Engine '" + id + "' already registered.", 'ERR_ENGINE_EXISTS')
      error.engine = engines[id]
      error.config = _config[id]
      throw error
    }

    var _engines = _.clone(engines)
    _engines[id] = engine
    var _defaultConfig = {}
    _defaultConfig[id] = engine.defaultConfig
    return new Customize(_defaultConfig, _config, _engines)

  }

  /**
   * Creates a new instance of Customize. The config of the current Customize
   * are used as default values and are overridden by the config provided as parameter.
   * @param {object} config config overriding the config of this builder
   * @return {Customize} new Builder instance
   */
  this.merge = function (config) {
    if (_.isUndefined(config)) {
      throw new Error("Cannot merge undefined 'config'")
    }

    debug('Calling merge', config)

    // Assert that for each key in the other configuration, there is an engine present
    // Apply engine preprocessor to each config
    var preprocessedConfig = _.mapValues(config, function (value, key) {
      var engine = engines[key]
      if (_.isUndefined(engine)) {
        throw new Error("Engine '" + key + "' not found. Refusing to store configuration")
      }
      // Load preprocessor with identity as default
      var preprocessor = engine.preprocessConfig || _.identity
      return Q(preprocessor(Q(value))).then(function (config) {
        debug('Merging preprocessed config', config)
        return config
      })
    })
    return new Customize(preprocessedConfig, _config, engines)
  }

  /**
   * Inherit configuration config from another module.
   * `require("Customize-modulename")` usually return a function(builder)
   * and this functions needs to be passed in here.
   * A new Customize will be returned that overrides the current config
   * with config from the builderFunction's result.
   * @param {function} builderFunction  that receives a Customize as paramater
   *  and returns a Customize with changed configuration.
   * @return {Customize} the result of the builderFunction
   */
  this.load = function (builderFunction) {
    if (builderFunction.package) {
      console.log('Loading', builderFunction.package.name, builderFunction.package.version)
    }
    return builderFunction(this)
  }

  /**
   * Build the configured Bootprint-instance.
   * @return {Promise<object>} a promise for the whole configuration
   */
  this.build = function () {
    return deep(_config).then(function (config) {
      debug('Building', config)
      return config
    })
  }

  /**
   * Run each engine with its part of the config.
   */
  this.run = function () {
    return this.build().then(function (resolvedConfig) {
      var result = _.mapValues(engines, function (engine, key) {
        return engine.run(resolvedConfig[key])
      })
      return deep(result)
    })
  }

}

/**
 * Create a new Customize object with
 * @returns {Customize}
 */
module.exports = function () {
  return new Customize({}, {}, {})
}

/**
 * @readonly
 */
module.exports.withParent = require('./lib/withParent')

/**
 * @readonly
 */
module.exports.leaf = require('./lib/leaf')

/**
 * Customize has predefined override rules for merging configs.
 *
 * * If the overriding object has a `_ro_custom_overrider` function-property,
 *   it is called to perform the merger.
 * * Arrays are concatenated
 * * Promises are resolved and the results are merged
 *
 *
 * @param a
 * @param b
 * @param propertyName
 * @returns {*}
 */
function customOverrider (a, b, propertyName) {
  if (_.isUndefined(b)) {
    return a
  }

  if (_.isUndefined(a)) {
    // Invoke default overrider
    return undefined
  }

  // Some objects have custom overriders
  if (_.isFunction(b._customize_custom_overrider)) {
    return b._customize_custom_overrider(a, b, propertyName)
  }

  // Arrays should be concatenated
  if (_.isArray(a)) {
    return a.concat(b)
  }

  // Merge values resolving promises, if they are not leaf-promises
  if (Q.isPromiseAlike(a) || Q.isPromiseAlike(b)) {
    return Q.all([a, b]).spread(function (_a, _b) {
      // Merge the promise results
      return _.merge({}, {x: _a}, {x: _b}, customOverrider).x
    })
  }

}

/**
 * @readonly
 * @type {customOverrider}
 */
module.exports.overrider = customOverrider
<|endoftext|>


<commit_before>function start_game() {
	//load elements
	sprite = document.getElementById("sprite");
	jump = false;
	jump_x = 2;
	var x = parseInt(sprite.getAttribute("cx").slice(0,-1));
	move_sprite(2, 0.1, x, false);
			//velocity, gravity, x, side
}

function check_bounds(x, velocity) {
	//return true if sprite is in bounds
	if (0 < x + velocity && x + velocity < 100) {
		return true;
	} else {
		return false;
	}
}

function apply_score() {
	var score = document.getElementById("score");
	score.textContent = parseInt(score.textContent) + 1;
}

function move_sprite(velocity, gravity, x, left_side) {
	//moves sprite, requestAnimationFrame calls this function repetedly

	if (x < 50) {
		//sprite is on left side
		if (left_side !== true) {
			//apply score if not yet applied
			left_side = true;
			apply_score();
		}
		//keep in bounds
		if (!check_bounds(x, velocity)) {
			velocity = Math.abs(velocity) + gravity;
		}else {
			velocity = velocity + gravity;
		}
		//if jump on left side
		if (velocity > 0 && jump) {
			//if going towards center, move sprite towards bounds
			velocity = velocity - jump_x;
			jump = false;
		}else if (jump) {
			//if going towards bounds, move sprite towards center
			velocity = velocity + jump_x;
			jump = false;
		}
	} else {
		//sprite on right side
		if (left_side !== false) {
			//apply score if not yet applied
			left_side = false;
			apply_score();
		}
		//keep in bounds
		if (!check_bounds(x, velocity)) {
			velocity = -(velocity) - gravity;
		} else {
			velocity = velocity - gravity;
		}
		//if jump on right side
		if (jump && velocity < 0) {
			//if going towards center, move in opposite direction
			velocity = velocity + jump_x;
			jump = false;
		} else if (jump) {
			//if going towards bounds, move in opposite direction
			velocity = velocity - jump_x;
			jump = false;
		}
	}

	//set new position
	var new_x = x + velocity;	//sets x
	sprite.setAttribute("cx", new_x + "%");

	window.requestAnimationFrame( function() {
		move_sprite(velocity, gravity, new_x, left_side);
	});
}

function entry() {
	jump = true;
}
<commit_msg>Add function to make SVG rect<commit_after>function start_game() {
	//load elements
	sprite = document.getElementById("sprite");
	svg = document.getElementsByTagName("svg")[0];
	console.log(svg);
	jump = false;
	jump_x = 2;
	var x = parseInt(sprite.getAttribute("cx").slice(0,-1));
	move_sprite(2, 0.1, x, false);
			//velocity, gravity, x, side
}

function make_rect(y, h) {
	var rect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
	rect.setAttributeNS(null, "x", "49%");
	rect.setAttributeNS(null, "y", y + "%");
	rect.setAttributeNS(null, "width", "2%");
	rect.setAttributeNS(null, "height", h +"%");
	rect.setAttributeNS(null, "fill", "white");
	svg.appendChild(rect);
	console.log(rect);
}

function check_bounds(x, velocity) {
	//return true if sprite is in bounds
	if (0 < x + velocity && x + velocity < 100) {
		return true;
	} else {
		return false;
	}
}

function apply_score() {
	var score = document.getElementById("score");
	score.textContent = parseInt(score.textContent) + 1;
}

function move_sprite(velocity, gravity, x, left_side) {
	//moves sprite, requestAnimationFrame calls this function repetedly

	if (x < 50) {
		//sprite is on left side
		if (left_side !== true) {
			//apply score if not yet applied
			left_side = true;
			apply_score();
		}
		//keep in bounds
		if (!check_bounds(x, velocity)) {
			velocity = Math.abs(velocity) + gravity;
		}else {
			velocity = velocity + gravity;
		}
		//if jump on left side
		if (velocity > 0 && jump) {
			//if going towards center, move sprite towards bounds
			velocity = velocity - jump_x;
			jump = false;
		}else if (jump) {
			//if going towards bounds, move sprite towards center
			velocity = velocity + jump_x;
			jump = false;
		}
	} else {
		//sprite on right side
		if (left_side !== false) {
			//apply score if not yet applied
			left_side = false;
			apply_score();
		}
		//keep in bounds
		if (!check_bounds(x, velocity)) {
			velocity = -(velocity) - gravity;
		} else {
			velocity = velocity - gravity;
		}
		//if jump on right side
		if (jump && velocity < 0) {
			//if going towards center, move in opposite direction
			velocity = velocity + jump_x;
			jump = false;
		} else if (jump) {
			//if going towards bounds, move in opposite direction
			velocity = velocity - jump_x;
			jump = false;
		}
	}

	//set new position
	var new_x = x + velocity;	//sets x
	sprite.setAttribute("cx", new_x + "%");

	window.requestAnimationFrame( function() {
		move_sprite(velocity, gravity, new_x, left_side);
	});
}

function entry() {
	jump = true;
}
<|endoftext|>


<commit_before>'use strict';

module.exports = require('./src/nunjucks-intl');
<commit_msg>Fixes main file pointing to src rather than dist. Closes #47<commit_after>'use strict';

module.exports = require('./dist/nunjucks-intl');
<|endoftext|>


<commit_before>#! /usr/bin/env node

/*
 * Module dependencies.
 */
var program = require('commander');
var chalk = require('chalk');

// Googleit's version
// Only change this in release branch
program.version('1.1.9');

// Print red error message
function printConsoleError(message) {
  var fullMessage = '\n    ' + message + '\n';
  console.error(chalk.red(fullMessage));
}

// Check system is running on macOS or not => Show error message and retrun false
function checkEnvironment(callback) {
  var exec = require('child_process').exec;
  var cmd = 'uname -s';
  var result;
  exec(cmd, function(error, stdout) {
    if (!stdout.includes('Darwin')) {
      var errorMessage = 'googleit only supports macOS. Using other OS may causing error.';
      printConsoleError(errorMessage);
      result = false;
      callback(result);
      process.exit(1);
    } else {
      result = true;
      callback(result);
    }
  });
}

// Callback for checkEnvironment
var checkEnvironmentIsTrue = function(param) {
  if (param === true) {
    argumentsExist(typeof wordValue);
  }
};

// Error message when no any argument
function argumentsExist(wordValue) {
  if (wordValue === 'undefined') {
    var errorMessage = 'Please enter search terms. "googleit <terms>"';
    printConsoleError(errorMessage);
    process.exit(1);
  }
}

// ReplaceAll function(replaceThisWord, replacement)
// Use in multiple terms search
String.prototype.replaceAll = function(search, replacement) {
  var target = this;
  return target.split(search).join(replacement);
};

// CheckEnvironment before check argumentsExistence
checkEnvironment(checkEnvironmentIsTrue);

// Example command usages in --help
program.on('--help', function() {
  console.log('  Examples:');
  console.log('');
  console.log('    $ googleit weather-tomorrow');
  console.log('    $ googleit -i cat');
  console.log('    $ googleit -b harry-potter');
  console.log('');
});

program
  .arguments('<word>')
  .option('-i, --image', 'Search Image on Google')
  .option('-n, --news', 'Search News on Google')
  .option('-v, --video', 'Search Video on Google')
  .option('-p, --patent', 'Search Patent on Google')
  .option('-b, --book', 'Search Book on Google')
  .option('-e, --except <exception>', 'Search with exception')

  .action(function(word) {

    wordValue = word;
    word = word.replaceAll('-', '%20');

    if (program.except) {
      word = word + '%20-' + program.except;
    }

    var exec = require('child_process').exec;
    var cmd = 'open https://google.com/#q=' + word;
    var base = "open \'https://google.com/search?q=";
    if (program.image) {
      cmd = base + word + "&tbm=isch\'";
      exec(cmd);
    } else if (program.news) {
      cmd = base + word + "&tbm=nws\'";
      exec(cmd);
    } else if (program.video) {
      cmd = base + word + "&tbm=vid\'";
      exec(cmd);
    } else if (program.patent) {
      cmd = base + word + "&tbm=pts\'";
      exec(cmd);
    } else if (program.book) {
      cmd = base + word + "&tbm=bks\'";
      exec(cmd);
    } else {
      exec(cmd);
    }
  })
  .parse(process.argv);
<commit_msg>:fire: Fix undefined<commit_after>#! /usr/bin/env node

/*
 * Module dependencies.
 */
var program = require('commander');
var chalk = require('chalk');

// Googleit's version
// Only change this in release branch
program.version('1.1.9');

// Print red error message
function printConsoleError(message) {
  var fullMessage = '\n    ' + message + '\n';
  console.error(chalk.red(fullMessage));
}

// Check system is running on macOS or not => Show error message and retrun false
function checkEnvironment(callback) {
  var exec = require('child_process').exec;
  var cmd = 'uname -s';
  var result;
  exec(cmd, function(error, stdout) {
    if (!stdout.includes('Darwin')) {
      var errorMessage = 'googleit only supports macOS. Using other OS may causing error.';
      printConsoleError(errorMessage);
      result = false;
      callback(result);
      process.exit(1);
    } else {
      result = true;
      callback(result);
    }
  });
}

// Callback for checkEnvironment
var checkEnvironmentIsTrue = function(param) {
  if (param === true) {
    argumentsExist(typeof wordValue);
  }
};

// Error message when no any argument
function argumentsExist(wordValue) {
  if (wordValue === 'undefined') {
    var errorMessage = 'Please enter search terms. "googleit <terms>"';
    printConsoleError(errorMessage);
    process.exit(1);
  }
}

// ReplaceAll function(replaceThisWord, replacement)
// Use in multiple terms search
String.prototype.replaceAll = function(search, replacement) {
  var target = this;
  return target.split(search).join(replacement);
};

// CheckEnvironment before check argumentsExistence
checkEnvironment(checkEnvironmentIsTrue);

// Example command usages in --help
program.on('--help', function() {
  console.log('  Examples:');
  console.log('');
  console.log('    $ googleit weather-tomorrow');
  console.log('    $ googleit -i cat');
  console.log('    $ googleit -b harry-potter');
  console.log('');
});

var wordValue;

program
  .arguments('<word>')
  .option('-i, --image', 'Search Image on Google')
  .option('-n, --news', 'Search News on Google')
  .option('-v, --video', 'Search Video on Google')
  .option('-p, --patent', 'Search Patent on Google')
  .option('-b, --book', 'Search Book on Google')
  .option('-e, --except <exception>', 'Search with exception')

  .action(function(word) {

    wordValue = word;
    word = word.replaceAll('-', '%20');

    if (program.except) {
      word = word + '%20-' + program.except;
    }

    var exec = require('child_process').exec;
    var cmd = 'open https://google.com/#q=' + word;
    var base = "open \'https://google.com/search?q=";
    if (program.image) {
      cmd = base + word + "&tbm=isch\'";
      exec(cmd);
    } else if (program.news) {
      cmd = base + word + "&tbm=nws\'";
      exec(cmd);
    } else if (program.video) {
      cmd = base + word + "&tbm=vid\'";
      exec(cmd);
    } else if (program.patent) {
      cmd = base + word + "&tbm=pts\'";
      exec(cmd);
    } else if (program.book) {
      cmd = base + word + "&tbm=bks\'";
      exec(cmd);
    } else {
      exec(cmd);
    }
  })
  .parse(process.argv);
<|endoftext|>


<commit_before>const uuid = require('uuid');
const fs = require('fs');
const path = require('path');

const pushMessageScript = fs.readFileSync(path.join(__dirname, 'lua/pushMessage.lua')).toString();
const getBatchScript = fs.readFileSync(path.join(__dirname, 'lua/getBatch.lua')).toString();
const removeMessagesScript = fs.readFileSync(path.join(__dirname, 'lua/removeMessages.lua')).toString();
const reinsertUnprocessedScript = fs.readFileSync(path.join(__dirname, 'lua/reinsertUnprocessed.lua')).toString();

function BQueue(redisClient, queueCount = 1) {
  if (!Number.isInteger(queueCount)) {
    throw new Error('Queue count must be an integer!');
  } else if (queueCount < 1 || queueCount > 100) {
    throw new Error('Queue count must be between 1 and 100!');
  }

  this.redisClient = redisClient;
  this.queueCount = queueCount;

  this.redisClient.defineCommand('pushMessage', {
    numberOfKeys: 1,
    lua: pushMessageScript
  });
  this.redisClient.defineCommand('getBatch', {
    numberOfKeys: 1,
    lua: getBatchScript
  });
  this.redisClient.defineCommand('removeMessages', {
    numberOfKeys: 1,
    lua: removeMessagesScript
  });
  this.redisClient.defineCommand('reinsertUnprocessed', {
    numberOfKeys: 1,
    lua: reinsertUnprocessedScript
  });
}

BQueue.prototype.pushMessage = function(message = '') {
  return new Promise((resolve, reject) => {
    const queueNumber = Math.floor(Math.random()*this.queueCount);
    const queue = 'bqueue:' + queueNumber;
    const id = uuid.v4();
    this.redisClient.pushMessage(queue, id, JSON.stringify({id, message}), (err, result) => {
      if (err) {
        return reject(err);
      } else {
        return resolve(result);
      }
    });
  });
};

BQueue.prototype.getBatch = function(batchSize = 1, processingTimeout = 5000) {
  if (!Number.isInteger(batchSize)) {
    throw new Error('Batch size must be an integer!');
  } else if (batchSize < 1 || batchSize > 1000) {
    throw new Error('Batch batchSize must be between 1 and 1000!');
  } else if (!Number.isInteger(processingTimeout)) {
    throw new Error('Processing timeout must be an integer!');
  } else if (processingTimeout < 1000 || processingTimeout > 604800000) {
    throw new Error('Processing timeout must be between 1000 and 604800000!');
  }
  return new Promise((resolve, reject) => {
    const queueNumber = Math.floor(Math.random()*this.queueCount);
    const queue = 'bqueue:' + queueNumber;
    this.redisClient.getBatch(queue, batchSize, processingTimeout, (err, results) => {
      if (err) {
        return reject(err);
      } else {
        const messages = results.map(value => JSON.parse(value));
        return resolve({
          messages: messages,
          remove: () => {
            return new Promise((resolve, reject) => {
              const ids = messages.map(message => message.id);
              this.redisClient.removeMessages(queue, ...ids, (err, results) => {
                if (err) {
                  return reject(err);
                } else {
                  return resolve(results);
                }
              });
            });
          }
        });
      }
    });
  });
};

BQueue.prototype.reinsertUnprocessed = function() {
  return new Promise((resolve, reject) => {
    const queueNumber = Math.floor(Math.random()*this.queueCount);
    const queue = 'bqueue:' + queueNumber;
    this.redisClient.reinsertUnprocessed(queue, (err, result) => {
      if (err) {
        return reject(err);
      } else {
        return resolve(result);
      }
    });
  });
};

module.exports = BQueue;
<commit_msg>Improve parameter validation<commit_after>const uuid = require('uuid');
const fs = require('fs');
const path = require('path');

const pushMessageScript = fs.readFileSync(path.join(__dirname, 'lua/pushMessage.lua')).toString();
const getBatchScript = fs.readFileSync(path.join(__dirname, 'lua/getBatch.lua')).toString();
const removeMessagesScript = fs.readFileSync(path.join(__dirname, 'lua/removeMessages.lua')).toString();
const reinsertUnprocessedScript = fs.readFileSync(path.join(__dirname, 'lua/reinsertUnprocessed.lua')).toString();

function BQueue(redisClient, queueCount = 1) {
  if (!Number.isInteger(queueCount)) {
    throw new Error('Queue count must be an integer!');
  } else if (queueCount < 1 || queueCount > 100) {
    throw new Error('Queue count must be between 1 and 100!');
  }

  this.redisClient = redisClient;
  this.queueCount = queueCount;

  this.redisClient.defineCommand('pushMessage', {
    numberOfKeys: 1,
    lua: pushMessageScript
  });
  this.redisClient.defineCommand('getBatch', {
    numberOfKeys: 1,
    lua: getBatchScript
  });
  this.redisClient.defineCommand('removeMessages', {
    numberOfKeys: 1,
    lua: removeMessagesScript
  });
  this.redisClient.defineCommand('reinsertUnprocessed', {
    numberOfKeys: 1,
    lua: reinsertUnprocessedScript
  });
}

BQueue.prototype.pushMessage = function(message = '') {
  return new Promise((resolve, reject) => {
    const queueNumber = Math.floor(Math.random()*this.queueCount);
    const queue = 'bqueue:' + queueNumber;
    const id = uuid.v4();
    this.redisClient.pushMessage(queue, id, JSON.stringify({id, message}), (err, result) => {
      if (err) {
        return reject(err);
      } else {
        return resolve(result);
      }
    });
  });
};

BQueue.prototype.getBatch = function(batchSize = 1, processingTimeout = 5000) {
  return new Promise((resolve, reject) => {
    if (!Number.isInteger(batchSize)) {
      return reject(Error('Batch size must be an integer!'));
    } else if (batchSize < 1 || batchSize > 1000) {
      return reject(Error('Batch batchSize must be between 1 and 1000!'));
    } else if (!Number.isInteger(processingTimeout)) {
      return reject(Error('Processing timeout must be an integer!'));
    } else if (processingTimeout < 1000 || processingTimeout > 604800000) {
      return reject(Error('Processing timeout must be between 1000 and 604800000!'));
    }
    const queueNumber = Math.floor(Math.random()*this.queueCount);
    const queue = 'bqueue:' + queueNumber;
    this.redisClient.getBatch(queue, batchSize, processingTimeout, (err, results) => {
      if (err) {
        return reject(err);
      } else {
        const messages = results.map(value => JSON.parse(value));
        return resolve({
          messages: messages,
          remove: () => {
            return new Promise((resolve, reject) => {
              const ids = messages.map(message => message.id);
              this.redisClient.removeMessages(queue, ...ids, (err, results) => {
                if (err) {
                  return reject(err);
                } else {
                  return resolve(results);
                }
              });
            });
          }
        });
      }
    });
  });
};

BQueue.prototype.reinsertUnprocessed = function() {
  return new Promise((resolve, reject) => {
    const queueNumber = Math.floor(Math.random()*this.queueCount);
    const queue = 'bqueue:' + queueNumber;
    this.redisClient.reinsertUnprocessed(queue, (err, result) => {
      if (err) {
        return reject(err);
      } else {
        return resolve(result);
      }
    });
  });
};

module.exports = BQueue;
<|endoftext|>