<commit_before>#!/usr/bin/env node
var http = require('http');
var spawn = require('child_process').spawn;
var launcher = require('browser-launcher');
var concat = require('concat-stream');
var finished = require('tap-finished');
var parseCommand = require('shell-quote').parse;
var ent = require('ent');
var fs = require('fs');

var argv = require('optimist').boolean('u').argv;
if (argv.h || argv.help) {
    return fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout);
}

var unglob = require('../lib/unglob.js');

var path = require('path');
var prelude = fs.readFileSync(__dirname + '/../bundle/prelude.js', 'utf8');

var bundle, launch;
var scripts = [];
var htmlQueue = [];
var pending = 3;
var dir = path.resolve(argv._[0] === '-' ? false : argv._[0] || process.cwd());
var ecstatic = require('ecstatic')(dir);
var resolve = require('resolve').sync;
var pkg = { testling: {} };

if ((process.stdin.isTTY || argv._.length) && argv._[0] !== '-') {
    try {
        pkg = require(path.join(dir, 'package.json'));
    }
    catch (err) {
        if (err.code === 'MODULE_NOT_FOUND') {
            console.error(
                'No package.json in ' + dir + ' found.\n'
                + 'Consult the quick start guide for how to create one:\n'
                + 'https://ci.testling.com/guide/quick_start'
            );
        }
        else {
            console.error(err.message);
        }
        return;
    }

    if (!pkg.testling) {
        console.error(
            'The "testling" field isn\'t present '
            + 'in ' + path.join(dir, 'package.json') + '.\n'
            + 'This field is required by testling. Please consult:\n'
            + 'https://ci.testling.com/guide/quick_start'
        );
        return;
    }
    var bundleId = Math.floor(Math.pow(16,8)*Math.random()).toString(16);

    if (pkg.testling.preprocess) {
        // todo
    }
    else if (!pkg.testling.html) {
        unglob(dir, pkg.testling, function (err, expanded) {
            if (err) return console.error(err);
            process.env.PATH = path.resolve(dir, 'node_modules/.bin')
                + ':' + process.env.PATH
            ;
            scripts = expanded.script;

            if (expanded.file.length) {
                var args = expanded.file.concat('--debug');
                var ps = spawn('browserify', args, { cwd: dir });
                ps.stdout.pipe(concat(function (src) {
                    bundle = src;
                    htmlQueue.forEach(function (f) { getHTML(f) });
                }));
                ps.stderr.pipe(process.stderr);
                ps.on('exit', function (code) {
                    if (code !== 0) {
                        console.error('FAILURE: non-zero exit code');
                    }
                    else ready();
                });
            }
            else if (expanded.script.length) {
                ready();
            }
            else {
                console.error(
                    'No test files, no scripts, and no html parameter found'
                    + 'after expanding the globs. At least one file or a custom'
                    + 'html field is needed.'
                );
                process.exit(1);
            }
        });
    }

}
else {
    process.stdin.pipe(concat(function (src) {
        bundle = src;
        htmlQueue.forEach(function (f) { getHTML(f) });
        ready();
    }));
}

var xws = require('xhr-write-stream')();

if (argv.html) {
    getHTML(function (html) { console.log(html) });
    return;
}

var server = http.createServer(function (req, res) {
    if (req.url === '/__testling/sock') {
        req.pipe(xws(function (stream) {
            stream.pipe(process.stdout, { end: false });
            stream.pipe(finished(function (results) {
                if (results.ok) {
                    process.exit(0);
                }
                else process.exit(1);
            }));
        }));
        req.on('end', res.end.bind(res));
    }
    else if (req.url.split('?')[0].replace(/\/$/, '') === '/__testling') {
        res.setHeader('content-type', 'text/html');
        getHTML(function (html) { res.end(html) });
    }
    else {
        ecstatic(req, res);
    }
});

server.listen(0, ready);

if ((argv.x || argv.bcmd) && typeof (argv.x || argv.bcmd) === 'boolean') {
    console.error('-x expects an argument');
    process.exit(1);
}

if (argv.u || argv.cmd || argv.x || argv.bcmd) {
    ready();
}
else {
    launcher(function (err, launch_) {
        if (err) return console.error(err);
        launch = launch_;
        ready();
    });
}

function ready () {
    if (--pending !== 0) return;

    var opts = {
        headless: true,
        browser: launch && launch.browsers && launch.browsers.local[0].name
    };
    var href = 'http://localhost:' + server.address().port + '/__testling';
    if (argv.u) {
        console.log(href);
    }
    else if (argv.bcmd || argv.x) {
        var cmd = parseCommand(argv.bcmd || argv.x);
        var ps = spawn(cmd[0], cmd.slice(1).concat(href));
        ps.stderr.pipe(process.stderr);
        ps.stdout.pipe(process.stderr);
        ps.on('exit', function (code) {
            if (code !== 0) {
                console.error(
                    'Command ' + JSON.stringify(argv.bcmd)
                    + ' terminated with non-zero exit code'
                );
            }
        });
    }
    else {
        launch(href, opts, function (err, ps) {
            if (err) return console.error(err);
        });
    }
}

function getHTML (cb) {
    if (bundle === undefined) return htmlQueue.push(cb);

    if (pkg.testling.html) {
        fs.readFile(path.join(dir, pkg.testling.html), function (err, src) {
            if (err) console.error('while loading testling.html: ' + err);
            else {
                cb('' + src);
            }
        });
        return;
    }
    var before = '', after = '';
    if (/^mocha(-|$)/.test(pkg.testling.harness)) {
        var mochaFile = path.relative(dir,
            resolve('mocha/mocha.js', { basedir: dir })
        );
        var m = /^mocha-(\w+)/.exec(pkg.testling.harness);
        var ui = m && m[1] || 'bdd';
        before =
            ''
            + ''
        ;
        after = '';
    }

    cb(''
        + ''
        + before
        + scripts.map(function (s) {
            return ''
        }).join('\n')
        + ''
        + after
        + ''
    );
}
<commit_msg>host static files until __testling too<commit_after>#!/usr/bin/env node
var http = require('http');
var spawn = require('child_process').spawn;
var launcher = require('browser-launcher');
var concat = require('concat-stream');
var finished = require('tap-finished');
var parseCommand = require('shell-quote').parse;
var ent = require('ent');
var fs = require('fs');

var argv = require('optimist').boolean('u').argv;
if (argv.h || argv.help) {
    return fs.createReadStream(__dirname + '/usage.txt').pipe(process.stdout);
}

var unglob = require('../lib/unglob.js');

var path = require('path');
var prelude = fs.readFileSync(__dirname + '/../bundle/prelude.js', 'utf8');

var bundle, launch;
var scripts = [];
var htmlQueue = [];
var pending = 3;
var dir = path.resolve(argv._[0] === '-' ? false : argv._[0] || process.cwd());
var ecstatic = require('ecstatic')(dir);
var resolve = require('resolve').sync;
var pkg = { testling: {} };

if ((process.stdin.isTTY || argv._.length) && argv._[0] !== '-') {
    try {
        pkg = require(path.join(dir, 'package.json'));
    }
    catch (err) {
        if (err.code === 'MODULE_NOT_FOUND') {
            console.error(
                'No package.json in ' + dir + ' found.\n'
                + 'Consult the quick start guide for how to create one:\n'
                + 'https://ci.testling.com/guide/quick_start'
            );
        }
        else {
            console.error(err.message);
        }
        return;
    }

    if (!pkg.testling) {
        console.error(
            'The "testling" field isn\'t present '
            + 'in ' + path.join(dir, 'package.json') + '.\n'
            + 'This field is required by testling. Please consult:\n'
            + 'https://ci.testling.com/guide/quick_start'
        );
        return;
    }
    var bundleId = Math.floor(Math.pow(16,8)*Math.random()).toString(16);

    if (pkg.testling.preprocess) {
        // todo
    }
    else if (!pkg.testling.html) {
        unglob(dir, pkg.testling, function (err, expanded) {
            if (err) return console.error(err);
            process.env.PATH = path.resolve(dir, 'node_modules/.bin')
                + ':' + process.env.PATH
            ;
            scripts = expanded.script;

            if (expanded.file.length) {
                var args = expanded.file.concat('--debug');
                var ps = spawn('browserify', args, { cwd: dir });
                ps.stdout.pipe(concat(function (src) {
                    bundle = src;
                    htmlQueue.forEach(function (f) { getHTML(f) });
                }));
                ps.stderr.pipe(process.stderr);
                ps.on('exit', function (code) {
                    if (code !== 0) {
                        console.error('FAILURE: non-zero exit code');
                    }
                    else ready();
                });
            }
            else if (expanded.script.length) {
                ready();
            }
            else {
                console.error(
                    'No test files, no scripts, and no html parameter found'
                    + 'after expanding the globs. At least one file or a custom'
                    + 'html field is needed.'
                );
                process.exit(1);
            }
        });
    }

}
else {
    process.stdin.pipe(concat(function (src) {
        bundle = src;
        htmlQueue.forEach(function (f) { getHTML(f) });
        ready();
    }));
}

var xws = require('xhr-write-stream')();

if (argv.html) {
    getHTML(function (html) { console.log(html) });
    return;
}

var server = http.createServer(function (req, res) {
    var u = req.url.split('?')[0];

    if (u === '/__testling/sock') {
        req.pipe(xws(function (stream) {
            stream.pipe(process.stdout, { end: false });
            stream.pipe(finished(function (results) {
                if (results.ok) {
                    process.exit(0);
                }
                else process.exit(1);
            }));
        }));
        req.on('end', res.end.bind(res));
    }
    else if (u.replace(/\/$/, '') === '/__testling') {
        res.setHeader('content-type', 'text/html');
        getHTML(function (html) { res.end(html) });
    }
    else if (u.split('/')[1] === '__testling') {
        req.url = req.url.replace(/^\/__testling/, '');
        ecstatic(req, res);
    }
});

server.listen(0, ready);

if ((argv.x || argv.bcmd) && typeof (argv.x || argv.bcmd) === 'boolean') {
    console.error('-x expects an argument');
    process.exit(1);
}

if (argv.u || argv.cmd || argv.x || argv.bcmd) {
    ready();
}
else {
    launcher(function (err, launch_) {
        if (err) return console.error(err);
        launch = launch_;
        ready();
    });
}

function ready () {
    if (--pending !== 0) return;

    var opts = {
        headless: true,
        browser: launch && launch.browsers && launch.browsers.local[0].name
    };
    var href = 'http://localhost:' + server.address().port + '/__testling';
    if (argv.u) {
        console.log(href);
    }
    else if (argv.bcmd || argv.x) {
        var cmd = parseCommand(argv.bcmd || argv.x);
        var ps = spawn(cmd[0], cmd.slice(1).concat(href));
        ps.stderr.pipe(process.stderr);
        ps.stdout.pipe(process.stderr);
        ps.on('exit', function (code) {
            if (code !== 0) {
                console.error(
                    'Command ' + JSON.stringify(argv.bcmd)
                    + ' terminated with non-zero exit code'
                );
            }
        });
    }
    else {
        launch(href, opts, function (err, ps) {
            if (err) return console.error(err);
        });
    }
}

