<commit_before>var fs = require('fs'),
    path = require('path'),
    async = require('../deps/async'),
    utils = require('./utils'),
    Script = process.binding('evals').Script;

// As modules are added, their original file paths are added to this object
// eg: {'lib': {'mymodule': '/home/user/project/lib/mymodule.js'}, ...}
exports.originalPaths = {};

exports.load = function (dir, doc, callback) {
    var paths = doc.settings.modules;
    if (!Array.isArray(paths)) {
        paths = [paths];
    }
    async.concat(paths, function (p, cb) {
        exports.find(path.join(dir, p), dir, cb);
    },
    function (err, files) {
        if (err) {
            return callback(err);
        }
        exports.addFiles(dir, files, doc, function (err) {
            exports.addKansoModules(doc, callback);
        });
    });
};

exports.addKansoModules = function (doc, callback) {
    var default_dir = path.normalize(__dirname + '/../commonjs');

    exports.findKansoModules(function (err, files) {
        if (err) {
            return callback(err);
        }
        exports.addFiles(default_dir, files, doc, callback);
    });
};

exports.findKansoModules = function (callback) {
    var default_dir = path.normalize(__dirname + '/../commonjs');
    exports.find(default_dir, default_dir, function (err, files) {
        if (err) {
            return callback(err);
        }
        if (!files.length) {
            return callback(new Error(
                'Couldn\'t find kanso core commonjs modules in: ' +
                default_dir
            ));
        }
        try {
            // strip out auto-generated modules
            files = files.filter(function (f) {
                return (
                    f !== default_dir + '/kanso/templates.js' &&
                    f !== default_dir + '/kanso/settings.js'
                );
            });
        }
        catch (e) {
            callback(e);
        }
        callback(null, files);
    });
};

exports.addFiles = function (dir, files, doc, callback) {
    dir = utils.abspath(dir);
    async.forEach(files, function (f, cb) {
        exports.addFile(dir, utils.abspath(f), doc, cb);
    }, callback);
};

exports.addFile = function (dir, file, doc, callback) {
    fs.readFile(file, function (err, content) {
        if (err) {
            return callback(err);
        }
        var rel = utils.relpath(file, dir);
        var module_path = rel.replace(/\.js$/, '');
        var src = content.toString();
        utils.setPropertyPath(doc, rel, src);
        utils.setPropertyPath(exports.originalPaths, rel, file);
        exports.wrap(doc, module_path, src);

        callback();
    });
};

exports.wrap = function (doc, module_path, src) {
    // wrap the module and add as an attachment
    var wrapped = '/********** ' + module_path + ' **********/\n\n' +
        'kanso.moduleCache["' +
            module_path.replace('"', '\\"') +
        '"] = {load: (function (module, exports, require) {\n\n' +
            src +
        '\n\n})};\n\n';

    if (!doc._attachments) {
        doc._attachments = {};
    }
    if (!doc.hasOwnProperty('_wrapped_modules')) {
        doc._wrapped_modules = '';
    }
    doc._wrapped_modules += wrapped;
    // doc._wrapped_modules is appended to kanso.js and base64 encoded
    // in lib/app.js
};

exports.find = function (p, projectdir, callback) {
    utils.find(p, exports.filenameFilter(projectdir), callback);
};

exports.filenameFilter = function (projectdir) {
    return function (f) {
        var relpath = utils.relpath(f, projectdir);
        // should not start with a '.'
        if (/^\./.test(relpath)) {
            return false;
        }
        // should not contain a file or folder starting with a '.'
        if (/\/\./.test(relpath)) {
            return false;
        }
        // should have a .js extension
        if (!/\.js$/.test(f)) {
            return false;
        }
        return true;
    };
};

/**
 * Loads a commonjs module from the loaded design document, returning
 * the exported properties. The current_dir and target parameters are not the
 * path of the module on the filesystem, but rather the path of the module
 * within couchdb, root ('/') being the design doc itself.
 *
 * @param {Object} module_cache
 * @param {Object} doc
 * @param {String} current_dir
 * @param {String} target
 * @param {Object} context - optional, extends sandbox object
 */

exports.require = function (module_cache, doc, current_dir, target, context) {
    if (target.charAt(0) !== '.') {
        current_dir = '/';
    }
    var p = path.normalize(path.join(current_dir, target));
    if (module_cache[p]) {
        return module_cache[p];
    }

    var nodes = p.split('/').slice(1);
    var content = nodes.reduce(function (a, x) {
        if (a[x] === undefined) {
            throw new Error('Could not require module: ' + target);
        }
        a = a[x];
        return a;
    }, doc);

    var sandbox = {
        module: {exports: {}},
        require: async.apply(
            exports.require, module_cache, doc, path.dirname(p)
        ),
        log: function () {
            console.log.apply(console, arguments);
        }
    };
    sandbox.exports = sandbox.module.exports;

    // copy context into sandbox
    if (context) {
        Object.keys(context).forEach(function (k) {
            sandbox[k] = context[k];
        });
    }

    // Create a placeholder for this module's exports so circular requires
    // are possible. TODO: node.js uses a loaded = false attribute on the
    // cached module object to mark this as a placeholder.
    module_cache[p] = {};

    var filename;
    try {
        filename = utils.getPropertyPath(
            exports.originalPaths, p.substr(1), true
        );
        var s = new Script(content, filename).runInNewContext(sandbox);
    }
    catch (e) {
        if (e instanceof SyntaxError && filename) {
            // gives a better syntax error than runInNewContext
            // with filename and line number
            require(filename);
        }
        else {
            throw e;
        }
    }
    module_cache[p] = sandbox.module.exports;
    return module_cache[p];
};
<commit_msg>add fix for node v0.5.0-pre, use evals.NodeScript when evals.Script not available, closes #46<commit_after>var fs = require('fs'),
    path = require('path'),
    async = require('../deps/async'),
    utils = require('./utils'),
    evals = process.binding('evals'),
    Script = evals.Script || evals.NodeScript;

// As modules are added, their original file paths are added to this object
// eg: {'lib': {'mymodule': '/home/user/project/lib/mymodule.js'}, ...}
exports.originalPaths = {};

exports.load = function (dir, doc, callback) {
    var paths = doc.settings.modules;
    if (!Array.isArray(paths)) {
        paths = [paths];
    }
    async.concat(paths, function (p, cb) {
        exports.find(path.join(dir, p), dir, cb);
    },
    function (err, files) {
        if (err) {
            return callback(err);
        }
        exports.addFiles(dir, files, doc, function (err) {
            exports.addKansoModules(doc, callback);
        });
    });
};

exports.addKansoModules = function (doc, callback) {
    var default_dir = path.normalize(__dirname + '/../commonjs');

    exports.findKansoModules(function (err, files) {
        if (err) {
            return callback(err);
        }
        exports.addFiles(default_dir, files, doc, callback);
    });
};

exports.findKansoModules = function (callback) {
    var default_dir = path.normalize(__dirname + '/../commonjs');
    exports.find(default_dir, default_dir, function (err, files) {
        if (err) {
            return callback(err);
        }
        if (!files.length) {
            return callback(new Error(
                'Couldn\'t find kanso core commonjs modules in: ' +
                default_dir
            ));
        }
        try {
            // strip out auto-generated modules
            files = files.filter(function (f) {
                return (
                    f !== default_dir + '/kanso/templates.js' &&
                    f !== default_dir + '/kanso/settings.js'
                );
            });
        }
        catch (e) {
            callback(e);
        }
        callback(null, files);
    });
};

exports.addFiles = function (dir, files, doc, callback) {
    dir = utils.abspath(dir);
    async.forEach(files, function (f, cb) {
        exports.addFile(dir, utils.abspath(f), doc, cb);
    }, callback);
};

exports.addFile = function (dir, file, doc, callback) {
    fs.readFile(file, function (err, content) {
        if (err) {
            return callback(err);
        }
        var rel = utils.relpath(file, dir);
        var module_path = rel.replace(/\.js$/, '');
        var src = content.toString();
        utils.setPropertyPath(doc, rel, src);
        utils.setPropertyPath(exports.originalPaths, rel, file);
        exports.wrap(doc, module_path, src);

        callback();
    });
};

exports.wrap = function (doc, module_path, src) {
    // wrap the module and add as an attachment
    var wrapped = '/********** ' + module_path + ' **********/\n\n' +
        'kanso.moduleCache["' +
            module_path.replace('"', '\\"') +
        '"] = {load: (function (module, exports, require) {\n\n' +
            src +
        '\n\n})};\n\n';

    if (!doc._attachments) {
        doc._attachments = {};
    }
    if (!doc.hasOwnProperty('_wrapped_modules')) {
        doc._wrapped_modules = '';
    }
    doc._wrapped_modules += wrapped;
    // doc._wrapped_modules is appended to kanso.js and base64 encoded
    // in lib/app.js
};

exports.find = function (p, projectdir, callback) {
    utils.find(p, exports.filenameFilter(projectdir), callback);
};

exports.filenameFilter = function (projectdir) {
    return function (f) {
        var relpath = utils.relpath(f, projectdir);
        // should not start with a '.'
        if (/^\./.test(relpath)) {
            return false;
        }
        // should not contain a file or folder starting with a '.'
        if (/\/\./.test(relpath)) {
            return false;
        }
        // should have a .js extension
        if (!/\.js$/.test(f)) {
            return false;
        }
        return true;
    };
};

/**
 * Loads a commonjs module from the loaded design document, returning
 * the exported properties. The current_dir and target parameters are not the
 * path of the module on the filesystem, but rather the path of the module
 * within couchdb, root ('/') being the design doc itself.
 *
 * @param {Object} module_cache
 * @param {Object} doc
 * @param {String} current_dir
 * @param {String} target
 * @param {Object} context - optional, extends sandbox object
 */

exports.require = function (module_cache, doc, current_dir, target, context) {
    if (target.charAt(0) !== '.') {
        current_dir = '/';
    }
    var p = path.normalize(path.join(current_dir, target));
    if (module_cache[p]) {
        return module_cache[p];
    }

    var nodes = p.split('/').slice(1);
    var content = nodes.reduce(function (a, x) {
        if (a[x] === undefined) {
            throw new Error('Could not require module: ' + target);
        }
        a = a[x];
        return a;
    }, doc);

    var sandbox = {
        module: {exports: {}},
        require: async.apply(
            exports.require, module_cache, doc, path.dirname(p)
        ),
        log: function () {
            console.log.apply(console, arguments);
        }
    };
    sandbox.exports = sandbox.module.exports;

    // copy context into sandbox
    if (context) {
        Object.keys(context).forEach(function (k) {
            sandbox[k] = context[k];
        });
    }

    // Create a placeholder for this module's exports so circular requires
    // are possible. TODO: node.js uses a loaded = false attribute on the
    // cached module object to mark this as a placeholder.
    module_cache[p] = {};

    var filename;
    try {
        filename = utils.getPropertyPath(
            exports.originalPaths, p.substr(1), true
        );
        var s = new Script(content, filename).runInNewContext(sandbox);
    }
    catch (e) {
        if (e instanceof SyntaxError && filename) {
            // gives a better syntax error than runInNewContext
            // with filename and line number
            require(filename);
        }
        else {
            throw e;
        }
    }
    module_cache[p] = sandbox.module.exports;
    return module_cache[p];
};
<|endoftext|>