function getHTML (cb) {
    if (bundle === undefined) return htmlQueue.push(cb);

    if (pkg.testling.html) {
        fs.readFile(path.join(dir, pkg.testling.html), function (err, src) {
            if (err) console.error('while loading testling.html: ' + err);
            else {
                cb('' + src);
            }
        });
        return;
    }
    var before = '', after = '';
    if (/^mocha(-|$)/.test(pkg.testling.harness)) {
        var mochaFile = path.relative(dir,
            resolve('mocha/mocha.js', { basedir: dir })
        );
        var m = /^mocha-(\w+)/.exec(pkg.testling.harness);
        var ui = m && m[1] || 'bdd';
        before =
            ''
            + ''
        ;
        after = '';
    }

    cb(''
        + ''
        + before
        + scripts.map(function (s) {
            return ''
        }).join('\n')
        + ''
        + after
        + ''
    );
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var minimist = require('minimist');
var level = require('level');
var strftime = require('strftime');
var sprintf = require('sprintf');
var through = require('through');

var argv = minimist(process.argv.slice(2), {
    alias: { m: 'message' }
});
var HOME = process.env.HOME || process.env.USERPROFILE;
var datadir = argv.d || path.join(HOME, '.clocker');
mkdirp.sync(datadir);

var db = level(path.join(datadir, 'db'), { encoding: 'json' });

if (argv.h) usage(0)
else if (argv._[0] === 'start') {
    var d = argv.d ? new Date(argv.d) : new Date;
    var type = argv.type || argv.t;
    var pkey = strftime('time!%F %T', d);
    var tkey = 'time-type!' + type + '!' + strftime('%F %T', d);
    db.batch([
        { type: 'put', key: pkey, value: { type: type } },
        { type: 'put', key: tkey, value: 0 }
    ], error);
}
else if (argv._[0] === 'stop') {
    var d = argv.d ? new Date(argv.d) : new Date;
    var s = db.createReadStream({
        gt: 'time!', lt: 'time!~',
        limit: 1, reverse: true
    });
    s.once('data', function (row) {
        if (argv.message) row.value.message = argv.message;
        row.value.end = strftime('%F %T', d);
        db.put(row.key, row.value, error);
    });
}
else if (argv._[0] === 'status') {
    var s = db.createReadStream({
        gt: 'time!', lt: 'time!~',
        limit: 1, reverse: true
    });
    s.once('data', function (row) {
        var started = new Date(row.key.split('!')[1]);
        if (!row.value.end) {
            var elapsed = (new Date) - started;
            console.log('elapsed time: ' + fmt(elapsed));
        }
        else {
            console.log('stopped');
        }
    });
}
else if (argv._[0] === 'data') {
    var type = argv.type || argv.t || argv._[1];
    var rate = argv.rate || argv.r || argv._[2];
    var title = argv.title || 'consulting';

    var s = db.createReadStream({ gt: 'time!', lt: 'time!~' });
    var rows = [];
    var write = function (row) {
        if (!type) rows.push(row);
        if (row.value.type === type) rows.push(row)
    };
    s.pipe(through(write, function () {
        var hours = rows.reduce(function reducer (acc, row) {
            if (!row.value.end) {
                console.error("clocked time hasn't ended yet");
                return process.exit(1);
            }
            var start = new Date(row.key.split('!')[1]);
            var end = new Date(row.value.end);
            var key = strftime('%F', start);
            if (key !== strftime('%F', end)) {
                var nextDay = new Date(start);
                nextDay.setDate(start.getDate() + 1);
                nextDay.setHours(0);
                nextDay.setMinutes(0);
                nextDay.setSeconds(0);
                nextDay.setMilliseconds(0);

                acc = reducer(acc, {
                    key: 'time!' + strftime('%F %T', nextDay),
                    value: row.value
                });
                end = nextDay;
            }
            var hours = (end - start) / 1000 / 60 / 60;
            if (!acc[key]) {
                acc[key] = {
                    date: strftime('%F', start),
                    hours: 0
                };
            }
            acc[key].hours += hours;
            return acc;
        }, {});

        console.log(JSON.stringify([ {
            title: title,
            rate: rate,
            hours: Object.keys(hours).map(function (key) {
                var h = hours[key];
                return {
                    date: h.date,
                    hours: Number(sprintf('%.1f', h.hours))
                };
            })
        } ], null, 2));
    }));
}
else if (argv._[0] === 'list') {
    var s = db.createReadStream({ gt: 'time!', lt: 'time!~' });
    s.on('error', error);
    s.pipe(through(function (row) {
        var start = new Date(row.key.split('!')[1]);
        var end = row.value.end && new Date(row.value.end);
        var elapsed = (end ? end : new Date) - start;

        console.log(
            '%s  %s  [ %s - %s ]  (%s)%s',
            toStamp(row.key),
            strftime('%F', start),
            strftime('%T', start),
            end ? strftime('%T', end) : 'NOW',
            fmt(elapsed),
            (row.value.type ? '  [' + row.value.type + ']' : '')
        );
    }));
}
else if (argv._[0] === 'get') {
    var key = getKey(argv._[1]);
    db.get(key, function (err, row) {
        if (err) return error(err);
        console.log(row);
    });
}
else if (argv._[0] === 'rm') {
    var key = getKey(argv._[1]);
    db.del(key, error);
}
else if (argv._[0] === 'set') {
    if (argv._.length < 3) {
        return error('clocker adjust STAMP KEY VALUE');
    }
    var key = getKey(argv._[1]);
    var k = argv._[2];
    var value = argv._.slice(3).join(' ');

    if (k === 'end') {
        db.get(key, function (err, row) {
            if (err) return error(err);
            row[k] = updateDate(value, row[k]);
            db.put(key, row, error);
        });
    }
    else if (k === 'start') {
        db.get(key, function (err, row) {
            if (err) return error(err);
            var newKey = 'time!' + updateDate(value, key.split('!')[1]);

            db.batch([
                { type: 'put', key: newKey, value: row },
                { type: 'del', key: key }
            ], error);
        });
    }
    else if (k === 'type') {
        db.get(key, function (err, row) {
            if (err) return error(err);
            var prevType = row.type;
            row.type = value;
            db.batch([
                prevType && { type: 'del', key: prevType },
                { type: 'put', key: key, value: row }
            ].filter(Boolean), error);
        });
    }
    else {
        db.get(key, function (err, row) {
            if (err) return error(err);
            if (value === '') delete row[k];
            else row[k] = value;
            db.put(key, row, error);
        });
    }
}
else usage(1)

function usage (code) {
    var rs = fs.createReadStream(__dirname + '/usage.txt');
    rs.pipe(process.stdout);
    rs.on('close', function () {
        if (code) process.exit(code);
    });
}

function pad (s, len) {
    return Array(Math.max(0, len - String(s).length + 1)).join('0') + s;
}

function fmt (elapsed) {
    var n = elapsed / 1000;
    var hh = pad(Math.floor(n / 60 / 60), 2);
    var mm = pad(Math.floor(n / 60 % 60), 2);
    var ss = pad(Math.floor(n % 60), 2);
    return [ hh, mm, ss ].join(':');
}

function error (err) {
    if (!err) return;
    console.error(String(err));
    process.exit(1);
}

function toStamp (s) {
    return Math.floor(new Date(s.split('!')[1]).valueOf() / 1000);
}

function getKey (x) {
    return strftime('time!%F %T', new Date(x * 1000));
}

function updateDate (value, old) {
    var d = new Date(value);
    if (isNaN(d.valueOf())) {
        if (!old || isNaN(old)) {
            old = key.split('!')[1];
        }
        d = new Date(old.split(' ')[0] + ' ' + value);
    }
    return strftime('%F %T', d);
}
<commit_msg>show messages in list -v<commit_after>#!/usr/bin/env node
var fs = require('fs');
var path = require('path');
var mkdirp = require('mkdirp');
var minimist = require('minimist');
var level = require('level');
var strftime = require('strftime');
var sprintf = require('sprintf');
var through = require('through');

var argv = minimist(process.argv.slice(2), {
    alias: { m: 'message', v: 'verbose' }
});
var HOME = process.env.HOME || process.env.USERPROFILE;
var datadir = argv.d || path.join(HOME, '.clocker');
mkdirp.sync(datadir);

var db = level(path.join(datadir, 'db'), { encoding: 'json' });

if (argv.h) usage(0)
else if (argv._[0] === 'start') {
    var d = argv.d ? new Date(argv.d) : new Date;
    var type = argv.type || argv.t;
    var pkey = strftime('time!%F %T', d);
    var tkey = 'time-type!' + type + '!' + strftime('%F %T', d);
    db.batch([
        { type: 'put', key: pkey, value: { type: type } },
        { type: 'put', key: tkey, value: 0 }
    ], error);
}
else if (argv._[0] === 'stop') {
    var d = argv.d ? new Date(argv.d) : new Date;
    var s = db.createReadStream({
        gt: 'time!', lt: 'time!~',
        limit: 1, reverse: true
    });
    s.once('data', function (row) {
        if (argv.message) row.value.message = argv.message;
        row.value.end = strftime('%F %T', d);
        db.put(row.key, row.value, error);
    });
}
else if (argv._[0] === 'status') {
    var s = db.createReadStream({
        gt: 'time!', lt: 'time!~',
        limit: 1, reverse: true
    });
    s.once('data', function (row) {
        var started = new Date(row.key.split('!')[1]);
        if (!row.value.end) {
            var elapsed = (new Date) - started;
            console.log('elapsed time: ' + fmt(elapsed));
        }
        else {
            console.log('stopped');
        }
    });
}
else if (argv._[0] === 'data') {
    var type = argv.type || argv.t || argv._[1];
    var rate = argv.rate || argv.r || argv._[2];
    var title = argv.title || 'consulting';

    var s = db.createReadStream({ gt: 'time!', lt: 'time!~' });
    var rows = [];
    var write = function (row) {
        if (!type) rows.push(row);
        if (row.value.type === type) rows.push(row)
    };
    s.pipe(through(write, function () {
        var hours = rows.reduce(function reducer (acc, row) {
            if (!row.value.end) {
                console.error("clocked time hasn't ended yet");
                return process.exit(1);
            }
            var start = new Date(row.key.split('!')[1]);
            var end = new Date(row.value.end);
            var key = strftime('%F', start);
            if (key !== strftime('%F', end)) {
                var nextDay = new Date(start);
                nextDay.setDate(start.getDate() + 1);
                nextDay.setHours(0);
                nextDay.setMinutes(0);
                nextDay.setSeconds(0);
                nextDay.setMilliseconds(0);

                acc = reducer(acc, {
                    key: 'time!' + strftime('%F %T', nextDay),
                    value: row.value
                });
                end = nextDay;
            }
            var hours = (end - start) / 1000 / 60 / 60;
            if (!acc[key]) {
                acc[key] = {
                    date: strftime('%F', start),
                    hours: 0
                };
            }
            acc[key].hours += hours;
            return acc;
        }, {});

        console.log(JSON.stringify([ {
            title: title,
            rate: rate,
            hours: Object.keys(hours).map(function (key) {
                var h = hours[key];
                return {
                    date: h.date,
                    hours: Number(sprintf('%.1f', h.hours))
                };
            })
        } ], null, 2));
    }));
}
else if (argv._[0] === 'list') {
    var s = db.createReadStream({ gt: 'time!', lt: 'time!~' });
    s.on('error', error);
    s.pipe(through(function (row) {
        var start = new Date(row.key.split('!')[1]);
        var end = row.value.end && new Date(row.value.end);
        var elapsed = (end ? end : new Date) - start;

        console.log(
            '%s  %s  [ %s - %s ]  (%s)%s',
            toStamp(row.key),
            strftime('%F', start),
            strftime('%T', start),
            end ? strftime('%T', end) : 'NOW',
            fmt(elapsed),
            (row.value.type ? '  [' + row.value.type + ']' : '')
        );
        if (argv.verbose && row.value.message) {
            var lines = row.value.message.split('\n');
            console.log();
            lines.forEach(function (line) {
                console.log('    ' + line);
            });
            console.log();
        }
    }));
}
else if (argv._[0] === 'get') {
    var key = getKey(argv._[1]);
    db.get(key, function (err, row) {
        if (err) return error(err);
        console.log(row);
    });
}
else if (argv._[0] === 'rm') {
    var key = getKey(argv._[1]);
    db.del(key, error);
}
else if (argv._[0] === 'set') {
    if (argv._.length < 3) {
        return error('clocker adjust STAMP KEY VALUE');
    }
    var key = getKey(argv._[1]);
    var k = argv._[2];
    var value = argv._.slice(3).join(' ');

    if (k === 'end') {
        db.get(key, function (err, row) {
            if (err) return error(err);
            row[k] = updateDate(value, row[k]);
            db.put(key, row, error);
        });
    }
    else if (k === 'start') {
        db.get(key, function (err, row) {
            if (err) return error(err);
            var newKey = 'time!' + updateDate(value, key.split('!')[1]);

            db.batch([
                { type: 'put', key: newKey, value: row },
                { type: 'del', key: key }
            ], error);
        });
    }
    else if (k === 'type') {
        db.get(key, function (err, row) {
            if (err) return error(err);
            var prevType = row.type;
            row.type = value;
            db.batch([
                prevType && { type: 'del', key: prevType },
                { type: 'put', key: key, value: row }
            ].filter(Boolean), error);
        });
    }
    else {
        db.get(key, function (err, row) {
            if (err) return error(err);
            if (value === '') delete row[k];
            else row[k] = value;
            db.put(key, row, error);
        });
    }
}
else usage(1)

function usage (code) {
    var rs = fs.createReadStream(__dirname + '/usage.txt');
    rs.pipe(process.stdout);
    rs.on('close', function () {
        if (code) process.exit(code);
    });
}

function pad (s, len) {
    return Array(Math.max(0, len - String(s).length + 1)).join('0') + s;
}

function fmt (elapsed) {
    var n = elapsed / 1000;
    var hh = pad(Math.floor(n / 60 / 60), 2);
    var mm = pad(Math.floor(n / 60 % 60), 2);
    var ss = pad(Math.floor(n % 60), 2);
    return [ hh, mm, ss ].join(':');
}

function error (err) {
    if (!err) return;
    console.error(String(err));
    process.exit(1);
}

function toStamp (s) {
    return Math.floor(new Date(s.split('!')[1]).valueOf() / 1000);
}

function getKey (x) {
    return strftime('time!%F %T', new Date(x * 1000));
}

function updateDate (value, old) {
    var d = new Date(value);
    if (isNaN(d.valueOf())) {
        if (!old || isNaN(old)) {
            old = key.split('!')[1];
        }
        d = new Date(old.split(' ')[0] + ' ' + value);
    }
    return strftime('%F %T', d);
}
<|endoftext|>


<commit_before>#!/usr/bin/env node
/**
 * An executable command which will be added to $PATH.
 *
 * @copyright Copyright 2017-2019 Kevin Locke <kevin@kevinlocke.name>
 * @license MIT
 */

'use strict';

const Yargs = require('yargs/yargs');
const packageJson = require('../package.json');
const modulename = require('..');

/** Options for command entry points.
 *
 * @typedef {{
 *   stdin: !stream.Readable,
 *   stdout: !stream.Writable,
 *   stderr: !stream.Writable
 * }} CommandOptions
 * @property {!stream.Readable} stdin Stream from which input is read.
 * @property {!stream.Writable} stdout Stream to which output is written.
 * @property {!stream.Writable} stderr Stream to which errors and non-output
 * status messages are written.
 */
// const CommandOptions;

/** Entry point for this command.
 *
 * @param {Array<string>} args Command-line arguments.
 * @param {!CommandOptions} options Options.
 * @param {function(number)} callback Callback with exit code.
 */
function modulenameCmd(args, options, callback) {
  if (typeof callback !== 'function') {
    throw new TypeError('callback must be a function');
  }

  if (args !== undefined
      && args !== null
      && Math.floor(args.length) !== args.length) {
    throw new TypeError('args must be Array-like');
  }

  if (!options || typeof options !== 'object') {
    throw new TypeError('options must be an object');
  }

  if (!options.stdin || typeof options.stdin.on !== 'function') {
    throw new TypeError('options.stdin must be a stream.Readable');
  }
  if (!options.stdout || typeof options.stdout.write !== 'function') {
    throw new TypeError('options.stdout must be a stream.Writable');
  }
  if (!options.stderr || typeof options.stderr.write !== 'function') {
    throw new TypeError('options.stderr must be a stream.Writable');
  }

  if (args.length >= 2) {
    // Strip "node" and script name, ensure args are strings
    args = Array.prototype.slice.call(args, 2).map(String);
  } else {
    args = [];
  }

  // Workaround for https://github.com/yargs/yargs/issues/783
  // Necessary because mocha package.json overrides .parserConfiguration()
  require.main = module;
  const yargs = new Yargs(null, null, require)
    .parserConfiguration({
      'parse-numbers': false,
      'duplicate-arguments-array': false,
      'flatten-duplicate-arrays': false,
    })
    .usage('Usage: $0 [options] [args...]')
    .help()
    .alias('help', 'h')
    .alias('help', '?')
    .option('quiet', {
      alias: 'q',
      describe: 'Print less output',
      count: true,
    })
    .option('verbose', {
      alias: 'v',
      describe: 'Print more output',
      count: true,
    })
    .version(`${packageJson.name} ${packageJson.version}`)
    .alias('version', 'V')
    .strict();
  yargs.parse(args, (err, argOpts, output) => {
    if (err) {
      if (output) {
        options.stderr.write(`${output}\n`);
      } else {
        options.stderr.write(`${err.name}: ${err.message}\n`);
      }
      callback(null, 1);
      return;
    }

    if (output) {
      options.stdout.write(`${output}\n`);
    }

    if (argOpts.help || argOpts.version) {
      callback(0);
      return;
    }

    if (argOpts._.length !== 1) {
      options.stderr.write('Error: Exactly one argument is required.\n');
      callback(1);
      return;
    }

    // Parse arguments then call API function with parsed options
    const cmdOpts = {
      files: argOpts._,
      verbosity: argOpts.verbose - argOpts.quiet,
    };
    modulename(cmdOpts, callback);
  });
}

modulenameCmd.default = modulenameCmd;
module.exports = modulenameCmd;

if (require.main === module) {
  // This file was invoked directly.
  // Note:  Could pass process.exit as callback to force immediate exit.
  modulenameCmd(process.argv, process, (exitCode) => {
    process.exitCode = exitCode;
  });
}
<commit_msg>fix: yargs-parser greedy-arrays: false<commit_after>#!/usr/bin/env node
/**
 * An executable command which will be added to $PATH.
 *
 * @copyright Copyright 2017-2019 Kevin Locke <kevin@kevinlocke.name>
 * @license MIT
 */

'use strict';

const Yargs = require('yargs/yargs');
const packageJson = require('../package.json');
const modulename = require('..');

/** Options for command entry points.
 *
 * @typedef {{
 *   stdin: !stream.Readable,
 *   stdout: !stream.Writable,
 *   stderr: !stream.Writable
 * }} CommandOptions
 * @property {!stream.Readable} stdin Stream from which input is read.
 * @property {!stream.Writable} stdout Stream to which output is written.
 * @property {!stream.Writable} stderr Stream to which errors and non-output
 * status messages are written.
 */
// const CommandOptions;

/** Entry point for this command.
 *
 * @param {Array<string>} args Command-line arguments.
 * @param {!CommandOptions} options Options.
 * @param {function(number)} callback Callback with exit code.
 */
function modulenameCmd(args, options, callback) {
  if (typeof callback !== 'function') {
    throw new TypeError('callback must be a function');
  }

  if (args !== undefined
      && args !== null
      && Math.floor(args.length) !== args.length) {
    throw new TypeError('args must be Array-like');
  }

  if (!options || typeof options !== 'object') {
    throw new TypeError('options must be an object');
  }

  if (!options.stdin || typeof options.stdin.on !== 'function') {
    throw new TypeError('options.stdin must be a stream.Readable');
  }
  if (!options.stdout || typeof options.stdout.write !== 'function') {
    throw new TypeError('options.stdout must be a stream.Writable');
  }
  if (!options.stderr || typeof options.stderr.write !== 'function') {
    throw new TypeError('options.stderr must be a stream.Writable');
  }

  if (args.length >= 2) {
    // Strip "node" and script name, ensure args are strings
    args = Array.prototype.slice.call(args, 2).map(String);
  } else {
    args = [];
  }

  // Workaround for https://github.com/yargs/yargs/issues/783
  // Necessary because mocha package.json overrides .parserConfiguration()
  require.main = module;
  const yargs = new Yargs(null, null, require)
    .parserConfiguration({
      'parse-numbers': false,
      'duplicate-arguments-array': false,
      'flatten-duplicate-arrays': false,
      'greedy-arrays': false,
    })
    .usage('Usage: $0 [options] [args...]')
    .help()
    .alias('help', 'h')
    .alias('help', '?')
    .option('quiet', {
      alias: 'q',
      describe: 'Print less output',
      count: true,
    })
    .option('verbose', {
      alias: 'v',
      describe: 'Print more output',
      count: true,
    })
    .version(`${packageJson.name} ${packageJson.version}`)
    .alias('version', 'V')
    .strict();
  yargs.parse(args, (err, argOpts, output) => {
    if (err) {
      if (output) {
        options.stderr.write(`${output}\n`);
      } else {
        options.stderr.write(`${err.name}: ${err.message}\n`);
      }
      callback(null, 1);
      return;
    }

    if (output) {
      options.stdout.write(`${output}\n`);
    }

    if (argOpts.help || argOpts.version) {
      callback(0);
      return;
    }

    if (argOpts._.length !== 1) {
      options.stderr.write('Error: Exactly one argument is required.\n');
      callback(1);
      return;
    }

    // Parse arguments then call API function with parsed options
    const cmdOpts = {
      files: argOpts._,
      verbosity: argOpts.verbose - argOpts.quiet,
    };
    modulename(cmdOpts, callback);
  });
}

modulenameCmd.default = modulenameCmd;
module.exports = modulenameCmd;

if (require.main === module) {
  // This file was invoked directly.
  // Note:  Could pass process.exit as callback to force immediate exit.
  modulenameCmd(process.argv, process, (exitCode) => {
    process.exitCode = exitCode;
  });
}
<|endoftext|>


<commit_before>/** DAX - Download and extract mongodb with given version and extraction directory or defaults **/

var
  logger = require('npmlog'),
  args = process.argv.splice(process.execArgv.length + 2),

  nems = require('../lib/nems'),

  MODULE_NAME = require('../package.json').name,
  MESSAGE_START = 'Starting distribution of mongodb!',
  MESSAGE_USAGE = 'Usage:\n\nnode ./lib/nems.js [version [dir]]\n\nversion - the version of the mongodb\ndir - the directory to download and extract to',
  MESSAGE_DEFAULTS= 'Using default configuration for download and extraction.';

logger.info(MODULE_NAME, MESSAGE_START);

if (args.length > 2) {
  logger.warn(MODULE_NAME, MESSAGE_USAGE);
  return;
} else if (args.length === 0) {
  logger.info(MODULE_NAME, MESSAGE_DEFAULTS);
}

var
  VERSION = (args[0]) ? args[0] : '2.4.9',
  DOWNLOAD_DIR = args[1];

nems.distribute(VERSION, DOWNLOAD_DIR);<commit_msg>feat (nems) enrich message output in binary script<commit_after>/** DAX - Download and extract mongodb with given version and extraction directory or defaults **/

var
  logger = require('npmlog'),
  sprintf = require('sprintf-js').sprintf,
  args = process.argv.splice(process.execArgv.length + 2),

  nems = require('../lib/nems'),

  MODULE_NAME = require('../package.json').name,
  MESSAGE_START = 'Starting distribution of mongodb!',
  MESSAGE_USAGE = 'Usage:\n\nnode ./lib/nems.js [version [dir]]\n\nversion - the version of the mongodb\ndir - the directory to download and extract to',
  MESSAGE_DEFAULTS = 'Using default configuration for download and extraction.',
  MESSAGE_FAILURE = 'Download or extraction failed. No file information returned from extraction',
  MESSAGE_EXTRACTED = 'Extracted %s files to %s.',
  MESSAGE_SUCCESS = 'Download and extraction completed.';

logger.info(MODULE_NAME, MESSAGE_START);

if (args.length > 2) {
  logger.warn(MODULE_NAME, MESSAGE_USAGE);
  return;
} else if (args.length === 0) {
  logger.info(MODULE_NAME, MESSAGE_DEFAULTS);
}

var
  VERSION = (args[0]) ? args[0] : '2.4.9',
  DOWNLOAD_DIR = args[1];

nems.distribute(VERSION, DOWNLOAD_DIR)
  .then(function(files) {
    if (!files || files.length === 0) {
      logger.info(MODULE_NAME, MESSAGE_FAILURE);
      return;
    }
    logger.info(MODULE_NAME, sprintf(MESSAGE_EXTRACTED, files.length, files[0]['base']));
    logger.info(MODULE_NAME, MESSAGE_SUCCESS);
  });<|endoftext|>


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

const fs = require('fs-extra')
const path = require('path')
const program = require('commander')
const pm2 = require('pm2')
const chalk = require('chalk')
const npmRunScript = require('npm-run-script')
const opn = require('opn')

const __ = require('../utils/translate')
const sleep = require('../utils/sleep')
const getPort = require('../utils/get-port')
const spinner = require('../utils/spinner')
const readBuildConfigFile = require('../utils/read-build-config-file')
const getAppType = require('../utils/get-app-type')
const setEnvFromCommand = require('../utils/set-env-from-command')
const getChunkmapPath = require('../utils/get-chunkmap-path')
const initNodeEnv = require('../utils/init-node-env')

program
    .version(require('../package').version, '-v, --version')
    .usage('[options]')
    .option('-c, --client', 'Set STAGE to CLIENT')
    .option('-s, --server', 'Set STAGE to SERVER')
    .option('--stage <stage>', 'Set STAGE')
    .option('--config <config-file-path>', 'Set config file')
    .option('--type <project-type>', 'Set project type')
    .parse(process.argv)

/**
 * 进入开发环境
 * ****************************************************************************
 * 同构 (isomorphic)
 * 以 PM2 进程方式顺序执行以下流程
 *      1. 启动 webpack-dev-server (STAGE: client)
 *      2. 启动 webpack (watch mode) (STAGE: server)
 *      3. 运行 /server/index.js
 * ****************************************************************************
 * 单页面应用 (SPA)
 * 强制设置 STAGE 为 client，并启动 webpack-dev-server
 * ****************************************************************************
 */
const run = async () => {
    // 清空 log
    process.stdout.write('\x1B[2J\x1B[0f')

    const {
        client, server,
        stage: _stage,
        config,
        type,
    } = program

    initNodeEnv()
    setEnvFromCommand({
        config,
        type,
    })

    let stage = _stage ? _stage : (client ? 'client' : (server ? 'server' : false))

    // if (!stage) {
    //     console.log(
    //         chalk.redBright('× ')
    //         + __('dev.missing_stage', {
    //             example: 'super-dev ' + chalk.green('--client'),
    //             indent: '  '
    //         })
    //     )
    //     return
    // }

    // 读取项目信息
    const appType = await getAppType()
    const packageInfo = await fs.readJson(path.resolve(process.cwd(), 'package.json'))
    const { dist, port } = await readBuildConfigFile()
    const {
        name
    } = packageInfo

    // 如果为 SPA，强制设置 STAGE
    if (process.env.WEBPACK_BUILD_TYPE === 'spa') {
        process.env.WEBPACK_BUILD_STAGE = 'client'
        stage = 'client'
    }

    // 如果配置中存在 port，修改环境变量
    if (typeof port !== 'undefined')
        process.env.SERVER_PORT = getPort(port, 'dev')

    // 如果设置了 stage，仅运行该 stage
    if (stage) {
        const cmd = `super-build --stage ${stage} --env dev`
        const child = npmRunScript(cmd, {})
        child.once('error', (error) => {
            console.trace(error)
            process.exit(1)
        })
        child.once('exit', (/*exitCode*/) => {
            // console.trace('exit in', exitCode)
            // process.exit(exitCode)
        })
        return
    } else {
        // 没有设置 STAGE，开始 PM2 进程

        let waitingSpinner = false
        // spinner(
        //     chalk.yellowBright('[super/build] ')
        //     + __('build.build_start', {
        //         type: chalk.cyanBright(appType),
        //         stage: chalk.green('client'),
        //         env: chalk.green('dev'),
        //     })
        // )

        const processes = []
        const pathChunkmap = getChunkmapPath(dist)
        const pathServerJS = path.resolve(dist, 'server/index.js')
        const contentWaiting = '// WAITING FOR SERVER BUNDLING'

        { // 在脚本进程关闭/结束时，同时关闭打开的 PM2 进程
            process.stdin.resume()
            const exitHandler = async (/*options, err*/) => {
                // console.log(processes)
                if (Array.isArray(processes) && processes.length) {
                    if (waitingSpinner) waitingSpinner.stop()
                    await sleep(300)
                    process.stdout.write('\x1B[2J\x1B[0f')
                    const w = spinner('WAITING FOR ENDING')
                    await Promise.all(processes.map(proc =>
                        new Promise((resolve/*, reject*/) => {
                            setTimeout(() => {
                                processes.splice(processes.indexOf(proc), 1)
                                resolve()
                            }, 500)
                            // console.log(proc)
                            pm2.delete(proc)
                        })
                    ))
                    await Promise.all(processes.map(proc =>
                        new Promise((resolve/*, reject*/) => {
                            setTimeout(() => resolve(), 500)
                            // console.log(proc)
                            pm2.delete(proc)
                        })
                    ))
                    // console.log(JSON.stringify(processes))
                    pm2.disconnect()
                    await sleep(300)
                    w.stop()
                    try {
                        // console.log(process.pid)
                        process.exit(1)
                        // process.kill(process.pid)
                    } catch (e) {
                        console.log(e)
                    }
                } else {
                    process.removeListener('exit', exitHandler)
                    process.removeListener('SIGINT', exitHandler)
                    process.removeListener('SIGUSR1', exitHandler)
                    process.removeListener('SIGUSR2', exitHandler)
                    process.removeListener('uncaughtException', exitHandler)
                    // 清空 log
                    process.stdout.write('\x1B[2J\x1B[0f')
                    console.log('Press CTRL+C again to terminate.')
                    process.exit(1)
                }
            }
            // do something when app is closing
            process.on('exit', exitHandler);
            // catches ctrl+c event
            process.on('SIGINT', exitHandler);
            // catches "kill pid" (for example: nodemon restart)
            process.on('SIGUSR1', exitHandler);
            process.on('SIGUSR2', exitHandler);
            // catches uncaught exceptions
            process.on('uncaughtException', exitHandler);
        }

        // 根据 stage 开启 PM2 进程
        const start = (stage) => new Promise(async (resolve, reject) => {
            const pathLogOut = path.resolve(process.cwd(), `logs/dev/${stage}.log`)
            const pathLogErr = path.resolve(process.cwd(), `logs/dev/${stage}-error.log`)
            if (fs.existsSync(pathLogOut)) await fs.remove(pathLogOut)
            if (fs.existsSync(pathLogErr)) await fs.remove(pathLogErr)
            const config = {
                name: `dev-${stage}-${name}`,
                script: path.resolve(__dirname, './build.js'),
                args: `--stage ${stage} --env dev`,
                cwd: process.cwd(),
                output: pathLogOut,
                error: pathLogErr,
                autorestart: false,
            }
            if (stage === 'run') {
                config.script = pathServerJS
                config.watch = true
                delete config.args
            }
            processes.push(config.name)
            pm2.start(
                config,
                (err, proc) => {
                    // console.log(err)
                    if (err) return reject(err)
                    resolve(proc)
                }
            )
        })

        // 连接 PM2
        pm2.connect(true, async (err) => {
            if (err) {
                // console.error(err)
                process.exit(2)
            }

            console.log(
                `  `
                + chalk.yellowBright('[super/build] ')
                + __('build.build_start', {
                    type: chalk.cyanBright(appType),
                    stage: chalk.green('client'),
                    env: chalk.green('dev'),
                })
            )

            // 清空 chunkmap 文件
            await fs.ensureFile(pathChunkmap)
            await fs.writeFile(pathChunkmap, contentWaiting)

            // 清空 server 打包结果文件
            await fs.ensureFile(pathServerJS)
            await fs.writeFile(pathServerJS, contentWaiting)

            // 启动 client webpack-dev-server
            await start('client')

            // 监视 chunkmap 文件，如果修改，进入下一步
            await new Promise(resolve => {
                const waiting = () => setTimeout(async () => {
                    if (!fs.existsSync(pathChunkmap)) return waiting()
                    const content = await fs.readFile(pathChunkmap, 'utf-8')
                    if (!content || content === contentWaiting) return waiting()
                    await sleep(100)
                    resolve()
                }, 500)
                waiting()
            })
            // waitingSpinner.succeed()
            console.log(
                chalk.green('√ ')
                + chalk.yellowBright('[super/build] ')
                + __('build.build_complete', {
                    type: chalk.cyanBright(appType),
                    stage: chalk.green('client'),
                    env: chalk.green('dev'),
                })
            )

            // 启动 server webpack
            // waitingSpinner = spinner(
            //     chalk.yellowBright('[super/build] ')
            //     + __('build.build_start', {
            //         type: chalk.cyanBright(appType),
            //         stage: chalk.green('server'),
            //         env: chalk.green('dev'),
            //     })
            // )
            console.log(
                `  `
                + chalk.yellowBright('[super/build] ')
                + __('build.build_start', {
                    type: chalk.cyanBright(appType),
                    stage: chalk.green('server'),
                    env: chalk.green('dev'),
                })
            )
            await start('server')

            // 监视 server.js 文件，如果修改，进入下一步
            await new Promise(resolve => {
                const waiting = () => setTimeout(async () => {
                    if (!fs.existsSync(pathServerJS)) return waiting()
                    const content = await fs.readFile(pathServerJS, 'utf-8')
                    if (!content || content === contentWaiting) return waiting()
                    await sleep(100)
                    resolve()
                }, 500)
                waiting()
            })
            // waitingSpinner.succeed()

            // 执行
            // waitingSpinner = spinner(
            //     chalk.yellowBright('[super/build] ')
            //     + 'waiting...'
            // )
            await start('run')
            await sleep(500)

            console.log(
                chalk.green('√ ')
                + chalk.yellowBright('[super/build] ')
                + __('build.build_complete', {
                    type: chalk.cyanBright(appType),
                    stage: chalk.green('server'),
                    env: chalk.green('dev'),
                })
            )

            // waitingSpinner.stop()
            // waitingSpinner = undefined
            npmRunScript(`pm2 logs`)
            opn(`http://localhost:${process.env.SERVER_PORT}/`)
        })
    }
}

run()
<commit_msg>polish<commit_after>#!/usr/bin/env node

const fs = require('fs-extra')
const path = require('path')
const program = require('commander')
const pm2 = require('pm2')
const chalk = require('chalk')
const npmRunScript = require('npm-run-script')
const opn = require('opn')

const __ = require('../utils/translate')
const sleep = require('../utils/sleep')
const getPort = require('../utils/get-port')
const spinner = require('../utils/spinner')
const readBuildConfigFile = require('../utils/read-build-config-file')
const getAppType = require('../utils/get-app-type')
const setEnvFromCommand = require('../utils/set-env-from-command')
const getChunkmapPath = require('../utils/get-chunkmap-path')
const initNodeEnv = require('../utils/init-node-env')

program
    .version(require('../package').version, '-v, --version')
    .usage('[options]')
    .option('-c, --client', 'Set STAGE to CLIENT')
    .option('-s, --server', 'Set STAGE to SERVER')
    .option('--stage <stage>', 'Set STAGE')
    .option('--config <config-file-path>', 'Set config file')
    .option('--type <project-type>', 'Set project type')
    .parse(process.argv)

/**
 * 进入开发环境
 * ****************************************************************************
 * 同构 (isomorphic)
 * 以 PM2 进程方式顺序执行以下流程
 *      1. 启动 webpack-dev-server (STAGE: client)
 *      2. 启动 webpack (watch mode) (STAGE: server)
 *      3. 运行 /server/index.js
 * ****************************************************************************
 * 单页面应用 (SPA)
 * 强制设置 STAGE 为 client，并启动 webpack-dev-server
 * ****************************************************************************
 */
const run = async () => {
    // 清空 log
    process.stdout.write('\x1B[2J\x1B[0f')

    const {
        client, server,
        stage: _stage,
        config,
        type,
    } = program

    initNodeEnv()
    setEnvFromCommand({
        config,
        type,
    })

    let stage = _stage ? _stage : (client ? 'client' : (server ? 'server' : false))

    // if (!stage) {
    //     console.log(
    //         chalk.redBright('× ')
    //         + __('dev.missing_stage', {
    //             example: 'super-dev ' + chalk.green('--client'),
    //             indent: '  '
    //         })
    //     )
    //     return
    // }

    // 读取项目信息
    const appType = await getAppType()
    const packageInfo = await fs.readJson(path.resolve(process.cwd(), 'package.json'))
    const { dist, port } = await readBuildConfigFile()
    const {
        name
    } = packageInfo

    // 如果为 SPA，强制设置 STAGE
    if (process.env.WEBPACK_BUILD_TYPE === 'spa') {
        process.env.WEBPACK_BUILD_STAGE = 'client'
        stage = 'client'
    }

    // 如果配置中存在 port，修改环境变量
    if (typeof port !== 'undefined')
        process.env.SERVER_PORT = getPort(port, 'dev')

    // 如果设置了 stage，仅运行该 stage
    if (stage) {
        const cmd = `super-build --stage ${stage} --env dev`
        const child = npmRunScript(cmd, {})
        child.once('error', (error) => {
            console.trace(error)
            process.exit(1)
        })
        child.once('exit', (/*exitCode*/) => {
            // console.trace('exit in', exitCode)
            // process.exit(exitCode)
        })
        return
    } else {
        // 没有设置 STAGE，开始 PM2 进程

        let waitingSpinner = false
        // spinner(
        //     chalk.yellowBright('[super/build] ')
        //     + __('build.build_start', {
        //         type: chalk.cyanBright(appType),
        //         stage: chalk.green('client'),
        //         env: chalk.green('dev'),
        //     })
        // )

        const processes = []
        const pathChunkmap = getChunkmapPath(dist)
        const pathServerJS = path.resolve(dist, 'server/index.js')
        const contentWaiting = '// WAITING FOR SERVER BUNDLING'

        { // 在脚本进程关闭/结束时，同时关闭打开的 PM2 进程
            process.stdin.resume()
            const exitHandler = async (/*options, err*/) => {
                // console.log(processes)
                if (Array.isArray(processes) && processes.length) {
                    if (waitingSpinner) waitingSpinner.stop()
                    await sleep(300)
                    process.stdout.write('\x1B[2J\x1B[0f')
                    const w = spinner('WAITING FOR ENDING')
                    await Promise.all(processes.map(proc =>
                        new Promise((resolve/*, reject*/) => {
                            setTimeout(() => {
                                processes.splice(processes.indexOf(proc), 1)
                                resolve()
                            }, 500)
                            // console.log(proc)
                            pm2.delete(proc)
                        })
                    ))
                    await Promise.all(processes.map(proc =>
                        new Promise((resolve/*, reject*/) => {
                            setTimeout(() => resolve(), 500)
                            // console.log(proc)
                            pm2.delete(proc)
                        })
                    ))
                    // console.log(JSON.stringify(processes))
                    pm2.disconnect()
                    await sleep(300)
                    w.stop()
                    try {
                        // console.log(process.pid)
                        process.exit(1)
                        // process.kill(process.pid)
                    } catch (e) {
                        console.log(e)
                    }
                } else {
                    process.removeListener('exit', exitHandler)
                    process.removeListener('SIGINT', exitHandler)
                    process.removeListener('SIGUSR1', exitHandler)
                    process.removeListener('SIGUSR2', exitHandler)
                    process.removeListener('uncaughtException', exitHandler)
                    // 清空 log
                    process.stdout.write('\x1B[2J\x1B[0f')
                    console.log('Press CTRL+C again to terminate.')
                    process.exit(1)
                }
            }
            // do something when app is closing
            process.on('exit', exitHandler);
            // catches ctrl+c event
            process.on('SIGINT', exitHandler);
            // catches "kill pid" (for example: nodemon restart)
            process.on('SIGUSR1', exitHandler);
            process.on('SIGUSR2', exitHandler);
            // catches uncaught exceptions
            process.on('uncaughtException', exitHandler);
        }

        // 根据 stage 开启 PM2 进程
        const start = (stage) => new Promise(async (resolve, reject) => {
            const pathLogOut = path.resolve(process.cwd(), `logs/dev/${stage}.log`)
            const pathLogErr = path.resolve(process.cwd(), `logs/dev/${stage}-error.log`)
            if (fs.existsSync(pathLogOut)) await fs.remove(pathLogOut)
            if (fs.existsSync(pathLogErr)) await fs.remove(pathLogErr)
            const config = {
                name: `dev-${stage}-${name}`,
                script: path.resolve(__dirname, './build.js'),
                args: `--stage ${stage} --env dev`,
                cwd: process.cwd(),
                output: pathLogOut,
                error: pathLogErr,
                autorestart: false,
            }
            if (stage === 'run') {
                config.script = pathServerJS
                config.watch = true
                delete config.args
            }
            processes.push(config.name)
            pm2.start(
                config,
                (err, proc) => {
                    // console.log(err)
                    if (err) return reject(err)
                    resolve(proc)
                }
            )
        })

        // 连接 PM2
        pm2.connect(true, async (err) => {
            if (err) {
                // console.error(err)
                process.exit(2)
            }

            console.log(
                `  `
                + chalk.yellowBright('[super/build] ')
                + __('build.build_start', {
                    type: chalk.cyanBright(appType),
                    stage: chalk.green('client'),
                    env: chalk.green('dev'),
                })
            )

            // 清空 chunkmap 文件
            await fs.ensureFile(pathChunkmap)
            await fs.writeFile(pathChunkmap, contentWaiting)

            // 清空 server 打包结果文件
            await fs.ensureFile(pathServerJS)
            await fs.writeFile(pathServerJS, contentWaiting)

            // 启动 client webpack-dev-server
            await start('client')

            // 监视 chunkmap 文件，如果修改，进入下一步
            await new Promise(resolve => {
                const waiting = () => setTimeout(async () => {
                    if (!fs.existsSync(pathChunkmap)) return waiting()
                    const content = await fs.readFile(pathChunkmap, 'utf-8')
                    if (!content || content === contentWaiting) return waiting()
                    await sleep(100)
                    resolve()
                }, 500)
                waiting()
            })
            // waitingSpinner.succeed()
            console.log(
                chalk.green('√ ')
                + chalk.yellowBright('[super/build] ')
                + __('build.build_complete', {
                    type: chalk.cyanBright(appType),
                    stage: chalk.green('client'),
                    env: chalk.green('dev'),
                })
            )

            // 启动 server webpack
            // waitingSpinner = spinner(
            //     chalk.yellowBright('[super/build] ')
            //     + __('build.build_start', {
            //         type: chalk.cyanBright(appType),
            //         stage: chalk.green('server'),
            //         env: chalk.green('dev'),
            //     })
            // )
            console.log(
                `  `
                + chalk.yellowBright('[super/build] ')
                + __('build.build_start', {
                    type: chalk.cyanBright(appType),
                    stage: chalk.green('server'),
                    env: chalk.green('dev'),
                })
            )
            await start('server')

            // 监视 server.js 文件，如果修改，进入下一步
            await new Promise(resolve => {
                const waiting = () => setTimeout(async () => {
                    if (!fs.existsSync(pathServerJS)) return waiting()
                    const content = await fs.readFile(pathServerJS, 'utf-8')
                    if (!content || content === contentWaiting) return waiting()
                    await sleep(100)
                    resolve()
                }, 500)
                waiting()
            })
            // waitingSpinner.succeed()

            // 执行
            // waitingSpinner = spinner(
            //     chalk.yellowBright('[super/build] ')
            //     + 'waiting...'
            // )
            await start('run')
            await sleep(1000)

            console.log(
                chalk.green('√ ')
                + chalk.yellowBright('[super/build] ')
                + __('build.build_complete', {
                    type: chalk.cyanBright(appType),
                    stage: chalk.green('server'),
                    env: chalk.green('dev'),
                })
            )

            // waitingSpinner.stop()
            // waitingSpinner = undefined
            npmRunScript(`pm2 logs`)
            opn(`http://localhost:${process.env.SERVER_PORT}/`)
        })
    }
}

run()
<|endoftext|>


<commit_before>var Twit = require('twit')
var Const = require('./constants');
var fs = require('fs');

/* ##########
 * The values you have to edit
 * ##########
 */
var exportType = 'csv';

/*
 * Compares two strings to know if it starts by a given prefix
 * @params      string      str     wanted string to compare
 *              string      prefix  start of the string we want to compare
 * @return      boolean     true if str starts by prefix
 */
function stringStartsWith (str, prefix) {
    return str.slice(0, prefix.length) == prefix;
}

/*
 * Encode a given string into a wanted format, used for parsing into a csv file
 * @params  string  str     String to convert
 * @return  string          Formated string
 */
function strFormat(str) {
    return '"' + str.replace(/\n/g, ' ').replace(/"/g, '""') + '"';
}

// All the files are in this directory
var dirName = './tweets';
// Tweets will be stored in this variable
var tweets;
var files = fs.readdirSync(dirName);
// This variable will only be used to give informations about the number of files remaining
var i = 0;

// For each filename
files.forEach(function(fileName){
    i++;
    // Only on certain files
    if (stringStartsWith(fileName, 'tweets_')){
        // Reading the file
        var text = fs.readFileSync(dirName + '/' + fileName);
        // Parsing the text in a JSON
        var tmpTweets = JSON.parse(text);
        // Concatenating the tweets
        tweets = (typeof tweets == 'undefined') ? tmpTweets : tweets.concat(tmpTweets);
        console.log(fileName + " is read (" + i + "/" + files.length + ")");
    }
});

console.log("I got " + tweets.length + " tweets, wow!");

console.log("Writing the file, it may takes a few minutes if there are many tweets.");

var text;
var outputFilename;

if (exportType == 'csv') {
    outputFilename = dirName + '/grouped_tweets.csv';
    text = "\ufeffCreated at;Name;Username;Text";

    tweets.forEach(function(tweet){
         text += "\n" + strFormat(tweet.created_at)
            + ";" + strFormat(tweet.user.name)
            + ";" + strFormat('@' + tweet.user.screen_name)
            + ";" + strFormat(tweet.text);
    });
}
else {
    outputFilename = dirName + '/grouped_tweets.json';
    text = JSON.stringify(tweets, null, 4);
}

// Writing formated object in a file
fs.writeFile(outputFilename, text, function(err) {
    if(err) console.log(err);
    else console.log("file saved to " + outputFilename);
});
<commit_msg>Fix: remove day name in csv export for enabling sort<commit_after>var Twit = require('twit')
var Const = require('./constants');
var fs = require('fs');

/* ##########
 * The values you have to edit
 * ##########
 */
var exportType = 'csv';

/*
 * Compares two strings to know if it starts by a given prefix
 * @params      string      str     wanted string to compare
 *              string      prefix  start of the string we want to compare
 * @return      boolean     true if str starts by prefix
 */
function stringStartsWith (str, prefix) {
    return str.slice(0, prefix.length) == prefix;
}

/*
 * Encode a given string into a wanted format, used for parsing into a csv file
 * @params  string  str     String to convert
 * @return  string          Formated string
 */
function strFormat(str) {
    return '"' + str.replace(/\n/g, ' ').replace(/"/g, '""') + '"';
}

// All the files are in this directory
var dirName = './tweets';
// Tweets will be stored in this variable
var tweets;
var files = fs.readdirSync(dirName);
// This variable will only be used to give informations about the number of files remaining
var i = 0;

// For each filename
files.forEach(function(fileName){
    i++;
    // Only on certain files
    if (stringStartsWith(fileName, 'tweets_')){
        // Reading the file
        var text = fs.readFileSync(dirName + '/' + fileName);
        // Parsing the text in a JSON
        var tmpTweets = JSON.parse(text);
        // Concatenating the tweets
        tweets = (typeof tweets == 'undefined') ? tmpTweets : tweets.concat(tmpTweets);
        console.log(fileName + " is read (" + i + "/" + files.length + ")");
    }
});

console.log("I got " + tweets.length + " tweets, wow!");

console.log("Writing the file, it may takes a few minutes if there are many tweets.");

var text;
var outputFilename;

if (exportType == 'csv') {
    outputFilename = dirName + '/grouped_tweets.csv';
    text = "\ufeffCreated at;Name;Username;Text";

    tweets.forEach(function(tweet){
         text += "\n" + strFormat(tweet.created_at.substr(4))
            + ";" + strFormat(tweet.user.name)
            + ";" + strFormat('@' + tweet.user.screen_name)
            + ";" + strFormat(tweet.text);
    });
}
else {
    outputFilename = dirName + '/grouped_tweets.json';
    text = JSON.stringify(tweets, null, 4);
}

// Writing formated object in a file
fs.writeFile(outputFilename, text, function(err) {
    if(err) console.log(err);
    else console.log("file saved to " + outputFilename);
});
<|endoftext|>


<commit_before>#!/bin/bash
set -e

work=no
model=''

while (( $# > 0 )); do
    arg="$1"
    shift
    case $arg in
    -work)
	work=yes
	;;
    -*)
	echo "unknown flag: $arg"
	exit 1
	;;
    *)
	model="$arg"
        ;;
    esac
done

pushd "`dirname $0`" >/dev/null
SDJS_DIR="`pwd -P`"
popd >/dev/null

OUT=`mktemp --suffix=.js`

node "$SDJS_DIR/emit_sim.js" "$model" >"$OUT"
#time ~/src/v8/out/native/d8 --use-strict --harmony worker.js
node "$OUT"

if [ $work = 'yes' ]; then
    echo "$OUT" >&2
else
    rm -f "$OUT"
fi
<commit_msg>build: fix mdl.js on OSX, BSD mktemp is a pain<commit_after>#!/bin/bash
set -e

work=no
model=''

while (( $# > 0 )); do
    arg="$1"
    shift
    case $arg in
    -work)
	work=yes
	;;
    -*)
	echo "unknown flag: $arg"
	exit 1
	;;
    *)
	model="$arg"
        ;;
    esac
done

pushd "`dirname $0`" >/dev/null
SDJS_DIR="`pwd -P`"
popd >/dev/null

OUT=`mktemp /tmp/sdjs.XXXXXX.js`

node "$SDJS_DIR/emit_sim.js" "$model" >"$OUT"
#time ~/src/v8/out/native/d8 --use-strict --harmony worker.js
node "$OUT"

if [ $work = 'yes' ]; then
    echo "$OUT" >&2
else
    rm -f "$OUT"
fi
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////
//  This file was authored by A. Leah Zulas             ////
//  It heavily utilizes D3 js                           ////
//  If retreives data using Ajax, from an express server////
//  Any questions about the below code should be sent to:///
//  alzulas@alzulas.com                                 ////
////////////////////////////////////////////////////////////

//Create CSV array and retreive cookie
var outPutCSV = [];
var myid = getCookie("userName");
//Use cookie to request data from the server, so long as cookie exists.
if (myid != ""){
    var dataPassed;
    $.ajax({
        type: "GET",
        url: "/RSSMresult/" + myid,
        async: false,
        success: function(dataPassed){
            outPutCSV = calculateScores(dataPassed); //collect data and put them into the CSV
            console.log(outPutCSV); //Correctly calculated data print to console so we can see it worked
            console.log("Get request complete");//verification that the data was retreieved.
        },
    });
}

    //d3.getElementById("myDiv").style.margin = "50px 10px 20px 30px";
    //This html just explains what the participant just did.
    d3.select("body").append("p")
        .style("margin", "30px 50px 0px 50px")
        .text("The measure you completed was designed to assess how you experience yourself when you are interacting with different significant others in your life or engaged in different roles.  More specifically, this questionnaire measures to what extent you experience satisfaction of 3 psychological needs in these different interactions.");
    d3.select("body").append("p")
        .style("margin", "30px 50px 0px 50px")
        .text("According to self-determination theory (Ryan & Deci, 2000), humans have three essential needs that if satisfied promote psychological well-being. These 3 needs are:");
    d3.select("body").append("li")
        .style("margin", "30px 50px 0px 50px")
        .text("Relatedness-which is the experience of intimacy and genuine connection with others.");
    d3.select("body").append("li")
        .style("margin", "10px 50px 0px 50px")
        .text("Competence-which is the experience of feeling effective and capable of achieving desired outcomes.");
    d3.select("body").append("li")
        .style("margin", "10px 50px 0px 50px")
        .text("Autonomy-which is the experience of self-determination, full willingness, and volition when carrying out an activity.");
    d3.select("body").append("p")
        .style("margin", "30px 50px 0px 50px")
        .text("");

//begins the process of printing scores.
//Common was to write JS, because any variables not wrapped in a function is available in the entire namespace of the website.
printScores();

function printScores(){
    //creat array of possible relationships
    //THIS IS ONE OF THE VARIABLES TO CHANGE IF YOU WANT TO ADD NEW RELATIONSHIPS.
    var relationship = ["Mother", "Father", "Romantic Partner", "Ex-Romantic Partner", "Sibling", "Close Friend", "Overall"];
    i = 0;//counter
    for (relation in relationship){ //Go through each relationship above and...
        standardResults(outPutCSV[i], outPutCSV[i+1], outPutCSV[i+2], relationship[relation]); //calculate info about it.
        //The above hands the next part of this the comp score, auto score, relation score, and the relationship name
        i = i+3;
        //it then progresses the counter to the next relationship in the CSV
    }
}

function getCookie(cname) { //This function retreives the participant ID, stored as a cookie
    var name = cname + "=";
    var ca = document.cookie.split(';'); //Ask for cookie, split by ;
    for(var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) == 0) { //looking for ID in cookie called "cname"
            return c.substring(name.length, c.length); //Return ID
        }
    }
    return ""; //No ID found, return empty string
}