<commit_before>// Load modules

var Events = require('events');
var Http = require('http');
var Https = require('https');
var Os = require('os');
var Hoek = require('hoek');
var Items = require('items');
var Wreck = require('wreck');
var Network = require('./network');
var Package = require('../package.json');
var ProcessMonitor = require('./process');
var Schema = require('./schema');
var System = require('./system');
var Utils = require('./utils');

// Declare internals

var internals = {
    host: Os.hostname(),
    appVer: Package.version
};

internals.defaults = {
    opsInterval: 15000,
    responseEvent: 'tail',
    requestHeaders: false,
    requestPayload: false,
    responsePayload: false,
    extensions: []
};

internals.iterateOverEventHash = function (hash, predicate) {

    var keys = Object.keys(hash);
    for (var k = 0, kl = keys.length; k < kl; ++k) {
        var key = keys[k];
        predicate(key, hash[key]);
    }
};

module.exports = internals.Monitor = function (server, options) {

    options = options || {};

    Hoek.assert(this.constructor === internals.Monitor, 'Monitor must be instantiated using new');
    Hoek.assert(server, 'server required to create monitor');

    options = Hoek.applyToDefaultsWithShallow(internals.defaults, options, ['reporters', 'httpAgents', 'httpsAgents']);

    // Force them to be arrays
    var args = [];
    options.httpAgents = args.concat(options.httpAgents || Http.globalAgent);
    options.httpsAgents = args.concat(options.httpsAgents || Https.globalAgent);

    this.settings = options;
    this._reporters = [];
    this._state = {
        handlers: {},
        extensions: {}
    };
    this._server = server;

    // Options used to create Great Response
    this._responseOptions = {
        requestHeaders: this.settings.requestHeaders,
        requestPayload: this.settings.requestPayload,
        responsePayload: this.settings.responsePayload
    };

    // Validate settings
    Schema.assert('monitorOptions', this.settings);

    // Register as event emitter
    Events.EventEmitter.call(this);
};

Hoek.inherits(internals.Monitor, Events.EventEmitter);

internals.Monitor.prototype.start = function (callback) {

    var self = this;

    var setupOpsMonitoring = function () {

        var pmonitor = ProcessMonitor;
        var os = System;
        var network = new Network.Monitor(self._server);

        var asyncOps = {
            osload: os.loadavg,
            osmem: os.mem,
            osup: os.uptime,
            psup: pmonitor.uptime,
            psmem: pmonitor.memoryUsage,
            psdelay: pmonitor.delay,
            requests: network.requests.bind(network),
            concurrents: network.concurrents.bind(network),
            responseTimes: network.responseTimes.bind(network),
            sockets: network.sockets.bind(network, self.settings.httpAgents, self.settings.httpsAgents)
        };

        // Set ops interval timer

        return function () {

            // Gather operational statistics in parallel

            Items.parallel.execute(asyncOps, function (error, results) {

                if (error) {
                    console.error(error);
                }
                else {
                    results.host = internals.host;
                    self.emit('ops', results);
                }
                network.reset();
            });
        };
    };

    for (var i = 0, il = this.settings.reporters.length; i < il; i++) {

        var item = this.settings.reporters[i];
        var reporter;

        // If it has a reporter constructor, then create a new one, otherwise, assume it is
        // a valid pre-constructed reporter
        if (item.reporter) {

            // If the supply a path or module node, try to load it
            if (typeof item.reporter === 'string') {
                item.reporter = require(item.reporter);
            }

            Hoek.assert(typeof item.reporter === 'function', 'reporter key must be a constructor function');

            item.args = item.args || [];
            // this pointer
            item.args.unshift(null);
            var constructor = item.reporter.bind.apply(item.reporter, item.args);
            reporter = new constructor();
        }
        else {
            reporter = item;
        }

        Hoek.assert(reporter.start && reporter.stop, 'Every reporter object must have a start and stop function.');

        this._reporters.push(reporter);
    }

    Items.serial(this._reporters, function (item, next) {

        item.start(self, next);
    }, function (error) {

        if (error) {
            return callback(error);
        }

        self._state.opsInterval = setInterval(setupOpsMonitoring(), self.settings.opsInterval);
        self._state.opsHandler = self._opsHandler.bind(self);
        self._state.wreckHandler = self._wreckHandler.bind(self);

        self._state.handlers.log = self._logHandler.bind(self);
        self._state.handlers['request-error'] = self._errorHandler.bind(self);
        self._state.handlers[self.settings.responseEvent] = self._responseHandler.bind(self);
        self._state.handlers.request = self._requestLogHandler.bind(self);

        // Initialize Events
        internals.iterateOverEventHash(self._state.handlers, function (event, handler) {

            self._server.on(event, handler);
        });

        self.on('ops', self._state.opsHandler);
        Wreck.on('response', self._state.wreckHandler);

        // Events can not be any of ['log', 'request-error', 'ops', 'request', 'response', 'tail']
        for (var i = 0, il = self.settings.extensions.length; i < il; ++i) {
            var event = self.settings.extensions[i];

            self._state.extensions[event] = self._extensionHandler.bind(self, event);
            self._server.on(self.settings.extensions[i], self._state.extensions[event]);
        }

        return callback();
    });
};

internals.Monitor.prototype.stop = function () {

    var self = this;
    var state = this._state;
    clearInterval(state.opsInterval);

    this.removeListener('ops', state.opsHandler);
    Wreck.removeListener('response', state.wreckHandler);

    internals.iterateOverEventHash(state.handlers, function (event, handler) {

        self._server.removeListener(event, handler);
    });

    internals.iterateOverEventHash(state.extensions, function (event, handler) {

        self._server.removeListener(event, handler);
    });

    for (var j = 0, jl = this._reporters.length; j < jl; ++j) {
        var reporter = this._reporters[j];
        reporter.stop();
    }
};

internals.Monitor.prototype._requestLogHandler = function (request, event) {

    this.emit('report', 'request', Utils.GreatRequest(request, event));
};

internals.Monitor.prototype._logHandler = function (event) {

    this.emit('report', 'log', Utils.GreatLog(event));
};

internals.Monitor.prototype._errorHandler = function (request, error) {

    this.emit('report', 'error', Utils.GreatError(request, error));
};

internals.Monitor.prototype._responseHandler = function (request) {

    this.emit('report', 'response', Utils.GreatResponse(request, this._responseOptions));
};

internals.Monitor.prototype._opsHandler = function (results) {

    this.emit('report', 'ops', Utils.GreatOps(results));
};

internals.Monitor.prototype._wreckHandler = function (error, request, response) {

    this.emit('report', 'wreck', Utils.GreatWreck(error, request, response));
};

internals.Monitor.prototype._extensionHandler = function (eventName) {

    var event;
    // (eventName, request, event, tags)
    if (arguments.length === 4) {
        event = arguments[2] || {};
    }
    else {
        event = arguments[1] || {};
    }
    event.event = eventName;
    this.emit('report', eventName, Object.freeze(event));
};
<commit_msg>PR updates.<commit_after>// Load modules

var Events = require('events');
var Http = require('http');
var Https = require('https');
var Os = require('os');
var Hoek = require('hoek');
var Items = require('items');
var Wreck = require('wreck');
var Network = require('./network');
var Package = require('../package.json');
var ProcessMonitor = require('./process');
var Schema = require('./schema');
var System = require('./system');
var Utils = require('./utils');

// Declare internals

var internals = {
    host: Os.hostname(),
    appVer: Package.version
};

internals.defaults = {
    opsInterval: 15000,
    responseEvent: 'tail',
    requestHeaders: false,
    requestPayload: false,
    responsePayload: false,
    extensions: []
};

module.exports = internals.Monitor = function (server, options) {

    options = options || {};

    Hoek.assert(this.constructor === internals.Monitor, 'Monitor must be instantiated using new');
    Hoek.assert(server, 'server required to create monitor');

    options = Hoek.applyToDefaultsWithShallow(internals.defaults, options, ['reporters', 'httpAgents', 'httpsAgents']);

    // Force them to be arrays
    var args = [];
    options.httpAgents = args.concat(options.httpAgents || Http.globalAgent);
    options.httpsAgents = args.concat(options.httpsAgents || Https.globalAgent);

    this.settings = options;
    this._reporters = [];
    this._state = {
        handlers: {},
        extensions: {}
    };
    this._server = server;

    // Options used to create Great Response
    this._responseOptions = {
        requestHeaders: this.settings.requestHeaders,
        requestPayload: this.settings.requestPayload,
        responsePayload: this.settings.responsePayload
    };

    // Validate settings
    Schema.assert('monitorOptions', this.settings);

    // Register as event emitter
    Events.EventEmitter.call(this);
};

Hoek.inherits(internals.Monitor, Events.EventEmitter);

internals.Monitor.prototype.start = function (callback) {

    var self = this;

    var setupOpsMonitoring = function () {

        var pmonitor = ProcessMonitor;
        var os = System;
        var network = new Network.Monitor(self._server);

        var asyncOps = {
            osload: os.loadavg,
            osmem: os.mem,
            osup: os.uptime,
            psup: pmonitor.uptime,
            psmem: pmonitor.memoryUsage,
            psdelay: pmonitor.delay,
            requests: network.requests.bind(network),
            concurrents: network.concurrents.bind(network),
            responseTimes: network.responseTimes.bind(network),
            sockets: network.sockets.bind(network, self.settings.httpAgents, self.settings.httpsAgents)
        };

        // Set ops interval timer

        return function () {

            // Gather operational statistics in parallel

            Items.parallel.execute(asyncOps, function (error, results) {

                if (error) {
                    console.error(error);
                }
                else {
                    results.host = internals.host;
                    self.emit('ops', results);
                }
                network.reset();
            });
        };
    };

    for (var i = 0, il = this.settings.reporters.length; i < il; i++) {

        var item = this.settings.reporters[i];
        var reporter;

        // If it has a reporter constructor, then create a new one, otherwise, assume it is
        // a valid pre-constructed reporter
        if (item.reporter) {

            // If the supply a path or module node, try to load it
            if (typeof item.reporter === 'string') {
                item.reporter = require(item.reporter);
            }

            Hoek.assert(typeof item.reporter === 'function', 'reporter key must be a constructor function');

            item.args = item.args || [];
            // this pointer
            item.args.unshift(null);
            var constructor = item.reporter.bind.apply(item.reporter, item.args);
            reporter = new constructor();
        }
        else {
            reporter = item;
        }

        Hoek.assert(reporter.start && reporter.stop, 'Every reporter object must have a start and stop function.');

        this._reporters.push(reporter);
    }

    Items.serial(this._reporters, function (item, next) {

        item.start(self, next);
    }, function (error) {

        if (error) {
            return callback(error);
        }

        self._state.opsInterval = setInterval(setupOpsMonitoring(), self.settings.opsInterval);
        self._state.opsHandler = self._opsHandler.bind(self);
        self._state.wreckHandler = self._wreckHandler.bind(self);

        self._state.handlers.log = self._logHandler.bind(self);
        self._state.handlers['request-error'] = self._errorHandler.bind(self);
        self._state.handlers[self.settings.responseEvent] = self._responseHandler.bind(self);
        self._state.handlers.request = self._requestLogHandler.bind(self);

        // Initialize Events
        internals.iterateOverEventHash(self._state.handlers, function (event, handler) {

            self._server.on(event, handler);
        });

        self.on('ops', self._state.opsHandler);
        Wreck.on('response', self._state.wreckHandler);

        // Events can not be any of ['log', 'request-error', 'ops', 'request', 'response', 'tail']
        for (var i = 0, il = self.settings.extensions.length; i < il; ++i) {
            var event = self.settings.extensions[i];

            self._state.extensions[event] = self._extensionHandler.bind(self, event);
            self._server.on(self.settings.extensions[i], self._state.extensions[event]);
        }

        return callback();
    });
};

internals.Monitor.prototype.stop = function () {

    var self = this;
    var state = this._state;
    clearInterval(state.opsInterval);

    this.removeListener('ops', state.opsHandler);
    Wreck.removeListener('response', state.wreckHandler);

    internals.iterateOverEventHash(state.handlers, function (event, handler) {

        self._server.removeListener(event, handler);
    });

    internals.iterateOverEventHash(state.extensions, function (event, handler) {

        self._server.removeListener(event, handler);
    });

    for (var j = 0, jl = this._reporters.length; j < jl; ++j) {
        var reporter = this._reporters[j];
        reporter.stop();
    }
};

internals.Monitor.prototype._requestLogHandler = function (request, event) {

    this.emit('report', 'request', Utils.GreatRequest(request, event));
};

internals.Monitor.prototype._logHandler = function (event) {

    this.emit('report', 'log', Utils.GreatLog(event));
};

internals.Monitor.prototype._errorHandler = function (request, error) {

    this.emit('report', 'error', Utils.GreatError(request, error));
};

internals.Monitor.prototype._responseHandler = function (request) {

    this.emit('report', 'response', Utils.GreatResponse(request, this._responseOptions));
};

internals.Monitor.prototype._opsHandler = function (results) {

    this.emit('report', 'ops', Utils.GreatOps(results));
};

internals.Monitor.prototype._wreckHandler = function (error, request, response) {

    this.emit('report', 'wreck', Utils.GreatWreck(error, request, response));
};

internals.Monitor.prototype._extensionHandler = function (eventName) {

    var event;
    // (eventName, request, event, tags)
    if (arguments.length === 4) {
        event = arguments[2] || {};
    }
    else {
        event = arguments[1] || {};
    }
    event.event = eventName;
    this.emit('report', eventName, Object.freeze(event));
};

internals.iterateOverEventHash = function (hash, predicate) {

    var keys = Object.keys(hash);
    for (var k = 0, kl = keys.length; k < kl; ++k) {
        var key = keys[k];
        predicate(key, hash[key]);
    }
};
<|endoftext|>


<commit_before>var oI2C = require("i2c");

// ##############################################################################
// MPU6050 Class:
// Used for Gyroscope and Accelerometer
// ##############################################################################

module.exports = {

	// ATTRIBUTES -----------------------------------------------------------------
	sDevice: "/dev/i2c-1",
	hAddress: 0x68,
	hAddressLow: 0x68,
	hAddressHight: 0x69,
	oWire: null,
	aRotationZero: [0,0,0],
	aAccelerationZero: [0,0,0],

	// CONSTANTS ------------------------------------------------------------------
	fRotation: 360 / 35252,
	fAcceleration: 100 / 35252,

	// FUNCTION -------------------------------------------------------------------
	// initialize sensor
	init: function(lVersion){
		if(lVersion == 0)
 			this.sDevice = "/dev/i2c-0";
		this.oWire = new oI2C(this.hAddress, {device: this.sDevice});
		// set clock to x gyro
		this.oWire.writeBytes(0x6B, 2, 0x01, this.handleError.bind(this));
		// set gyroscope to most sensitive setting
		this.oWire.writeBytes(0x1B, 4, 0x00, this.handleError.bind(this));
		// set accelerometer to most sensitive setting
		this.oWire.writeBytes(0x1C, 4, 0x00, this.handleError.bind(this));
	},

	// FUNCTION
	// get raw acceleration data
	getAcceleration: function(){
		var oBuffer = this.oWire.readBytes(0x3B, 6, this.handleError.bind(this));
		return [oBuffer.readInt16BE(0), oBuffer.readInt16BE(2), oBuffer.readInt16BE(4)];
	},

	// FUNCTION
	// get raw rotation data
	getRotation: function(){
		var oBuffer = this.oWire.readBytes(0x43, 6, this.handleError.bind(this));
		return [oBuffer.readInt16BE(2) - this.aRotationZero[1], oBuffer.readInt16BE(0) - this.aRotationZero[0], oBuffer.readInt16BE(4) - this.aRotationZero[2]];
	},

  // FUNCTION
  // get raw rotation offset data
  getRotationOffset: function(){
    var oBuffer = this.oWire.readBytes(0x13, 6, this.handleError.bind(this));
    return [oBuffer.readInt16BE(0), oBuffer.readInt16BE(2), oBuffer.readInt16BE(4)];
  },

  // FUNCTION
  // get chip temperature
  getTemperature: function(){
    var oData = this.oWire.readBytes(0x41, 2, this.handleError.bind(this));
    return (oData.readInt16BE(0) / 333.86) + 21.00;
  },

	// FUNCTION
	// read compass data
	getCompass: function(){
		var oBuffer = this.oWire.readBytes(0x03, 7, this.handleError.bind(this));
		return [(oBuffer[1] << 8) + oBuffer[0], (oBuffer[3] << 8) + oBuffer[2], (oBuffer[5] << 8) + oBuffer[4]];
	},

	// FUNCTION
	// set zero values
	setRotationZero: function(){
		this.aRotationZero = this.getRotation();
	},

	// FUNCTION
	// get rotation data as degrees
	getRotationDegree: function(){
		var oData = this.getRotation();
		return [Math.round(oData[0] * this.fRotation), Math.round(oData[1] * this.fRotation), Math.round(oData[2] * this.fRotation)];
	},

	// FUNCTION
	// get acceleration as percentage to highest measured
	getAccelerationPercentage: function(){
		var oData = this.getAcceleration();
		return [Math.round(oData[0] * this.fAcceleration), Math.round(oData[1] * this.fAcceleration), Math.round(oData[2] * this.fAcceleration)];
	},

	// FUNCTION
	// handle errors callback
	handleError: function(oErr){
	  if(oErr == null) return;
	  console.log(oErr);
	}

};
<commit_msg>wicked changes<commit_after>var oI2C = require("i2c");

// ##############################################################################
// MPU6050 Class:
// Used for Gyroscope and Accelerometer
// ##############################################################################

module.exports = {

	// ATTRIBUTES -----------------------------------------------------------------
	sDevice: "/dev/i2c-1",
	hAddress: 0x68,
	hAddressLow: 0x68,
	hAddressHight: 0x69,
	oWire: null,
	aRotationZero: [0,0,0],
	aAccelerationZero: [0,0,0],

	// CONSTANTS ------------------------------------------------------------------
	fRotation: 360 / 35252,
	fAcceleration: 100 / 35252,

	// FUNCTION -------------------------------------------------------------------
	// initialize sensor
	init: function(lVersion){
		if(lVersion == 0)
 			this.sDevice = "/dev/i2c-0";
		this.oWire = new oI2C(this.hAddress, {device: this.sDevice});
		// set clock to x gyro
		this.oWire.writeBytes(0x6B, 2, 0x01, this.handleError);
		// set gyroscope to most sensitive setting
		this.oWire.writeBytes(0x1B, 4, 0x00, this.handleError);
		// set accelerometer to most sensitive setting
		this.oWire.writeBytes(0x1C, 4, 0x00, this.handleError);
	},

	// FUNCTION
	// get raw acceleration data
	getAcceleration: function(){
		var oBuffer = this.oWire.readBytes(0x3B, 6, this.handleError);
		return [oBuffer.readInt16BE(0), oBuffer.readInt16BE(2), oBuffer.readInt16BE(4)];
	},

	// FUNCTION
	// get raw rotation data
	getRotation: function(){
		var oBuffer = this.oWire.readBytes(0x43, 6, this.handleError);
		return [oBuffer.readInt16BE(2) - this.aRotationZero[1], oBuffer.readInt16BE(0) - this.aRotationZero[0], oBuffer.readInt16BE(4) - this.aRotationZero[2]];
	},

  // FUNCTION
  // get raw rotation offset data
  getRotationOffset: function(){
    var oBuffer = this.oWire.readBytes(0x13, 6, this.handleError);
    return [oBuffer.readInt16BE(0), oBuffer.readInt16BE(2), oBuffer.readInt16BE(4)];
  },

  // FUNCTION
  // get chip temperature
  getTemperature: function(){
    var oData = this.oWire.readBytes(0x41, 2, this.handleError);
    return (oData.readInt16BE(0) / 333.86) + 21.00;
  },

	// FUNCTION
	// read compass data
	getCompass: function(){
		var oBuffer = this.oWire.readBytes(0x03, 7, this.handleError);
		return [(oBuffer[1] << 8) + oBuffer[0], (oBuffer[3] << 8) + oBuffer[2], (oBuffer[5] << 8) + oBuffer[4]];
	},

	// FUNCTION
	// set zero values
	setRotationZero: function(){
		this.aRotationZero = this.getRotation();
	},

	// FUNCTION
	// get rotation data as degrees
	getRotationDegree: function(){
		var oData = this.getRotation();
		return [Math.round(oData[0] * this.fRotation), Math.round(oData[1] * this.fRotation), Math.round(oData[2] * this.fRotation)];
	},

	// FUNCTION
	// get acceleration as percentage to highest measured
	getAccelerationPercentage: function(){
		var oData = this.getAcceleration();
		return [Math.round(oData[0] * this.fAcceleration), Math.round(oData[1] * this.fAcceleration), Math.round(oData[2] * this.fAcceleration)];
	},

	// FUNCTION
	// handle errors callback
	handleError: function(oErr){
	  if(oErr == null) return;
	  console.log(oErr);
	}

};
<|endoftext|>