function calculateScores(dataPassed){
    //Takes data from CSV off the server, calculates relavant scores, returns array
    var results = [];
    //Will be in the order of mother comp-auto-related then
    //father comp-auto-related then
    //romantic partner comp-auto-related then
    //ex comp-auto-related then
    //sibling comp-auto-related then
    //close friend
    //Below are necessary variables
    var currentComp = 0;
    var currentAuto = 0;
    var currentRelated = 0;
    var overallComp = 0;
    var overallAuto = 0;
    var overallRelated = 0;
    var compDenominator = 4*6;
    var autoDenominator = 4*6;
    var relatedDenominator = 4*6;
    var dataArray = dataPassed.split(","); //Takes CSV from the server, creates array
    //round counter. Because every 4th time through the data, scores are calculated
    var round = 0;
    //Relevant data beings at position 8 in the array from the server
    for (var i = 8; i < 95; i++){
        currentComp = currentComp + Number(dataArray[i]);//take current score for this relationship, add to previous
        overallComp = overallComp + Number(dataArray[i]);//Do for an overall score as well
        if(Number(dataArray[i])==0){
            //If there is nothing in this relationship, because they don't have one or never think of that person,
            //Then the overall score must have a different number to divide from
            compDenominator--;
        }
        //Go to next item in the array and repeat
        i++;
        currentAuto = currentAuto + Number(dataArray[i]);
        overallAuto = overallAuto + Number(dataArray[i]);
        if(Number(dataArray[i])==0){
            autoDenominator--;
        }
        //Go to next item in the array and repeat
        i++;
        currentRelated = currentRelated + Number(dataArray[i]);
        overallRelated = overallRelated + Number(dataArray[i]);
        if(Number(dataArray[i])==0){
            relatedDenominator--;
        }
        //Move forward round
        round++;
        if (round > 3){
            //If we have all relevant scores for this relationship, then calculate averages
            currentComp = currentComp/4;
            currentAuto = currentAuto/4;
            currentRelated = currentRelated/4;
            //Push these scores onto the results array
            results.push(currentComp);
            results.push(currentAuto);
            results.push(currentRelated);
            //Reset variables for next relationship
            currentAuto = 0;
            currentComp = 0;
            currentRelated = 0;
            round = 0;
            //Move forward past questions like "relationship type", "closeness" and a filler question
            i = i+3;
        }
    }
    //Once all relationship scores are calculated, an overall must be calculated
    overallComp = overallComp/compDenominator;
    overallAuto = overallAuto/autoDenominator;
    overallRelated = overallRelated/relatedDenominator;
    //Push these onto the results array
    results.push(overallComp);
    results.push(overallAuto);
    results.push(overallRelated);

    //return results to the ajax call
    return results;
}