<commit_before>import EventEmitter from "events"

export class Fusion {

    constructor(hostString){
        this.hostString = hostString
        this._socket = new Socket(hostString, this.classify)
        // Hack for fusion(collectionName) syntax
        self = (collectionName) => self.collection(collectionName)
        Object.setPrototypeOf(self, Object.getPrototypeOf(this))
        return self
    }

    collection(name){
        //Check if collection exists?? Nope, EAFP let server handle it.
        return new Collection(this, name)
    }

    classify(response){
        // response -> responseType
        // this might need to go in another class and be given to this class
        if(response.new_val !== null && response.old_val !== null){
            return 'changed'
        }else if(response.new_val !== null && response.old_val === null){
            return 'added'
        }else if(response.new_val === null && response.old_val !== null){
            return 'removed'
        }else if(response.state === 'synced'){
            return 'synced'
        }else{
            return 'unknown'
        }
    }

    _query(path){
        return this.socket.send("QUERY", path)
    }

    _store(path, document, conflict){
        if(conflict === 'replace'){
            return this.socket.send("STORE_REPLACE", {path: path, data: document})
        }else if(conflict === 'error'){
            return this.socket.send("STORE_ERROR", {path: path, data: document})
        }else{
            return Promise.reject(`value of conflict not understood: ${conflict}`)
        }
    }

    _update(path, document){
        return this.socket.send("UPDATE", {path: path, data: document})
    }

    _remove(path, id){
        return this.socket.send("REMOVE", {path: path, data: id})
    }

    _subscribe(path, updates){
        if(updates){
            return this.socket.subscribe(path)
        }else{
            //Emulate subscription with one-shot query
            var emitter = new EventEmitter()
            this.socket.send("QUERY", path).then(
                // Do we have continues etc like cursors?
                // Right now assuming we get results back as an array
                (results) => {
                    for(let result of results) {
                        emitter.emit("added", {new_val: result, old_val: null})
                    }
                }
            )
            return emitter
        }
    }

}

//window.Fusion = Fusion;

class Socket {
    constructor(hostString, classifier){
        this.ws = new WebSocket(`ws://${hostString}`)
        this.ws.onmessage = this._onMessage
        this.ws.onclose = this._onClose
        this.ws.onopen = this._onOpen
        this.classifier = classifier
        this.promises = {}
        this.emitters = {}
        this.requestCounter = 0
    }

    send(type, data){
        var requestId = this.requestCounter++
        var req = {type: type, data: data, requestId: requestId}
        return new Promise((resolve, reject) =>
            this.promises[requestId] = {resolve: resolve, reject:reject})
    }

    subscribe(path){
        var requestId = this.requestCounter++
        var req = {type: "SUBSCRIBE", data: data, requestId: requestId}
        var emitter = new EventEmitter() // customize?
        this.emitters[requestId] = emitter
        return emitter
    }

    _onClose(event){
        for(let emitter of this.emitters){
            emitter.emit('disconnected', event)
        }
        // Do we do something with promises? What if we reconnect
    }

    _onOpen(event){
        for(let emitter of this.emitters){
            emitter.emit('reconnected', event)
        }
    }

    _onMessage(event){
        var resp = JSON.parse(event.data)
        if(this.promises.hasOwnProperty(resp.requestId)){
            var promise = this.promises[resp.requestId]
            delete this.promises[resp.requestId]

            if (resp.error !== undefined){
                promise.reject(resp.error)
            } else {
                promise.resolve(resp.value)
            }
        }else if(this.emitters.hasOwnProperty(resp.requestId)){
            var emitter = this.emitters[resp.requestId]
            if(resp.error !== undefined){
                emitter.emit("error", resp.error)
            }else{
                emitter.emit(this.classifier(resp.data), resp.value)
            }
        }else{
            console.error(`Unrecognized response: ${event}`)
        }
    }
}

class TermBase {

    constructor(fusion){
        this.fusion = fusion
    }

    subscribe(updates: true){
        // should create a changefeed query, return eventemitter
        return this.fusion._subscribe(this.path)
    }

    value(){
        // return promise with no changefeed
        return this.fusion._value(this.path)
    }
}

class Collection {

    constructor(fusion, collectionName){
        this.collectionName = collectionName
        this.path = {collection: collectionName}
        this.fusion = fusion
    }

    findOne(id){
        return new findOne(this.fusion, this.path, id)
    }

    find(fieldName, fieldValue){
        return new Find(this.fusion, this.path, fieldName, fieldValue)
    }

    between(minVal, maxVal, field: 'id'){
        return new Between(this.fusion, this.path, minVal, maxVal,field)
    }

    order(field: 'id', descending: false){
        return new Order(this.fusion, this.path, field, descending)
    }

    store(document, conflict: 'replace'){
        return this.fusion._store(this.path, document, conflict)
    }

    update(document){
        return this.fusion._update(this.path, document)
    }

    remove(document){
        return this.fusion._remove(this.path, document)
    }
}

class Find extends TermBase {
    constructor(fusion, path, field, value){
        super(fusion)
        this.field
        this.value = value
        this.path = Object.assign({find: {field: field, value: value}}, path)
    }

    order(field: 'id', descending: false){
        return new Order(this.fusion, this.path, field, descending)
    }

    limit(size){
        return new Limit(this.fusion, this.path, size);
    }
}

class FindOne extends TermBase {
    constructor(fusion, path, docId){
        super(fusion)
        this.id = docId
        this.path = Object.assign({findOne: docId}, path)
    }
}

class Between extends TermBase {
    constructor(fusion, path, minVal, maxVal, field){
        super(fusion)
        this.minVal = minVal
        this.maxVal = maxVal
        this.field = field
        this.path = Object.assign({between: {min: minVal, max: maxVal, field: field}}, path)
    }

    limit(size){
        return new Limit(this.fusion, this.path, size);
    }
}

class Order {
    constructor(fusion, path, field, descending){
        this.fusion = fusion
        this.field = field
        this.direction = direction
        this.path = Object.assign({order: {field: field, descending: descending}}, path)
    }

    limit(size){
        return new Limit(this.fusion, this.path, size)
    }

    between(minVal, maxVal){
        // between is forced to have the same field as this term
        return new Between(this.fusion, this.path, minVal, maxVal, this.field)
    }
}

class Limit extends TermBase {
    constructor(fusion, path, size){
        super(fusion)
        this.size = size
        this.path = Object.assign({limit: size}, path)
    }
}
<commit_msg>Removing hack<commit_after>import EventEmitter from "events"

export class Fusion {

    constructor(hostString){
        this.hostString = hostString
        this._socket = new Socket(hostString, this.classify)
        // Hack for fusion(collectionName) syntax
        self = (collectionName) => self.collection(collectionName)
        Object.setPrototypeOf(self, Object.getPrototypeOf(this))
        return self
    }

    collection(name){
        //Check if collection exists?? Nope, EAFP let server handle it.
        return new Collection(this, name)
    }

    classify(response){
        // response -> responseType
        // this might need to go in another class and be given to this class
        if(response.new_val !== null && response.old_val !== null){
            return 'changed'
        }else if(response.new_val !== null && response.old_val === null){
            return 'added'
        }else if(response.new_val === null && response.old_val !== null){
            return 'removed'
        }else if(response.state === 'synced'){
            return 'synced'
        }else{
            return 'unknown'
        }
    }

    _query(path){
        return this.socket.send("QUERY", path)
    }

    _store(path, document, conflict){
        if(conflict === 'replace'){
            return this.socket.send("STORE_REPLACE", {path: path, data: document})
        }else if(conflict === 'error'){
            return this.socket.send("STORE_ERROR", {path: path, data: document})
        }else{
            return Promise.reject(`value of conflict not understood: ${conflict}`)
        }
    }

    _update(path, document){
        return this.socket.send("UPDATE", {path: path, data: document})
    }

    _remove(path, id){
        return this.socket.send("REMOVE", {path: path, data: id})
    }

    _subscribe(path, updates){
        if(updates){
            return this.socket.subscribe(path)
        }else{
            //Emulate subscription with one-shot query
            var emitter = new EventEmitter()
            this.socket.send("QUERY", path).then(
                // Do we have continues etc like cursors?
                // Right now assuming we get results back as an array
                (results) => {
                    for(let result of results) {
                        emitter.emit("added", {new_val: result, old_val: null})
                    }
                }
            )
            return emitter
        }
    }

}

class Socket {
    constructor(hostString, classifier){
        this.ws = new WebSocket(`ws://${hostString}`)
        this.ws.onmessage = this._onMessage
        this.ws.onclose = this._onClose
        this.ws.onopen = this._onOpen
        this.classifier = classifier
        this.promises = {}
        this.emitters = {}
        this.requestCounter = 0
    }

    send(type, data){
        var requestId = this.requestCounter++
        var req = {type: type, data: data, requestId: requestId}
        return new Promise((resolve, reject) =>
            this.promises[requestId] = {resolve: resolve, reject:reject})
    }

    subscribe(path){
        var requestId = this.requestCounter++
        var req = {type: "SUBSCRIBE", data: data, requestId: requestId}
        var emitter = new EventEmitter() // customize?
        this.emitters[requestId] = emitter
        return emitter
    }

    _onClose(event){
        for(let emitter of this.emitters){
            emitter.emit('disconnected', event)
        }
        // Do we do something with promises? What if we reconnect
    }

    _onOpen(event){
        for(let emitter of this.emitters){
            emitter.emit('reconnected', event)
        }
    }

    _onMessage(event){
        var resp = JSON.parse(event.data)
        if(this.promises.hasOwnProperty(resp.requestId)){
            var promise = this.promises[resp.requestId]
            delete this.promises[resp.requestId]

            if (resp.error !== undefined){
                promise.reject(resp.error)
            } else {
                promise.resolve(resp.value)
            }
        }else if(this.emitters.hasOwnProperty(resp.requestId)){
            var emitter = this.emitters[resp.requestId]
            if(resp.error !== undefined){
                emitter.emit("error", resp.error)
            }else{
                emitter.emit(this.classifier(resp.data), resp.value)
            }
        }else{
            console.error(`Unrecognized response: ${event}`)
        }
    }
}

class TermBase {

    constructor(fusion){
        this.fusion = fusion
    }

    subscribe(updates: true){
        // should create a changefeed query, return eventemitter
        return this.fusion._subscribe(this.path)
    }

    value(){
        // return promise with no changefeed
        return this.fusion._value(this.path)
    }
}

class Collection {

    constructor(fusion, collectionName){
        this.collectionName = collectionName
        this.path = {collection: collectionName}
        this.fusion = fusion
    }

    findOne(id){
        return new findOne(this.fusion, this.path, id)
    }

    find(fieldName, fieldValue){
        return new Find(this.fusion, this.path, fieldName, fieldValue)
    }