function standardResults(compScore, autoScore, relateScore, relation){
    //Printing scores to the screen.
    if(relation == "Overall"){//Print overall scores last
        d3.select("body").append("H1")
            .style("margin", "30px 50px 0px 50px")
            .text("Your Overall RSSM Scores are: ");
        d3.select("body").append("li")
            .style("margin", "30px 50px 0px 50px")
            .text("Your competence score is " + compScore);
        //These include the actal mean and SD for the population,
        //they go to a function to calculate where the participants score lies
        standardDeviationPrint(compScore, 3.97, .74, "competancy");
        d3.select("body").append("li")
            .style("margin", "30px 50px 0px 50px")
            .text("Your autonomy score is " + autoScore);
        standardDeviationPrint(autoScore, 3.85, .73, "autonomy");
        d3.select("body").append("li")
            .style("margin", "30px 50px 0px 50px")
            .text("Your relatedness score is " + relateScore);
        standardDeviationPrint(compScore, 4.22, .69, "relatedness");
        createBargraph(outPutCSV);
    }
    else if(compScore != 0 && autoScore != 0 && relateScore != 0){//Print each relationship, so long as it exists
        d3.select("body").append("H1")
            .style("margin", "30px 50px 0px 50px")
            .text("RSSM Score for you with your " + relation);
        d3.select("body").append("li")
            .style("margin", "15px 50px 0px 50px")
            .text("Your competence score is " + compScore);
        d3.select("body").append("li")
            .style("margin", "10px 50px 0px 50px")
            .text("Your autonomy score is " + autoScore);
        d3.select("body").append("li")
            .style("margin", "10px 50px 0px 50px")
            .text("Your relatedness score is " + relateScore);
    }
}

function standardDeviationPrint(Score, Mean, SD, type){ //participants score, popMean, popSD, score type
    //Find how many deviations from the mean they are, and print the accompanying text with it.
    if (Score > Mean-SD && Score < Mean+SD){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is average");
    }
    else if (Score > Mean-(SD*2) && Score < Mean-SD){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is on the low side of average");
    }
    else if (Score > Mean-(SD*3) && Score < Mean-(SD*2)){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is low");
    }
    else if (Score > 0 && Score < Mean-(SD*3)){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is very low");
    }
    else if (Score > Mean+(SD) && Score < Mean+(SD*2)){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is on the high side of average");
    }
    else if (Score > Mean+(SD*2) && Score < Mean+(SD*3)){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is high");
    }
    else if (Score > Mean+(SD*3) && Score < 5){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is very high");
    }
    else{
        //Something in the code failed most likely. But also, they could have not answered for any relationship.
        d3.select("body").append("p")
            .style("margin", "15px 50px 0px 50px")
            .text("Test was inconclusive or there is an error in the survey. Please contact the web developer.");
    }

}

function createBargraph(dataset){ //This was a test of D3
    //It creates a little BISBAS graph
    //It's not super useful
    //But I kept the code just in case.
    //If you'd like to see it, uncomment out the call to this function above.
     console.log("graphing18");

//			d3.select("body")//.selectAll("div")
//				.data(dataset)
//				.enter()
//				.append("div")
//				.attr("class", "bar")
//				.style("height", function(d) {
//					var barHeight = d * 5;
//					return barHeight + "px";
//				});

    var w = 1000;
    var h = 500;
    var barPadding = 1;

    //Create SVG element
    var svg = d3.select("body")
                .style("margin", "30px 50px 0px 50px")
                .style("height", function(d) {
					var barHeight = d * 5;
					return barHeight + "px";
				})
                .append("svg")
                .attr("width", w)
                .attr("height", h);

    svg.selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("x", function(d, i) {
            return i * (w / dataset.length);
        })
        .attr("y", function(d) {
            return h - (d * 4);
        })
        .attr("width", w / dataset.length - barPadding)
        .attr("height", function(d) {
            return d * 4;
        })
        .attr("fill", function(d) {
            return "rgb(0, 0, " + Math.round(d * 10) + ")";
        });
}<commit_msg>graph test19<commit_after>////////////////////////////////////////////////////////////
//  This file was authored by A. Leah Zulas             ////
//  It heavily utilizes D3 js                           ////
//  If retreives data using Ajax, from an express server////
//  Any questions about the below code should be sent to:///
//  alzulas@alzulas.com                                 ////
////////////////////////////////////////////////////////////