    between(minVal, maxVal, field: 'id'){
        return new Between(this.fusion, this.path, minVal, maxVal,field)
    }

    order(field: 'id', descending: false){
        return new Order(this.fusion, this.path, field, descending)
    }

    store(document, conflict: 'replace'){
        return this.fusion._store(this.path, document, conflict)
    }

    update(document){
        return this.fusion._update(this.path, document)
    }

    remove(document){
        return this.fusion._remove(this.path, document)
    }
}

class Find extends TermBase {
    constructor(fusion, path, field, value){
        super(fusion)
        this.field
        this.value = value
        this.path = Object.assign({find: {field: field, value: value}}, path)
    }

    order(field: 'id', descending: false){
        return new Order(this.fusion, this.path, field, descending)
    }

    limit(size){
        return new Limit(this.fusion, this.path, size);
    }
}

class FindOne extends TermBase {
    constructor(fusion, path, docId){
        super(fusion)
        this.id = docId
        this.path = Object.assign({findOne: docId}, path)
    }
}

class Between extends TermBase {
    constructor(fusion, path, minVal, maxVal, field){
        super(fusion)
        this.minVal = minVal
        this.maxVal = maxVal
        this.field = field
        this.path = Object.assign({between: {min: minVal, max: maxVal, field: field}}, path)
    }

    limit(size){
        return new Limit(this.fusion, this.path, size);
    }
}

class Order {
    constructor(fusion, path, field, descending){
        this.fusion = fusion
        this.field = field
        this.direction = direction
        this.path = Object.assign({order: {field: field, descending: descending}}, path)
    }

    limit(size){
        return new Limit(this.fusion, this.path, size)
    }

    between(minVal, maxVal){
        // between is forced to have the same field as this term
        return new Between(this.fusion, this.path, minVal, maxVal, this.field)
    }
}

class Limit extends TermBase {
    constructor(fusion, path, size){
        super(fusion)
        this.size = size
        this.path = Object.assign({limit: size}, path)
    }
}
<|endoftext|>


<commit_before>function newTimeView(v) {

    //
    var twrap = newDiv().appendTo(v);

        $LAB
            .script("lib/timeline/timeline-min.js")
            .wait(function() {
                var timeline = new links.Timeline(v[0]);

                //http://visjs.org/docs/timeline.html
                var data = [];
                var options = {
                    'width': '100%',
                    'height': '100%',
                    'editable': true, // enable dragging and editing events
                    'style': 'box',
                    'eventMargin': 0,
                    'cluster': true,
                    'autoResize': true,
                    'start': Date.now() - 1 * 60 * 60 * 1000 /* -1 hour */,
                    'end': Date.now() + 2 * 24 * 60 * 60 * 1000, /* 2 days */
                    'zoomMin': 60 * 1000, /* 1 min */
                    'groupsChangeable': false,
                    'animate': 0,
                };

                var times = {};

                var numTimeSegments = 128;
                var timeUnitLengthMS = 30 * 60 * 1000; //30min

                var currentViewRange = null;
                function redraw() {
                    if (currentViewRange) {
                        options.start = currentViewRange.start;
                        options.end = currentViewRange.end;
                    }

                    timeline.clearItems();
                    data = [];

                    foreachTimedObject(null, function(goals, centroids) {
                        function addGoal(g) {
                            var duration = g.duration || timeUnitLengthMS;
                            var gs = newObjectView(g, {
                                depthRemaining: 0,
                                nameClickable: false,
                                showActionPopupButton: false,
                                showSelectionCheck: false,
                                showTime: false,
                                showAuthorName: false,
                            });

                            var G = {
                                'id': g.id,
                                'start': g.when,
                                'end': g.when + duration,
                                'content': '
' + gs.html() + ''
                            };
                            if (g.author == $N.id()) {
                                G.group = 'me';
                            }
                            else if (g.author) {
                                G.group = 'others';
                            }
                            else {
                                G.group = 'system';
                            }
                            G.editable = (g.author === $N.id());
                            if (G.editable) {
                                times[g.id] = [G.start, G.end];
                            }

                            data.push(G);
                        }

                        _.each(goals, addGoal);
                        _.each(centroids, addGoal);

                    });

                    timeline.draw(data, options);

                }

                function changed(x) {
                    var d = timeline.getData();
                    for (var i = 0; i < d.length; i++) {
                        if (d[i].editable) {
                            var D = d[i];
                            var id = D.id;
                            var lastTimes = times[id];
                            var dstart = D.start;
                            var dend = D.end;
                            if (dstart.getTime)
                                dstart = dstart.getTime();
                            if (dend.getTime)
                                dend = dend.getTime();
                            if ((lastTimes[0] != dstart) || (lastTimes[1] != dend)) {
                                times[id] = [dstart, dend];

                            var G = $N.getObject(id);
                                if (G) {
                                    G.when = dstart;
                                    G.duration = dend - dstart;
                                    $N.pub(G);
                                }
                            }
                        }
                    }
                }

                redraw();

                function updateHandlers() {
                    $('.timelineLabel').off('dblclick');
                    $('.timelineLabel').dblclick(function() {
                        var uid = $(this).attr('uid');
                        newPopupObjectView($N.getObject(uid));
                        return false;
                    });
                }

                links.events.addListener(timeline, 'ready', function() {
                    updateHandlers();
                });

                //links.events.addListener(timeline, 'rangechanged', changed);
                links.events.addListener(timeline, 'edit', changed);
                links.events.addListener(timeline, 'change', changed);
                links.events.addListener(timeline, 'changed', changed);
                /*links.events.addListener(timeline, 'select', function(s) {
                });                */
                links.events.addListener(timeline, 'add', function() {
                    var dd = timeline.getData();
                    var tti = dd[dd.length - 1].start.getTime();
                    var d = newPopup("Add a Goal at " + new Date(tti), {width: 800, height: 600, modal: true});
                    d.append(newTagger([], function(results) {
                        saveAddedTags(results, 'Goal', tti);
                        later(function() {
                            d.dialog('close');
                        });
                    }));
                    dd.pop();

                    timeline.draw(dd, options);
                });
                links.events.addListener(timeline, 'rangechanged', function(p) {
                    updateHandlers();
                    currentViewRange = p;
                });

                twrap.onChange = redraw;

            });

    return twrap;
}