//Create CSV array and retreive cookie
var outPutCSV = [];
var myid = getCookie("userName");
//Use cookie to request data from the server, so long as cookie exists.
if (myid != ""){
    var dataPassed;
    $.ajax({
        type: "GET",
        url: "/RSSMresult/" + myid,
        async: false,
        success: function(dataPassed){
            outPutCSV = calculateScores(dataPassed); //collect data and put them into the CSV
            console.log(outPutCSV); //Correctly calculated data print to console so we can see it worked
            console.log("Get request complete");//verification that the data was retreieved.
        },
    });
}

    //d3.getElementById("myDiv").style.margin = "50px 10px 20px 30px";
    //This html just explains what the participant just did.
    d3.select("body").append("p")
        .style("margin", "30px 50px 0px 50px")
        .text("The measure you completed was designed to assess how you experience yourself when you are interacting with different significant others in your life or engaged in different roles.  More specifically, this questionnaire measures to what extent you experience satisfaction of 3 psychological needs in these different interactions.");
    d3.select("body").append("p")
        .style("margin", "30px 50px 0px 50px")
        .text("According to self-determination theory (Ryan & Deci, 2000), humans have three essential needs that if satisfied promote psychological well-being. These 3 needs are:");
    d3.select("body").append("li")
        .style("margin", "30px 50px 0px 50px")
        .text("Relatedness-which is the experience of intimacy and genuine connection with others.");
    d3.select("body").append("li")
        .style("margin", "10px 50px 0px 50px")
        .text("Competence-which is the experience of feeling effective and capable of achieving desired outcomes.");
    d3.select("body").append("li")
        .style("margin", "10px 50px 0px 50px")
        .text("Autonomy-which is the experience of self-determination, full willingness, and volition when carrying out an activity.");
    d3.select("body").append("p")
        .style("margin", "30px 50px 0px 50px")
        .text("");