//DEPRECATED:
function newTimeViewGridster(v) {
    var numTimeSegments = 48;
    var timeUnitLengthMS = 30 * 60 * 1000; //30min

    var goalWidgetSize = [170, 170];
    var goalWidgetScale = '75%';

    var d = newDiv().appendTo(v);

    var colTimes = {};

    var gridsterParam = {
        widget_base_dimensions: goalWidgetSize,
        widget_margins: [6, 6],
        min_cols: numTimeSegments
    };

    function updateGoal(g, when, duration) {
        var G = $N.getObject(g);
        if (when)
            G.when = when;
        if (duration)
            G.duration = duration;
        $N.pub(G);
    }

    var resizingGoalID = null;
    var goalGridsterParam = _.extend(_.clone(gridsterParam), {
        resize: {
            enabled: true,
            max_size: [Infinity, 1],
            start: function(e, ui, $widget) {
                resizingGoalID = $widget.attr('goalid');
            },
            stop: function(e, ui, $widget) {
                var cols = $widget.attr('data-sizex');
                var colTime = cols * timeUnitLengthMS;
                updateGoal(resizingGoalID, null, colTime);
                resizingGoalID = null;
            }
        },
        draggable: {
            start: function() {
            },
            stop: function(event, ui) {
                var p = ui.$player;
                var g = p.attr('goalid');
                var targetCol = p.attr('data-col') - 1;
                var targetTime = colTimes[targetCol];
                updateGoal(g, targetTime, null);
                //console.log(, , 'dragged');
            }
        }
    });

    var headerRow = newDiv().addClass('gridster').appendTo(d);
    var headerRowGrid = $('
').appendTo(headerRow);

    d.append('

');

    var goalRows = newDiv().addClass('gridster').appendTo(d);
    var goalRowsGrid = $('
').appendTo(goalRows);

    var goalRowsGridster = goalRowsGrid.gridster(goalGridsterParam).data('gridster');

    foreachGoal(numTimeSegments, timeUnitLengthMS, $N.id(), function(time, goals, centroids, column) {
        colTimes[column] = time;

        var b = $('

');
        b.attr('data-col', 1 + column);
        b.attr('data-row', 1);
        b.css('border-bottom', '1px solid gray');

        //b.append(name);

        var ts = new Date(time);

        if ((ts.getHours() !== 0) || (ts.getMinutes() !== 0)) {
            var m = ts.getMinutes();
            if (m === 0)
                m = '00';
            ts = ts.getHours() + ":" + m;
        }
        else {
            ts = ts.toDateString();
            ts = ts.substring(0, ts.length - 5);
        }
        b.append(ts);

        var addbutton = $('<button title="Add Tag">[+]</button>').appendTo(b);

        var y = function() {
            var tti = time;
            var tts = ts;
            addbutton.click(function() {
                var d = newPopup("Add a Goal at " + tts, {width: 800, height: 600, modal: true});
                d.append(newTagger([], function(results) {
                    saveAddedTags(results, 'Goal', tti + timeUnitLengthMS / 2);

                    //now = _.unique(now.concat(results));
                    later(function() {
                        d.dialog('close');
                        //updateGoalList();
                    });
                    //container.html(newSelfTimeList(s, x, container));
                }));
            });
        };
        y();

        headerRowGrid.append(b);

        function addGoal(g) {
            var gg = $('

');
            gg.css('font-size', goalWidgetScale);
            var O = newObjectView(g, {
                showAuthorIcon: false,
                showAuthorName: false,
                showActionPopupButton: false
            });
            gg.attr('goalid', g.id);
            O.css('height', '95%');

            gg.append(O);

            var duration = g.duration || timeUnitLengthMS;
            var cols = parseInt(Math.round(parseFloat(duration) / parseFloat(timeUnitLengthMS)));

            goalRowsGridster.add_widget(gg, cols, 1, 1 + column, 1);
        }

        _.each(goals, addGoal);
        _.each(centroids, addGoal);

    });

    var headerRowGridster = headerRowGrid.gridster(gridsterParam).data('gridster');

    headerRowGridster.disable();

    return d;
}

function foreachTimedObject(user, withObjects) {
    var time = new Date();
    time.setMinutes(0);
    time.setSeconds(0);
    time.setMilliseconds(0);
    time = time.getTime();

    var goals = _.filter(_.values($N.instance), function(x) {
        var w = x.when || 0;
        if (x.duration)
            w += x.duration;
        return (w >= time);
    });

    withObjects(goals);

}

function foreachGoal(numTimeSegments, timeUnitLengthMS, user, onTimeSegment) {

    var time = new Date();
    time.setMinutes(0);
    time.setSeconds(0);
    time.setMilliseconds(0);
    time = time.getTime();

    var GOALS = $N.objectsWithTag('Goal', true);

    for (var i = 0; i < numTimeSegments; i++) {

        var ti = time + (i * timeUnitLengthMS);

        var goals = _.filter(GOALS, function(x) {
            if (user)
                if (x.author != user)
                    return;

            var w = x.when || 0;
            return ((w >= ti) && (w < ti + timeUnitLengthMS));
        });

        /*
         var ts = new Date(ti);
         if (ts.getHours() != 0) {
         ts = ts.getHours() + ":00";
         }

         var d = newDiv().addClass('alternatingDiv').append('' + ts + '');

         var addbutton = $('<button title="Add Tag">[+]</button>').appendTo(d);

         var y = function() {
         var tti = ti;
         var tts = ts;
         addbutton.click(function() {
         var d = newPopup("Add a Goal at " + tts, {width: 800, height: 600, modal: true});
         d.append(newTagger([], function(results) {
         saveAddedTags(results, 'Goal', tti + timeUnitLengthMS / 2);

         //now = _.unique(now.concat(results));
         later(function() {
         d.dialog('close');
         //updateGoalList();
         });
         //container.html(newSelfTimeList(s, x, container));
         }));
         });
         };
         y();

         _.each(goals, function(g) {
         var ogg = objTags(g);
         if (_.contains(ogg, 'GoalCentroid'))
         return;

         var gg = newObjectView(g).addClass("miniGoalSummary");
         d.append(gg);
         });
         */

        var centroids = $N.objectsWithTag('GoalCentroid', true) || [];
        if (centroids) {
            centroids = _.filter(centroids, function(c) {
                return (c.when >= ti) && (c.when < ti + timeUnitLengthMS);
            });
        }

        onTimeSegment(ti, goals, centroids, i);

    }

}

//Deprecated
function newGoalList(target, user, centroids) {
    var numTimeSegments = 24;
    var timeUnitLengthMS = 30 * 60 * 1000; //30min

    var time = new Date();
    time.setMinutes(0);
    time.setSeconds(0);
    time.setMilliseconds(0);
    time = time.getTime();

    var GOALS = $N.objectsWithTag('Goal', true);

    for (var i = 0; i < numTimeSegments; i++) {

        var ti = time + (i * timeUnitLengthMS);

        var goals = _.filter(GOALS, function(x) {
            if (x.author != user)
                return;

            var w = x.when || 0;
            return ((w >= ti) && (w < ti + timeUnitLengthMS));
        });

        var ts = new Date(ti);

        if ((ts.getHours() !== 0) || (ts.getMinutes() !== 0)) {
            var m = ts.getMinutes();
            if (m === 0)
                m = '00';
            ts = ts.getHours() + ":" + m;
        }
        else {
            ts = ts.toDateString();
            ts = ts.substring(0, ts.length - 5);
        }

        var d = newDiv().addClass('alternatingDiv').append('' + ts + '');

        var addbutton = $('[+]').appendTo(d);

        var y = function() {
            var tti = ti;
            var tts = ts;
            addbutton.click(function() {
                var d = newPopup("Add a Goal at " + tts, {width: 800, height: 600, modal: true});
                d.append(newTagger([], function(results) {
                    saveAddedTags(results, 'Goal', tti + timeUnitLengthMS / 2);

                    //now = _.unique(now.concat(results));
                    later(function() {
                        d.dialog('close');
                        //updateGoalList();
                    });
                    //container.html(newSelfTimeList(s, x, container));
                }));
            });
        };
        y();

        _.each(goals, function(g) {
            var ogg = objTags(g);
            if (_.contains(ogg, 'GoalCentroid'))
                return;

            var gg = newObjectView(g).addClass("miniGoalSummary");
            d.append(gg);
        });

        if (centroids) {
            _.each(_.filter(centroids, function(c) {
                return (c.when >= ti) && (c.when < ti + timeUnitLengthMS);
            }), function(g) {
                newObjectView(g).addClass("miniGoalSummary centroidSummary").appendTo(d);
            });
        }

        target.append(d);
    }

}
<commit_msg>update<commit_after>function newTimeView(v) {

    //
    var twrap = newDiv().appendTo(v);

        $LAB
            .script("lib/timeline/timeline-min.js")
            .wait(function() {
                var timeline = new links.Timeline(v[0]);

                //http://visjs.org/docs/timeline.html
                var data = [];
                var options = {
                    'width': '100%',
                    'height': '100%',
                    'editable': true, // enable dragging and editing events
                    'style': 'box',
                    'eventMargin': 0,
                    'cluster': true,
                    'autoResize': true,
                    'start': Date.now() - 1 * 60 * 60 * 1000 /* -1 hour */,
                    'end': Date.now() + 2 * 24 * 60 * 60 * 1000, /* 2 days */
                    'zoomMin': 60 * 1000, /* 1 min */
                    'groupsChangeable': false,
                    'animate': 0,
                };

                var times = {};

                var numTimeSegments = 128;
                var timeUnitLengthMS = 30 * 60 * 1000; //30min

                var currentViewRange = null;
                function redraw() {
                    if (currentViewRange) {
                        options.start = currentViewRange.start;
                        options.end = currentViewRange.end;
                    }

                    timeline.clearItems();
                    data = [];

                    foreachTimedObject(null, function(goals, centroids) {
                        function addGoal(g) {
                            var duration = g.duration || timeUnitLengthMS;
                            var gs = newObjectView(g, {
                                depthRemaining: 0,
                                nameClickable: false,
                                showActionPopupButton: false,
                                showSelectionCheck: false,
                                showTime: false,
                                showAuthorName: false,
                                startMinimized: true
                            });

                            var G = {
                                'id': g.id,
                                'start': g.when,
                                'end': g.when + duration,
                                'content': '
' + gs.html() + ''
                            };
                            if (g.author == $N.id()) {
                                G.group = 'me';
                            }
                            else if (g.author) {
                                G.group = 'others';
                            }
                            else {
                                G.group = 'system';
                            }
                            G.editable = (g.author === $N.id());
                            if (G.editable) {
                                times[g.id] = [G.start, G.end];
                            }

                            data.push(G);
                        }

                        _.each(goals, addGoal);
                        _.each(centroids, addGoal);

                    });

                    timeline.draw(data, options);

                }

                function changed(x) {
                    var d = timeline.getData();
                    for (var i = 0; i < d.length; i++) {
                        if (d[i].editable) {
                            var D = d[i];
                            var id = D.id;
                            var lastTimes = times[id];
                            var dstart = D.start;
                            var dend = D.end;
                            if (dstart.getTime)
                                dstart = dstart.getTime();
                            if (dend.getTime)
                                dend = dend.getTime();
                            if ((lastTimes[0] != dstart) || (lastTimes[1] != dend)) {
                                times[id] = [dstart, dend];

                            var G = $N.getObject(id);
                                if (G) {
                                    G.when = dstart;
                                    G.duration = dend - dstart;
                                    $N.pub(G);
                                }
                            }
                        }
                    }
                }

                redraw();

                function updateHandlers() {
                    $('.timelineLabel').off('dblclick');
                    $('.timelineLabel').dblclick(function() {
                        var uid = $(this).attr('uid');
                        newPopupObjectView($N.getObject(uid));
                        return false;
                    });
                }

                links.events.addListener(timeline, 'ready', function() {
                    updateHandlers();
                });

                //links.events.addListener(timeline, 'rangechanged', changed);
                links.events.addListener(timeline, 'edit', changed);
                links.events.addListener(timeline, 'change', changed);
                links.events.addListener(timeline, 'changed', changed);
                /*links.events.addListener(timeline, 'select', function(s) {

                });*/
                links.events.addListener(timeline, 'add', function() {
                    var dd = timeline.getData();
                    var tti = dd[dd.length - 1].start.getTime();
                    var d = newPopup("Add a Goal at " + new Date(tti), {width: 800, height: 600, modal: true});
                    d.append(newTagger([], function(results) {
                        saveAddedTags(results, 'Goal', tti);
                        later(function() {
                            d.dialog('close');
                        });
                    }));
                    dd.pop();

                    timeline.draw(dd, options);
                });
                links.events.addListener(timeline, 'rangechanged', function(p) {
                    updateHandlers();
                    currentViewRange = p;
                });

                twrap.onChange = redraw;

            });

    return twrap;
}

//DEPRECATED:
function newTimeViewGridster(v) {
    var numTimeSegments = 48;
    var timeUnitLengthMS = 30 * 60 * 1000; //30min

    var goalWidgetSize = [170, 170];
    var goalWidgetScale = '75%';

    var d = newDiv().appendTo(v);

    var colTimes = {};

    var gridsterParam = {
        widget_base_dimensions: goalWidgetSize,
        widget_margins: [6, 6],
        min_cols: numTimeSegments
    };

    function updateGoal(g, when, duration) {
        var G = $N.getObject(g);
        if (when)
            G.when = when;
        if (duration)
            G.duration = duration;
        $N.pub(G);
    }

    var resizingGoalID = null;
    var goalGridsterParam = _.extend(_.clone(gridsterParam), {
        resize: {
            enabled: true,
            max_size: [Infinity, 1],
            start: function(e, ui, $widget) {
                resizingGoalID = $widget.attr('goalid');
            },
            stop: function(e, ui, $widget) {
                var cols = $widget.attr('data-sizex');
                var colTime = cols * timeUnitLengthMS;
                updateGoal(resizingGoalID, null, colTime);
                resizingGoalID = null;
            }
        },
        draggable: {
            start: function() {
            },
            stop: function(event, ui) {
                var p = ui.$player;
                var g = p.attr('goalid');
                var targetCol = p.attr('data-col') - 1;
                var targetTime = colTimes[targetCol];
                updateGoal(g, targetTime, null);
                //console.log(, , 'dragged');
            }
        }
    });

    var headerRow = newDiv().addClass('gridster').appendTo(d);
    var headerRowGrid = $('
').appendTo(headerRow);

    d.append('

');

    var goalRows = newDiv().addClass('gridster').appendTo(d);
    var goalRowsGrid = $('
').appendTo(goalRows);

    var goalRowsGridster = goalRowsGrid.gridster(goalGridsterParam).data('gridster');

    foreachGoal(numTimeSegments, timeUnitLengthMS, $N.id(), function(time, goals, centroids, column) {
        colTimes[column] = time;

        var b = $('

');
        b.attr('data-col', 1 + column);
        b.attr('data-row', 1);
        b.css('border-bottom', '1px solid gray');

        //b.append(name);

        var ts = new Date(time);

        if ((ts.getHours() !== 0) || (ts.getMinutes() !== 0)) {
            var m = ts.getMinutes();
            if (m === 0)
                m = '00';
            ts = ts.getHours() + ":" + m;
        }
        else {
            ts = ts.toDateString();
            ts = ts.substring(0, ts.length - 5);
        }
        b.append(ts);

        var addbutton = $('<button title="Add Tag">[+]</button>').appendTo(b);

        var y = function() {
            var tti = time;
            var tts = ts;
            addbutton.click(function() {
                var d = newPopup("Add a Goal at " + tts, {width: 800, height: 600, modal: true});
                d.append(newTagger([], function(results) {
                    saveAddedTags(results, 'Goal', tti + timeUnitLengthMS / 2);

                    //now = _.unique(now.concat(results));
                    later(function() {
                        d.dialog('close');
                        //updateGoalList();
                    });
                    //container.html(newSelfTimeList(s, x, container));
                }));
            });
        };
        y();

        headerRowGrid.append(b);

        function addGoal(g) {
            var gg = $('

');
            gg.css('font-size', goalWidgetScale);
            var O = newObjectView(g, {
                showAuthorIcon: false,
                showAuthorName: false,
                showActionPopupButton: false
            });
            gg.attr('goalid', g.id);
            O.css('height', '95%');

            gg.append(O);

            var duration = g.duration || timeUnitLengthMS;
            var cols = parseInt(Math.round(parseFloat(duration) / parseFloat(timeUnitLengthMS)));

            goalRowsGridster.add_widget(gg, cols, 1, 1 + column, 1);
        }

        _.each(goals, addGoal);
        _.each(centroids, addGoal);

    });

    var headerRowGridster = headerRowGrid.gridster(gridsterParam).data('gridster');

    headerRowGridster.disable();

    return d;
}

function foreachTimedObject(user, withObjects) {
    var time = new Date();
    time.setMinutes(0);
    time.setSeconds(0);
    time.setMilliseconds(0);
    time = time.getTime();

    var goals = _.filter(_.values($N.instance), function(x) {
        var w = x.when || 0;
        if (x.duration)
            w += x.duration;
        return (w >= time);
    });

    withObjects(goals);

}

function foreachGoal(numTimeSegments, timeUnitLengthMS, user, onTimeSegment) {

    var time = new Date();
    time.setMinutes(0);
    time.setSeconds(0);
    time.setMilliseconds(0);
    time = time.getTime();

    var GOALS = $N.objectsWithTag('Goal', true);

    for (var i = 0; i < numTimeSegments; i++) {

        var ti = time + (i * timeUnitLengthMS);

        var goals = _.filter(GOALS, function(x) {
            if (user)
                if (x.author != user)
                    return;

            var w = x.when || 0;
            return ((w >= ti) && (w < ti + timeUnitLengthMS));
        });

        /*
         var ts = new Date(ti);
         if (ts.getHours() != 0) {
         ts = ts.getHours() + ":00";
         }

         var d = newDiv().addClass('alternatingDiv').append('' + ts + '');

         var addbutton = $('<button title="Add Tag">[+]</button>').appendTo(d);

         var y = function() {
         var tti = ti;
         var tts = ts;
         addbutton.click(function() {
         var d = newPopup("Add a Goal at " + tts, {width: 800, height: 600, modal: true});
         d.append(newTagger([], function(results) {
         saveAddedTags(results, 'Goal', tti + timeUnitLengthMS / 2);

         //now = _.unique(now.concat(results));
         later(function() {
         d.dialog('close');
         //updateGoalList();
         });
         //container.html(newSelfTimeList(s, x, container));
         }));
         });
         };
         y();

         _.each(goals, function(g) {
         var ogg = objTags(g);
         if (_.contains(ogg, 'GoalCentroid'))
         return;

         var gg = newObjectView(g).addClass("miniGoalSummary");
         d.append(gg);
         });
         */

        var centroids = $N.objectsWithTag('GoalCentroid', true) || [];
        if (centroids) {
            centroids = _.filter(centroids, function(c) {
                return (c.when >= ti) && (c.when < ti + timeUnitLengthMS);
            });
        }

        onTimeSegment(ti, goals, centroids, i);

    }

}

//Deprecated
function newGoalList(target, user, centroids) {
    var numTimeSegments = 24;
    var timeUnitLengthMS = 30 * 60 * 1000; //30min

    var time = new Date();
    time.setMinutes(0);
    time.setSeconds(0);
    time.setMilliseconds(0);
    time = time.getTime();

    var GOALS = $N.objectsWithTag('Goal', true);

    for (var i = 0; i < numTimeSegments; i++) {

        var ti = time + (i * timeUnitLengthMS);

        var goals = _.filter(GOALS, function(x) {
            if (x.author != user)
                return;

            var w = x.when || 0;
            return ((w >= ti) && (w < ti + timeUnitLengthMS));
        });

        var ts = new Date(ti);

        if ((ts.getHours() !== 0) || (ts.getMinutes() !== 0)) {
            var m = ts.getMinutes();
            if (m === 0)
                m = '00';
            ts = ts.getHours() + ":" + m;
        }
        else {
            ts = ts.toDateString();
            ts = ts.substring(0, ts.length - 5);
        }

        var d = newDiv().addClass('alternatingDiv').append('' + ts + '');

        var addbutton = $('[+]').appendTo(d);

        var y = function() {
            var tti = ti;
            var tts = ts;
            addbutton.click(function() {
                var d = newPopup("Add a Goal at " + tts, {width: 800, height: 600, modal: true});
                d.append(newTagger([], function(results) {
                    saveAddedTags(results, 'Goal', tti + timeUnitLengthMS / 2);

                    //now = _.unique(now.concat(results));
                    later(function() {
                        d.dialog('close');
                        //updateGoalList();
                    });
                    //container.html(newSelfTimeList(s, x, container));
                }));
            });
        };
        y();

        _.each(goals, function(g) {
            var ogg = objTags(g);
            if (_.contains(ogg, 'GoalCentroid'))
                return;

            var gg = newObjectView(g).addClass("miniGoalSummary");
            d.append(gg);
        });

        if (centroids) {
            _.each(_.filter(centroids, function(c) {
                return (c.when >= ti) && (c.when < ti + timeUnitLengthMS);
            }), function(g) {
                newObjectView(g).addClass("miniGoalSummary centroidSummary").appendTo(d);
            });
        }

        target.append(d);
    }

}
<|endoftext|>


<commit_before>var restify = require('restify');
var config = require('config').Server;
var models = require('./models/');
var ResultConverter = require('./result-converter.js');

var server = restify.createServer({ name: 'cm-updater-server' });

models.sequelize.sync().success(function() {
	server.listen(config.listeningPort, config.listeningAddress, function () {
		console.log('%s listening at %s', server.name, server.url);
	});

	server.use(restify.bodyParser(config.bodyParserConfiguration));

	// Conditionally enable the throttle module with the settings from the config.
	if (config.throttleConfiguration && config.throttleConfiguration.isEnabled) {
		server.use(restify.throttle(config.throttleConfiguration));
	}

	server.get('/changelog/:romId', function (req, res, next) {
		models.Rom.find(req.params.romId).complete(function(err, rom) {
			if (err) {
				res.send(500);
			} else if (!rom) {
				res.send(404);
			} else if (!rom.isActive) {
				res.send(410);
			} else {
				var findParentRomHandler = function(childRom, resultHandler) {
					childRom.getParentRom().success(resultHandler);
				}

				ResultConverter.getChangelogContent(rom, findParentRomHandler, function(body) {
					res.writeHead(200, {
						'Content-Length': Buffer.byteLength(body),
						'Content-Type': 'text/plain'
					});

					res.end(body);
				});
			}

			return next();
		});
	});

	server.get('/download/:romId', function (req, res, next) {
		models.Rom.find(req.params.romId).complete(function(err, rom) {
			if (err) {
				res.send(500);
			} else if (!rom) {
				res.send(404);
			} else if (!rom.isActive) {
				res.send(410);
			} else {
				var realDownloadUrl = ResultConverter.getRealDownloadUrl(rom);

				res.writeHead(301, { Location: realDownloadUrl });
				res.end();

				models.Download.build({
					RomId: rom.id,
					timestamp: new Date(),
				}).save().error(function (err) {
					// Ignoring errors here since those have no impact for the user.
				});
			}

			return next();
		});
	});

	server.post('/api', function(req, res, next) {
		// Currently the CMUpdater app does not send the correct content-type.
		// Thus auto-parsing the body does not work. But we are ready once that problem is fixed.
		var requestParameters = req.is('json') ? req.body : JSON.parse(req.body);

		if (!requestParameters || !requestParameters.params || requestParameters.method != 'get_all_builds') {
			res.send(400);
			return next();
		}

		var responseId = null;

		models.Device.find({ where: { name: requestParameters.params.device } }).complete(function(err, device) {
			if (err) {
				res.send(500, ResultConverter.convert(responseId, 'Database error.', null));
				return next();
			}

			if (!device) {
				// No error but nothing found.
				res.send(200, ResultConverter.convert(responseId, null, null));
				return next();
			}

			models.Rom.findAll({
				where: {
					DeviceId: device.id,
					updateChannel: requestParameters.params.channels,
					isActive: true,
				},
			}).complete(function(err, roms) {
				if (err) {
					res.send(500, ResultConverter.convert(responseId, 'Database error.', null));
				} else {
					res.send(200, ResultConverter.convert(responseId, null, roms));
				}

				return next();
			});
		});
	});
});
<commit_msg>GET changelog: call next at the right places.<commit_after>var restify = require('restify');
var config = require('config').Server;
var models = require('./models/');
var ResultConverter = require('./result-converter.js');

var server = restify.createServer({ name: 'cm-updater-server' });

models.sequelize.sync().success(function() {
	server.listen(config.listeningPort, config.listeningAddress, function () {
		console.log('%s listening at %s', server.name, server.url);
	});

	server.use(restify.bodyParser(config.bodyParserConfiguration));

	// Conditionally enable the throttle module with the settings from the config.
	if (config.throttleConfiguration && config.throttleConfiguration.isEnabled) {
		server.use(restify.throttle(config.throttleConfiguration));
	}

	server.get('/changelog/:romId', function (req, res, next) {
		models.Rom.find(req.params.romId).complete(function(err, rom) {
			if (err) {
				res.send(500);
				return next();
			}

			if (!rom) {
				res.send(404);
				return next();
			}

			if (!rom.isActive) {
				res.send(410);
				return next();
			}

			var findParentRomHandler = function(childRom, resultHandler) {
				childRom.getParentRom().success(resultHandler);
			}

			ResultConverter.getChangelogContent(rom, findParentRomHandler, function(body) {
				res.writeHead(200, {
					'Content-Length': Buffer.byteLength(body),
					'Content-Type': 'text/plain'
				});

				res.end(body);

				return next();
			});
		});
	});

	server.get('/download/:romId', function (req, res, next) {
		models.Rom.find(req.params.romId).complete(function(err, rom) {
			if (err) {
				res.send(500);
			} else if (!rom) {
				res.send(404);
			} else if (!rom.isActive) {
				res.send(410);
			} else {
				var realDownloadUrl = ResultConverter.getRealDownloadUrl(rom);

				res.writeHead(301, { Location: realDownloadUrl });
				res.end();

				models.Download.build({
					RomId: rom.id,
					timestamp: new Date(),
				}).save().error(function (err) {
					// Ignoring errors here since those have no impact for the user.
				});
			}

			return next();
		});
	});

	server.post('/api', function(req, res, next) {
		// Currently the CMUpdater app does not send the correct content-type.
		// Thus auto-parsing the body does not work. But we are ready once that problem is fixed.
		var requestParameters = req.is('json') ? req.body : JSON.parse(req.body);

		if (!requestParameters || !requestParameters.params || requestParameters.method != 'get_all_builds') {
			res.send(400);
			return next();
		}

		var responseId = null;

		models.Device.find({ where: { name: requestParameters.params.device } }).complete(function(err, device) {
			if (err) {
				res.send(500, ResultConverter.convert(responseId, 'Database error.', null));
				return next();
			}

			if (!device) {
				// No error but nothing found.
				res.send(200, ResultConverter.convert(responseId, null, null));
				return next();
			}

			models.Rom.findAll({
				where: {
					DeviceId: device.id,
					updateChannel: requestParameters.params.channels,
					isActive: true,
				},
			}).complete(function(err, roms) {
				if (err) {
					res.send(500, ResultConverter.convert(responseId, 'Database error.', null));
				} else {
					res.send(200, ResultConverter.convert(responseId, null, roms));
				}

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


<commit_before>/**
 * X-Content-Type-Options.
 *
 * @see https://blogs.msdn.microsoft.com/ie/2008/09/02/ie8-security-part-vi-beta-2-update/
 */

'use strict';

const HEADER = 'x-content-type-options';
const VALUE = 'nosniff';

module.exports = () => {

  /**
   * No Sniff Middleware.
   *
   * @param {Object} req Express request object.
   * @param {Object} res Express response object.
   * @param {Function} next Express next callback.
   */
  function middleware(req, res, next) {
    res.header(HEADER, VALUE);

    next();
  }

  return middleware;

};<commit_msg>Improved NOSNIFF implementation and docs<commit_after>/**
 * Nosniff module.
 *
 * @module fi-aegis/nosniff
 *
 * @see module:fi-aegis/nosniff
 * @see https://blogs.msdn.microsoft.com/ie/2008/09/02/ie8-security-part-vi-beta-2-update/
 */

'use strict';

const HEADER = 'x-content-type-options';
const VALUE = 'nosniff';

/**
 * Nosniff Middleware.
 *
 * @param {Object} req Express request object.
 * @param {Object} res Express response object.
 * @param {Function} next Express next callback.
 */
function middleware(req, res, next) {
  res.header(HEADER, VALUE);

  next();
}

/**
 * Configures the Nosniff module.
 *
 * @returns {Function} The Express middleware.
 */
module.exports = () => middleware;<|endoftext|>


<commit_before>'use strict'

const extend = require('extend')
const abind = require('abind')
const isArrayKey = require('./key/is_array_key')
const fromArrayKey = require('./key/from_array_key')
const toArrayKey = require('./key/to_array_key')

const isRecursive = (value) => {
  if (!value) {
    return false
  }
  const reservedClasses = [Date]
  const isReservedClass = reservedClasses.some((C) => value instanceof C)
  if (isReservedClass) {
    return false
  }
  switch (typeof value) {
    case 'string':
    case 'number':
    case 'boolean':
    case 'function':
      return false
    default:
      return true
  }
}

/**
 * @memberOf module:objnest
 * @class Objnest
 * @param {object} config
 */
function Objnest (config) {
  extend(this, config || {})
  abind(this)
}

Objnest.prototype = {
  separator: '.',
  /**
   * @function expand
   * @param {object} object - Obj to flatten
   * @returns {object} Flatten obj.
   * @example
   *  const obj = objnest.expand({
   *      'foo.bar': 'baz'
   *  })
   *  console.log(obj) // => {foo: {bar: 'baz'}}
   */
  expand (object) {
    if (Array.isArray(object)) {
      return object.map((object) => this.expand(object))
    }
    if(!isRecursive(object)){
      return object
    }
    const separator = this.separator
    const result = {}
    for (let key of Object.keys(object)) {
      let val = object[key]
      const needsSeparate = !!~key.indexOf(separator)
      if (needsSeparate) {
        const subKeys = key.split(separator)
        const subObj = {}
        const thisKey = subKeys.shift()
        subObj[subKeys.join('.')] = val
        const subExpandedObj = this.expand(subObj)
        const thisVal = result[thisKey]
        val = this._merge(thisVal, subExpandedObj)
        key = thisKey
      }
      if (isArrayKey(key)) {
        const arrayKey = fromArrayKey(key)
        if (!result[arrayKey.name]) {
          const length = object[`${arrayKey.name}[length]`] || 0
          result[arrayKey.name] = new Array(length)
        }
        if (arrayKey.index !== null) {
          result[arrayKey.name][arrayKey.index] = this._merge(
            result[arrayKey.name][arrayKey.index],
            val
          )
        }
      } else {
        result[key] = val
      }
    }
    return result
  },
  /**
   * Flatten nested object.
   * @param {object} nested - Object to flatten.
   * @param {Object} [options={}]
   * @returns {object} - Flattened object.
   * @example
   *  const flattened = objnest.flatten({
   *      'foo': {'bar': 'baz'}
   *  })
   *  console.log(flattened) // => {'foo.bar': 'baz'}
   */
  flatten (nested, options={}) {
    const {parent} = options
    if (!isRecursive(nested)) {
      return nested
    }
    const topLevelArray = Array.isArray(nested) && !parent
    if(topLevelArray){
      return nested.map((v) => this.flatten(v))
    }
    const separator = this.separator
    const flattened = {}
    for (const key of Object.keys(nested || {})) {
      const value = nested[key]
      if (value === null) {
        flattened[key] = value
        continue
      }
      if (isRecursive(value)) {
        const subValues = this.flatten(value, {parent: nested})
        const isArray = Array.isArray(value)
        if (isArray) {
          flattened[`${key}[length]`] = value.length
        }
        for (const subKey of Object.keys(subValues)) {
          let fullKey
          if (isArray) {
            fullKey = key + toArrayKey(subKey)
          } else {
            fullKey = [key, subKey].join(separator)
          }
          flattened[fullKey] = subValues[subKey]
        }
      } else {
        flattened[key] = value
      }
    }
    return flattened
  },
  _merge (v1, v2) {
    if (typeof v1 === 'undefined') {
      return v2
    }
    if (typeof v2 === 'undefined') {
      return v1
    }
    return extend(true, v1, v2 || {})
  }
}

module.exports = Objnest
<commit_msg>Update objnest.js<commit_after>'use strict'

const extend = require('extend')
const abind = require('abind')
const isArrayKey = require('./key/is_array_key')
const fromArrayKey = require('./key/from_array_key')
const toArrayKey = require('./key/to_array_key')

const isRecursive = (value) => {
  if (!value) {
    return false
  }
  const reservedClasses = [Date]
  const isReservedClass = reservedClasses.some((C) => value instanceof C)
  if (isReservedClass) {
    return false
  }
  switch (typeof value) {
    case 'string':
    case 'number':
    case 'boolean':
    case 'function':
      return false
    default:
      return true
  }
}

/**
 * @memberOf module:objnest
 * @class Objnest
 * @param {object} config
 */
function Objnest (config) {
  extend(this, config || {})
  abind(this)
}

Objnest.prototype = {
  separator: '.',
  /**
   * @function expand
   * @param {object} object - Obj to flatten
   * @returns {object} Flatten obj.
   * @example
   *  const obj = objnest.expand({
   *      'foo.bar': 'baz'
   *  })
   *  console.log(obj) // => {foo: {bar: 'baz'}}
   */
  expand (object) {
    if (Array.isArray(object)) {
      return object.map((object) => this.expand(object))
    }
    if(!isRecursive(object)){
      return object
    }
    const separator = this.separator
    const result = {}
    for (let key of Object.keys(object)) {
      let val = object[key]
      const needsSeparate = !!~key.indexOf(separator)
      if (needsSeparate) {
        const subKeys = key.split(separator)
        if (subKeys[0] == '__proto__' || subKeys[0] == 'prototype' || subKeys[0] == 'constructor')
          continue
        const subObj = {}
        const thisKey = subKeys.shift()
        subObj[subKeys.join('.')] = val
        const subExpandedObj = this.expand(subObj)
        const thisVal = result[thisKey]
        val = this._merge(thisVal, subExpandedObj)
        key = thisKey
      }
      if (isArrayKey(key)) {
        const arrayKey = fromArrayKey(key)
        if (!result[arrayKey.name]) {
          const length = object[`${arrayKey.name}[length]`] || 0
          result[arrayKey.name] = new Array(length)
        }
        if (arrayKey.index !== null) {
          result[arrayKey.name][arrayKey.index] = this._merge(
            result[arrayKey.name][arrayKey.index],
            val
          )
        }
      } else {
        result[key] = val
      }
    }
    return result
  },
  /**
   * Flatten nested object.
   * @param {object} nested - Object to flatten.
   * @param {Object} [options={}]
   * @returns {object} - Flattened object.
   * @example
   *  const flattened = objnest.flatten({
   *      'foo': {'bar': 'baz'}
   *  })
   *  console.log(flattened) // => {'foo.bar': 'baz'}
   */
  flatten (nested, options={}) {
    const {parent} = options
    if (!isRecursive(nested)) {
      return nested
    }
    const topLevelArray = Array.isArray(nested) && !parent
    if(topLevelArray){
      return nested.map((v) => this.flatten(v))
    }
    const separator = this.separator
    const flattened = {}
    for (const key of Object.keys(nested || {})) {
      const value = nested[key]
      if (value === null) {
        flattened[key] = value
        continue
      }
      if (isRecursive(value)) {
        const subValues = this.flatten(value, {parent: nested})
        const isArray = Array.isArray(value)
        if (isArray) {
          flattened[`${key}[length]`] = value.length
        }
        for (const subKey of Object.keys(subValues)) {
          let fullKey
          if (isArray) {
            fullKey = key + toArrayKey(subKey)
          } else {
            fullKey = [key, subKey].join(separator)
          }
          flattened[fullKey] = subValues[subKey]
        }
      } else {
        flattened[key] = value
      }
    }
    return flattened
  },
  _merge (v1, v2) {
    if (typeof v1 === 'undefined') {
      return v2
    }
    if (typeof v2 === 'undefined') {
      return v1
    }
    return extend(true, v1, v2 || {})
  }
}

module.exports = Objnest
<|endoftext|>