//begins the process of printing scores.
//Common was to write JS, because any variables not wrapped in a function is available in the entire namespace of the website.
printScores();

function printScores(){
    //creat array of possible relationships
    //THIS IS ONE OF THE VARIABLES TO CHANGE IF YOU WANT TO ADD NEW RELATIONSHIPS.
    var relationship = ["Mother", "Father", "Romantic Partner", "Ex-Romantic Partner", "Sibling", "Close Friend", "Overall"];
    i = 0;//counter
    for (relation in relationship){ //Go through each relationship above and...
        standardResults(outPutCSV[i], outPutCSV[i+1], outPutCSV[i+2], relationship[relation]); //calculate info about it.
        //The above hands the next part of this the comp score, auto score, relation score, and the relationship name
        i = i+3;
        //it then progresses the counter to the next relationship in the CSV
    }
}

function getCookie(cname) { //This function retreives the participant ID, stored as a cookie
    var name = cname + "=";
    var ca = document.cookie.split(';'); //Ask for cookie, split by ;
    for(var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') {
            c = c.substring(1);
        }
        if (c.indexOf(name) == 0) { //looking for ID in cookie called "cname"
            return c.substring(name.length, c.length); //Return ID
        }
    }
    return ""; //No ID found, return empty string
}

function calculateScores(dataPassed){
    //Takes data from CSV off the server, calculates relavant scores, returns array
    var results = [];
    //Will be in the order of mother comp-auto-related then
    //father comp-auto-related then
    //romantic partner comp-auto-related then
    //ex comp-auto-related then
    //sibling comp-auto-related then
    //close friend
    //Below are necessary variables
    var currentComp = 0;
    var currentAuto = 0;
    var currentRelated = 0;
    var overallComp = 0;
    var overallAuto = 0;
    var overallRelated = 0;
    var compDenominator = 4*6;
    var autoDenominator = 4*6;
    var relatedDenominator = 4*6;
    var dataArray = dataPassed.split(","); //Takes CSV from the server, creates array
    //round counter. Because every 4th time through the data, scores are calculated
    var round = 0;
    //Relevant data beings at position 8 in the array from the server
    for (var i = 8; i < 95; i++){
        currentComp = currentComp + Number(dataArray[i]);//take current score for this relationship, add to previous
        overallComp = overallComp + Number(dataArray[i]);//Do for an overall score as well
        if(Number(dataArray[i])==0){
            //If there is nothing in this relationship, because they don't have one or never think of that person,
            //Then the overall score must have a different number to divide from
            compDenominator--;
        }
        //Go to next item in the array and repeat
        i++;
        currentAuto = currentAuto + Number(dataArray[i]);
        overallAuto = overallAuto + Number(dataArray[i]);
        if(Number(dataArray[i])==0){
            autoDenominator--;
        }
        //Go to next item in the array and repeat
        i++;
        currentRelated = currentRelated + Number(dataArray[i]);
        overallRelated = overallRelated + Number(dataArray[i]);
        if(Number(dataArray[i])==0){
            relatedDenominator--;
        }
        //Move forward round
        round++;
        if (round > 3){
            //If we have all relevant scores for this relationship, then calculate averages
            currentComp = currentComp/4;
            currentAuto = currentAuto/4;
            currentRelated = currentRelated/4;
            //Push these scores onto the results array
            results.push(currentComp);
            results.push(currentAuto);
            results.push(currentRelated);
            //Reset variables for next relationship
            currentAuto = 0;
            currentComp = 0;
            currentRelated = 0;
            round = 0;
            //Move forward past questions like "relationship type", "closeness" and a filler question
            i = i+3;
        }
    }
    //Once all relationship scores are calculated, an overall must be calculated
    overallComp = overallComp/compDenominator;
    overallAuto = overallAuto/autoDenominator;
    overallRelated = overallRelated/relatedDenominator;
    //Push these onto the results array
    results.push(overallComp);
    results.push(overallAuto);
    results.push(overallRelated);

    //return results to the ajax call
    return results;
}

function standardResults(compScore, autoScore, relateScore, relation){
    //Printing scores to the screen.
    if(relation == "Overall"){//Print overall scores last
        d3.select("body").append("H1")
            .style("margin", "30px 50px 0px 50px")
            .text("Your Overall RSSM Scores are: ");
        d3.select("body").append("li")
            .style("margin", "30px 50px 0px 50px")
            .text("Your competence score is " + compScore);
        //These include the actal mean and SD for the population,
        //they go to a function to calculate where the participants score lies
        standardDeviationPrint(compScore, 3.97, .74, "competancy");
        d3.select("body").append("li")
            .style("margin", "30px 50px 0px 50px")
            .text("Your autonomy score is " + autoScore);
        standardDeviationPrint(autoScore, 3.85, .73, "autonomy");
        d3.select("body").append("li")
            .style("margin", "30px 50px 0px 50px")
            .text("Your relatedness score is " + relateScore);
        standardDeviationPrint(compScore, 4.22, .69, "relatedness");
        createBargraph(outPutCSV);
    }
    else if(compScore != 0 && autoScore != 0 && relateScore != 0){//Print each relationship, so long as it exists
        d3.select("body").append("H1")
            .style("margin", "30px 50px 0px 50px")
            .text("RSSM Score for you with your " + relation);
        d3.select("body").append("li")
            .style("margin", "15px 50px 0px 50px")
            .text("Your competence score is " + compScore);
        d3.select("body").append("li")
            .style("margin", "10px 50px 0px 50px")
            .text("Your autonomy score is " + autoScore);
        d3.select("body").append("li")
            .style("margin", "10px 50px 0px 50px")
            .text("Your relatedness score is " + relateScore);
    }
}

function standardDeviationPrint(Score, Mean, SD, type){ //participants score, popMean, popSD, score type
    //Find how many deviations from the mean they are, and print the accompanying text with it.
    if (Score > Mean-SD && Score < Mean+SD){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is average");
    }
    else if (Score > Mean-(SD*2) && Score < Mean-SD){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is on the low side of average");
    }
    else if (Score > Mean-(SD*3) && Score < Mean-(SD*2)){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is low");
    }
    else if (Score > 0 && Score < Mean-(SD*3)){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is very low");
    }
    else if (Score > Mean+(SD) && Score < Mean+(SD*2)){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is on the high side of average");
    }
    else if (Score > Mean+(SD*2) && Score < Mean+(SD*3)){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is high");
    }
    else if (Score > Mean+(SD*3) && Score < 5){
        d3.select("body").append("ul")
            .style("margin", "15px 50px 0px 50px")
            .text("Your " + type + " score is very high");
    }
    else{
        //Something in the code failed most likely. But also, they could have not answered for any relationship.
        d3.select("body").append("p")
            .style("margin", "15px 50px 0px 50px")
            .text("Test was inconclusive or there is an error in the survey. Please contact the web developer.");
    }

}

function createBargraph(dataset){ //This was a test of D3
    //It creates a little BISBAS graph
    //It's not super useful
    //But I kept the code just in case.
    //If you'd like to see it, uncomment out the call to this function above.
     console.log("graphing19");

//			d3.select("body")//.selectAll("div")
//				.data(dataset)
//				.enter()
//				.append("div")
//				.attr("class", "bar")
//				.style("height", function(d) {
//					var barHeight = d * 5;
//					return barHeight + "px";
//				});

    var w = 1000;
    var h = 500;
    var barPadding = 1;

    //Create SVG element
    var svg = d3.select("body")
                .style("margin", "30px 50px 0px 50px")
                .append("svg")
                .attr("width", w)
                .attr("height", h);

    svg.selectAll("rect")
        .data(dataset)
        .style("height", function(d) {
					var barHeight = d * 5;
					return barHeight + "px";
				})
        .enter()
        .append("rect")
        .attr("x", function(d, i) {
            return i * (w / dataset.length);
        })
        .attr("y", function(d) {
            return h - (d * 4);
        })
        .attr("width", w / dataset.length - barPadding)
        .attr("height", function(d) {
            return d * 4;
        })
        .attr("fill", function(d) {
            return "rgb(0, 0, " + Math.round(d * 10) + ")";
        });
}<|endoftext|>


<commit_before>"use strict";

module.exports = {
    options: {
        rulePaths: [".eslintrules"],
        fix: true
    },
    target: configuration.files.linting.js
};
<commit_msg>Ignore warnings (such as ignored files) (#296)<commit_after>"use strict";

module.exports = {
    options: {
        rulePaths: [".eslintrules"],
        fix: true,
        quiet: true // do not show warnings
    },
    target: configuration.files.linting.js
};
<|endoftext|>


<commit_before>"use strict";

/*jshint camelcase: false */
/*eslint-disable camelcase*/

module.exports = {
    options: {
        beautify: {
            keep_quoted_props: true,
            ascii_only: true
        }
    },
    buildTests: {
        files: {
            "build/tests.js": configuration.files.test
        }
    },
    buildRelease: {
        files: {
            "build/gpf.js": ["build/gpf-release.js"]
        }
    }
};
<commit_msg>New uglify options (#231)<commit_after>"use strict";

/*jshint camelcase: false */
/*eslint-disable camelcase*/

module.exports = {
    options: {
        beautify: {
            keep_quoted_props: true,
            beautify: false
        },
        ie8: true,
        output: {
            ascii_only: true
        }
    },
    buildTests: {
        files: {
            "build/tests.js": configuration.files.test
        }
    },
    buildRelease: {
        files: {
            "build/gpf.js": ["build/gpf-release.js"]
        }
    }
};
<|endoftext|>


<commit_before>"use strict";

var assert = require('assert');

var ClosedInterval = function(from,to) {

  this.contains = function(a) {
      if (a instanceof ClosedInterval) {
        var min = a.minimum();
        var max = a.maximum();

        return this.contains(min) && this.contains(max);
      } else {
        return a >= from && a <= to;
      }
  };

  this.maximum = function() {
    return to;
  };

  this.minimum = function() {
    return from;
  };

  return this;
};

var createClosedInterval = function(from,to) {
  return new ClosedInterval(from, to);
};

var createOpenInterval = function(from,to) {
  return new ClosedInterval(from+1, to-1);
};

describe('range', function() {
  describe('creation', function() {
    it('exists', function() {
      assert(new ClosedInterval);
    });
  });

  describe('closed intervals', function() {

    var defaultRangeForTests = createClosedInterval(1,4);

    it('is created', function() {
      assert(defaultRangeForTests);
    });

    it('minimum', function() {
      assert.equal(1, defaultRangeForTests.minimum());
    });

    it('maximum', function() {
      assert.equal(4, defaultRangeForTests.maximum());
    });
  });

  describe('open intervals', function() {
    var defaultRangeForTests = createOpenInterval(1,4);

    it('is created', function() {
      assert(defaultRangeForTests);
    });

    it('minimum', function() {
      assert.equal(2, defaultRangeForTests.minimum());
    });

    it('maximum', function() {
      assert.equal(3, defaultRangeForTests.maximum());
    });
  });

  describe('closed range contains', function() {

    var range = createClosedInterval(1,100);

    it('correctly contains', function() {
      assert(range.contains(1));
      assert(range.contains(50));
      assert(range.contains(100));
    });

    it('correctly doesn\'t contain', function() {
      assert.equal(false, range.contains(0));
      assert.equal(false, range.contains(101));
    });

    it('can contain smaller ranges', function() {
      assert(range.contains(createClosedInterval(2,99)));
    });

    it('doesnt contain larger ranges', function() {
      assert(!range.contains(createClosedInterval(-1,101)));
      assert(!range.contains(createClosedInterval(2,333)));
    });
  });

  describe('open range contains', function() {

    var range = createOpenInterval(1,100);

    it('correctly contains', function() {
      assert(range.contains(2));
      assert(range.contains(50));
      assert(range.contains(99));
    });

    it('correctly doesn\'t contain', function() {
      assert.equal(false, range.contains(1));
      assert.equal(false, range.contains(100));
    });
  });
});
<commit_msg>note down silliness<commit_after>"use strict";

var assert = require('assert');

var ClosedInterval = function(from,to) {

  this.contains = function(a) {
      if (a instanceof ClosedInterval) {
        var min = a.minimum();
        var max = a.maximum();

        return this.contains(min) && this.contains(max);
      } else {
        return a >= from && a <= to;
      }
  };

  this.maximum = function() {
    return to;
  };

  this.minimum = function() {
    return from;
  };

  return this;
};

var createClosedInterval = function(from,to) {
  return new ClosedInterval(from, to);
};

var createOpenInterval = function(from,to) {
  return new ClosedInterval(from+1, to-1);
};

describe('range', function() {
  describe('creation', function() {
    it('exists', function() {
      assert(new ClosedInterval);
    });
  });

  describe('closed intervals', function() {

    var defaultRangeForTests = createClosedInterval(1,4);

    it('is created', function() {
      assert(defaultRangeForTests);
    });

    it('minimum', function() {
      assert.equal(1, defaultRangeForTests.minimum());
    });

    it('maximum', function() {
      assert.equal(4, defaultRangeForTests.maximum());
    });
  });

  describe('open intervals', function() {
    var defaultRangeForTests = createOpenInterval(1,4);

    it('is created', function() {
      assert(defaultRangeForTests);
    });

    it('minimum', function() {
      assert.equal(2, defaultRangeForTests.minimum());
    });

    it('maximum', function() {
      assert.equal(3, defaultRangeForTests.maximum());
    });
  });

  describe('closed range contains', function() {

    var range = createClosedInterval(1,100);

    it('correctly contains', function() {
      assert(range.contains(1));
      assert(range.contains(50));
      assert(range.contains(100));
    });

    it('correctly doesn\'t contain', function() {
      assert.equal(false, range.contains(0));
      assert.equal(false, range.contains(101));
    });

    it('can contain smaller ranges', function() {
      assert(range.contains(createClosedInterval(2,99)));
    });

    it('doesnt contain larger ranges', function() {
      assert(!range.contains(createClosedInterval(-1,101)));
      assert(!range.contains(createClosedInterval(2,333)));
    });
  });

  describe('open range contains', function() {

    var range = createOpenInterval(1,100);

    it('correctly contains', function() {
      assert(range.contains(2));
      assert(range.contains(50));
      assert(range.contains(99));
    });

    it('correctly doesn\'t contain', function() {
      assert.equal(false, range.contains(1));
      assert.equal(false, range.contains(100));
    });
  });
});

// TODO
// I learnt that I didn't know what I was doing.  I was returning
// completley anonymous objects with properties
// Instead, I should be assigning those properties to the "this"
// object and therefore making things make sense.
<|endoftext|>