<commit_before>Router.configure({
    layoutTemplate: 'layout',
    loadingTemplate: 'loading',
    notFoundTemplate: 'notFound',
    waitOn: function() {
        return Meteor.subscribe('openIncidents');
    }
});

Router.onBeforeAction('dataNotFound', {
    //only: 'journalItem',
});

/*
INCIDENT ROUTES
*/
Router.route('/incident', {
    name: 'incident',
    waitOn: function() {
        return Meteor.subscribe('openIncidents');
    },
});
Router.route('/incident/all', {
    name: 'incidentAll',
    waitOn: function() {
        return Meteor.subscribe('allIncidents');
    },
});

Router.route('/incident/new', {
    name: 'incidentAdd',
    waitOn: function() {
        return Meteor.subscribe('allIncidents');
    },
});

Router.route('/incident/:_id/edit', {
    name: 'incidentEdit',
    data: function() {
        return Incidents.findOne(this.params._id);
    },
});

/*
JOURNAL ROUTES
*/
Router.route('/incident/:incident/journal', {
    name: 'journal',
    waitOn: function() {
        return Meteor.subscribe('journal', this.params.incident);
    },
});

Router.route('/incident/:incident/journal/:_id', {
    name: 'journalItem',
    data: function() {
        return Journal.findOne(this.params._id);
    },
    waitOn: function() {
        return Meteor.subscribe('journal', this.params.incident);
    },
});
<commit_msg>add a redirection for root to incident<commit_after>Router.configure({
    layoutTemplate: 'layout',
    loadingTemplate: 'loading',
    notFoundTemplate: 'notFound',
    waitOn: function() {
        return Meteor.subscribe('openIncidents');
    }
});

Router.onBeforeAction('dataNotFound', {
    //only: 'journalItem',
});

Router.route('/', {
    onBeforeAction: function() {
        this.redirect('/incident');
    },
});

/*
INCIDENT ROUTES
*/
Router.route('/incident', {
    name: 'incident',
    waitOn: function() {
        return Meteor.subscribe('openIncidents');
    },
});
Router.route('/incident/all', {
    name: 'incidentAll',
    waitOn: function() {
        return Meteor.subscribe('allIncidents');
    },
});

Router.route('/incident/new', {
    name: 'incidentAdd',
    waitOn: function() {
        return Meteor.subscribe('allIncidents');
    },
});

Router.route('/incident/:_id/edit', {
    name: 'incidentEdit',
    data: function() {
        return Incidents.findOne(this.params._id);
    },
});

/*
JOURNAL ROUTES
*/
Router.route('/incident/:incident/journal', {
    name: 'journal',
    waitOn: function() {
        return Meteor.subscribe('journal', this.params.incident);
    },
});

Router.route('/incident/:incident/journal/:_id', {
    name: 'journalItem',
    data: function() {
        return Journal.findOne(this.params._id);
    },
    waitOn: function() {
        return Meteor.subscribe('journal', this.params.incident);
    },
});
<|endoftext|>


<commit_before>var RESULTS_LOCATION = "flypaper_results.json";

$(document).ready(function() {
    prepare_ui();
    get_json_via_ajax(RESULTS_LOCATION, update_ui);
});

function prepare_ui() {
    $("table#results").tablesorter();
}

function get_json_via_ajax(filename, callback) {
    $.ajax({
        type: "GET",
        url: filename,
        dataType: "json",
        success: function(data) {
            callback(data);
        }
    });
}

function update_ui(results) {
    var rows = "";
    for (var i in results.files) {
        var file = results.files[i];
        var score = new Number(file.score);
        rows += "
";
        rows += "" + score.toPrecision(4) + "	";
        rows += "" + shorten_filename(file.filename) + "	";
        rows += "" + file.bugs.join(', ') + "	";
        rows += "
";
    }

    var table = $('table#results');
    var tbody = table.find('tbody');
    tbody.empty();
    tbody.append(rows);

    //tell tablesorter that we changed the data underneath it
    table.trigger("update");
}

function shorten_filename(filename) {
    var reasonable_length = 85;

    //if the full filename isn't that long, just use it
    if (filename.length < reasonable_length) {
        return filename;
    }

    //split the filename up on slashes
    var parts = filename.split('/');

    //try and shorten the name and still include some path info
    var shortname = parts[0];
    if (parts.length > 0) {
        shortname += "/.../" + parts[parts.length - 1];
    }

    //if the name is still too long, just use the basename
    if (shortname.length > reasonable_length && parts.length > 0) {
        shortname = parts[parts.length - 1];
    }

    return shortname;
}
<commit_msg>disable sorting of the bugs column<commit_after>var RESULTS_LOCATION = "flypaper_results.json";

$(document).ready(function() {
    prepare_ui();
    get_json_via_ajax(RESULTS_LOCATION, update_ui);
});

function prepare_ui() {
    //initialize sorting
    $("table#results").tablesorter({
        //disable sorting of the bugs column
        headers: { 2: { sorter: false } }
    });
}

function get_json_via_ajax(filename, callback) {
    $.ajax({
        type: "GET",
        url: filename,
        dataType: "json",
        success: function(data) {
            callback(data);
        }
    });
}

function update_ui(results) {
    var rows = "";
    for (var i in results.files) {
        var file = results.files[i];
        var score = new Number(file.score);
        rows += "
";
        rows += "" + score.toPrecision(4) + "	";
        rows += "" + shorten_filename(file.filename) + "	";
        rows += "" + file.bugs.join(', ') + "	";
        rows += "
";
    }

    var table = $('table#results');
    var tbody = table.find('tbody');
    tbody.empty();
    tbody.append(rows);

    //tell tablesorter that we changed the data underneath it
    table.trigger("update");
}

function shorten_filename(filename) {
    var reasonable_length = 85;

    //if the full filename isn't that long, just use it
    if (filename.length < reasonable_length) {
        return filename;
    }

    //split the filename up on slashes
    var parts = filename.split('/');

    //try and shorten the name and still include some path info
    var shortname = parts[0];
    if (parts.length > 0) {
        shortname += "/.../" + parts[parts.length - 1];
    }

    //if the name is still too long, just use the basename
    if (shortname.length > reasonable_length && parts.length > 0) {
        shortname = parts[parts.length - 1];
    }

    return shortname;
}
<|endoftext|>


<commit_before>import React from 'react';
import Section from 'shared/components/section/section';
import QuoteBanner from 'shared/components/quoteBanner/quoteBanner';
import ProgramFeatures from './programFeatures/programFeatures';
import VolunteerChars from './volunteerChars/volunteerChars';
import Steps from './steps/steps';

import styles from './ourPrograms.css';

const OurPrograms = () => (

    <QuoteBanner
      author="The Smart Guy"
      quote="Here is a quote about the awesome stuff."
    />

        <ProgramFeatures />

        <VolunteerChars />

        <Steps />

);

export default OurPrograms;
<commit_msg>fixed eslint errors<commit_after>import React from 'react';
import Section from 'shared/components/section/section';
import QuoteBanner from 'shared/components/quoteBanner/quoteBanner';
import ProgramFeatures from './programFeatures/programFeatures';
import VolunteerChars from './volunteerChars/volunteerChars';
import Steps from './steps/steps';

import styles from './ourPrograms.css';

const OurPrograms = () => (

    <QuoteBanner
      author="The Smart Guy"
      quote="Here is a quote about the awesome stuff."
    />

        <ProgramFeatures />

        <VolunteerChars />

        <Steps />

);

export default OurPrograms;
<|endoftext|>


<commit_before>// Load modules

var Fs = require('fs');
var Domain = require('domain');
var Async = require('async');
var Reporters = require('./reporters');
var Coverage = require('./coverage');
var Leaks = require('./leaks');
var Output = require('./output');

// Declare internals

var internals = {};

Error.stackTraceLimit = Infinity;       // Set Error stack size

exports.defaults = {
    coverage: false,
    color: false,
    dry: false,
    environment: 'test',
    grep: null,
    id: null,
    globals: null,
    leaks: false,
    timeout: 2000,
    output: null,
    parallel: false,
    reporter: 'console',
    silence: false,
    threshold: 0,
    verbose: false
};

internals.executing = false;

exports.execute = function (experiments, options) {

    options = options || exports.defaults;

    if (internals.executing) {
        return;
    }

    internals.executing = true;

    // Setup environment

    process.env.NODE_ENV = options.environment;
    internals.timeout = options.timeout;
    internals.parallel = options.parallel;

    // Generate reporter

    var reporter = new Reporters[options.reporter]({ threshold: options.threshold, level: options.silence ? 0 : (options.verbose ? 2 : 1) });
    var dest = options.output ? Fs.createWriteStream(options.output) : process.stdout;
    Output.decorate(reporter, { dest: dest, forceColor: options.colors });

    var report = {
        tests: [],
        failures: 0
    };

    // Execute experiments

    var idsFilter = options.id ? [].concat(options.id) : []
    var grep = options.grep ? new RegExp(options.grep) : null;
    var count = internals.count(experiments, idsFilter, grep);          // Sets test.id
    reporter.start({ count: count });

    var startTime = Date.now();
    var state = {
        report: report,
        reporter: reporter,
        ids: idsFilter,
        grep: grep
    };

    internals.executeExperiments(experiments, state, options.dry, function (err) {

        // Finalize

        var notebook = {
            ms: Date.now() - startTime,
            tests: report.tests,
            leaks: !options.leaks ? Leaks.detect(options.globals ? options.globals.trim().split(',') : []) : undefined,
            coverage: options.coverage ? Coverage.analyze(report.tests) : undefined
        };

        var output = reporter.end(notebook) || '';
        dest.write(output, function () {

            var code = (options.coverage && options.threshold && (notebook.coverage.percent < options.threshold || isNaN(notebook.coverage.percent))) ||    // Missing coverage
                        report.failures ||                                                                                // Tests failed
                        (notebook.leaks && notebook.leaks.length) ? 1 : 0;                                                                                // Global leaked

            if (dest === process.stdout) {
                process.exit(code);
            }

            dest.end(function () {

                process.exit(code);
            });
        });
    });
};

internals.executeExperiments = function (experiments, state, skip, callback) {

    Async.forEachSeries(experiments || [], function (experiment, nextExperiment) {

        var skipExperiment = skip || experiment.options.skip;

        Async.series([
            function (next) {

                // Before

                if (skipExperiment) {
                    return next();
                }

                internals.executeDeps(experiment.befores, next);
            },
            function (next) {

                // Tests

                internals.executeTests(experiment, state, skipExperiment, next);
            },
            function (next) {

                // Sub-experiments

                internals.executeExperiments(experiment.experiments, state, skipExperiment, next);
            },
            function (next) {

                // After

                if (skipExperiment) {
                    return next();
                }

                internals.executeDeps(experiment.afters, next);
            }
        ],
        function (err, results) {

            if (err) {
                state.report.failures++;        // Force process.exit(1)
            }

            nextExperiment();
        });
    },
    function (err) {

        callback(err);
    });
};

internals.executeDeps = function (deps, callback) {

    Async.forEachSeries(deps || [], function (dep, next) {

        internals.protect(dep, false, next);
    }, function (err) {

        if (err) {
            internals.output(err);
        }

        callback();
    });
};

internals.executeTests = function (experiment, state, skip, callback) {

    if (!experiment.tests) {
        return callback();
    }

    // Collect beforeEach and afterEach from parents

    var befores = skip ? [] : internals.collectDeps(experiment, 'beforeEaches');
    var afters = skip ? [] : internals.collectDeps(experiment, 'afterEaches');

    // Separate serial and parallel execution tests

    var serial = [];
    var parallel = [];

    for (var i = 0, il = experiment.tests.length; i < il; ++i) {
        var test = experiment.tests[i];
        if (test.options.parallel ||
            (test.options.parallel === undefined && internals.parallel)) {

            parallel.push(test);
        }
        else {
            serial.push(test);
        }
    }

    // Execute tests

    var execute = function (test, nextTest) {

        if ((state.ids.length && state.ids.indexOf(test.id) === -1) ||
            (state.grep && !state.grep.test(test.title))) {

            return nextTest();
        }

        Async.series([
            function (next) {

                // Before each

                return internals.executeDeps(befores, next);
            },
            function (next) {

                // Unit

                if (!test.fn ||
                    skip ||
                    test.options.skip) {

                    test[test.fn ? 'skipped' : 'todo'] = true;
                    test.duration = 0;
                    state.report.tests.push(test);
                    state.reporter.test(test);
                    return setImmediate(next);
                }

                var start = Date.now();
                internals.protect(test, true, function (err) {

                    if (err) {
                        state.report.failures++;
                        test.err = err;
                        test.timeout = err.timeout;
                    }

                    test.duration = Date.now() - start;

                    state.report.tests.push(test);
                    state.reporter.test(test);
                    return next();
                });
            },
            function (next) {

                // After each

                return internals.executeDeps(afters, next);
            }
        ], function (err, results) {

            if (err) {
                internals.output(err);
            }

            return nextTest();
        });
    };

    Async.forEachSeries(serial, execute,
    function (err) {

        Async.forEach(parallel, execute, function () {

            return callback(err);
        });
    });
};

internals.collectDeps = function (experiment, key) {

    var set = [];

    if (experiment.parent) {
        set = set.concat(internals.collectDeps(experiment.parent, key));
    }

    set = set.concat(experiment[key] || [])
    return set;
};

internals.protect = function (item, isTimed, callback) {

    var timeoutId = 0;

    var baseDomain = Domain.createDomain();
    var scopeDomain = Domain.createDomain();

    var causes = null;
    var finish = function (err, cause) {

        var first = false;

        if (!causes) {
            causes = {};
            baseDomain.exit();
            scopeDomain.removeAllListeners();
            clearTimeout(timeoutId);
            first = true;
        }

        if (cause === 'done' && causes.done) {
            internals.output(new Error('Callback called twice in test: ' + item.title));
            return;
        }

        causes[cause] = true;

        if (first) {
            return callback(err);
        }
    };

    if (isTimed) {
        var ms = item.options.timeout || internals.timeout;
        timeoutId = setTimeout(function () {

            var error = new Error('Timed out (' + ms + 'ms)');
            error.timeout = true;
            finish(error, 'timeout');
        }, ms);
    }

    scopeDomain.once('error', function (err) {

        finish(err, 'error');
    });

    baseDomain.enter();
    scopeDomain.enter();

    setImmediate(function () {

        item.fn.call(null, function (err) {

            finish(err, err ? 'error' : 'done');
        });
    });
};

internals.output = function (err) {

    process.stderr.write(err.message + '\n' + err.stack + '\n');
};

internals.count = function (experiments, ids, grep, _seq) {

    var seq = _seq || 0;
    var counter = 0;

    if (experiments) {
        for (var e = 0, el = experiments.length; e < el; ++e) {
            var experiment = experiments[e];

            if (experiment.tests) {
                for (var i = 0, il = experiment.tests.length; i < il; ++i) {
                    var test = experiment.tests[i];
                    test.id = ++seq;
                    counter += (ids.length && ids.indexOf(test.id) === -1) || (grep && !grep.test(test.title)) ? 0 : 1;
                }
            }

            counter += internals.count(experiment.experiments, ids, grep, seq);
        }
    }

    return counter;
};

<commit_msg>Fix test id numbers<commit_after>// Load modules

var Fs = require('fs');
var Domain = require('domain');
var Async = require('async');
var Reporters = require('./reporters');
var Coverage = require('./coverage');
var Leaks = require('./leaks');
var Output = require('./output');

// Declare internals

var internals = {};

Error.stackTraceLimit = Infinity;       // Set Error stack size

exports.defaults = {
    coverage: false,
    color: false,
    dry: false,
    environment: 'test',
    grep: null,
    id: null,
    globals: null,
    leaks: false,
    timeout: 2000,
    output: null,
    parallel: false,
    reporter: 'console',
    silence: false,
    threshold: 0,
    verbose: false
};

internals.executing = false;

exports.execute = function (experiments, options) {

    options = options || exports.defaults;

    if (internals.executing) {
        return;
    }

    internals.executing = true;

    // Setup environment

    if (options.environment) {
        process.env.NODE_ENV = options.environment;
    }

    // Generate reporter

    var reporter = new Reporters[options.reporter]({ threshold: options.threshold, level: options.silence ? 0 : (options.verbose ? 2 : 1) });
    var dest = options.output ? Fs.createWriteStream(options.output) : process.stdout;
    Output.decorate(reporter, { dest: dest, forceColor: options.colors });

    var report = {
        tests: [],
        failures: 0
    };

    // Execute experiments

    var idsFilter = options.id ? [].concat(options.id) : []
    var grep = options.grep ? new RegExp(options.grep) : null;
    var count = internals.count(experiments, { filters: { ids: idsFilter, grep: grep } });        // Sets test.id
    reporter.start({ count: count });

    var startTime = Date.now();
    var state = {
        report: report,
        reporter: reporter,
        filters: {
            ids: idsFilter,
            grep: grep
        },
        options: options
    };

    internals.executeExperiments(experiments, state, options.dry, function (err) {

        // Finalize

        var notebook = {
            ms: Date.now() - startTime,
            tests: report.tests,
            leaks: !options.leaks ? Leaks.detect(options.globals ? options.globals.trim().split(',') : []) : undefined,
            coverage: options.coverage ? Coverage.analyze(report.tests) : undefined
        };

        var output = reporter.end(notebook) || '';
        dest.write(output, function () {

            var code = (options.coverage && options.threshold && (notebook.coverage.percent < options.threshold || isNaN(notebook.coverage.percent))) ||    // Missing coverage
                        report.failures ||                                                                                // Tests failed
                        (notebook.leaks && notebook.leaks.length) ? 1 : 0;                                                                                // Global leaked

            if (dest === process.stdout) {
                process.exit(code);
            }

            dest.end(function () {

                process.exit(code);
            });
        });
    });
};

internals.executeExperiments = function (experiments, state, skip, callback) {

    Async.forEachSeries(experiments || [], function (experiment, nextExperiment) {

        var skipExperiment = skip || experiment.options.skip;

        Async.series([
            function (next) {

                // Before

                if (skipExperiment) {
                    return next();
                }

                internals.executeDeps(experiment.befores, next);
            },
            function (next) {

                // Tests

                internals.executeTests(experiment, state, skipExperiment, next);
            },
            function (next) {

                // Sub-experiments

                internals.executeExperiments(experiment.experiments, state, skipExperiment, next);
            },
            function (next) {

                // After

                if (skipExperiment) {
                    return next();
                }

                internals.executeDeps(experiment.afters, next);
            }
        ],
        function (err, results) {

            if (err) {
                state.report.failures++;        // Force process.exit(1)
            }

            nextExperiment();
        });
    },
    function (err) {

        callback(err);
    });
};

internals.executeDeps = function (deps, callback) {

    Async.forEachSeries(deps || [], function (dep, next) {

        internals.protect(dep, null, next);
    }, function (err) {

        if (err) {
            internals.output(err);
        }

        callback();
    });
};

internals.executeTests = function (experiment, state, skip, callback) {

    if (!experiment.tests) {
        return callback();
    }

    // Collect beforeEach and afterEach from parents

    var befores = skip ? [] : internals.collectDeps(experiment, 'beforeEaches');
    var afters = skip ? [] : internals.collectDeps(experiment, 'afterEaches');

    // Separate serial and parallel execution tests

    var serial = [];
    var parallel = [];

    for (var i = 0, il = experiment.tests.length; i < il; ++i) {
        var test = experiment.tests[i];
        if (test.options.parallel ||
            (test.options.parallel === undefined && state.options.parallel)) {

            parallel.push(test);
        }
        else {
            serial.push(test);
        }
    }

    // Execute tests

    var execute = function (test, nextTest) {

        if ((state.filters.ids.length && state.filters.ids.indexOf(test.id) === -1) ||
            (state.filters.grep && !state.filters.grep.test(test.title))) {

            return nextTest();
        }

        Async.series([
            function (next) {

                // Before each

                return internals.executeDeps(befores, next);
            },
            function (next) {

                // Unit

                if (!test.fn ||
                    skip ||
                    test.options.skip) {

                    test[test.fn ? 'skipped' : 'todo'] = true;
                    test.duration = 0;
                    state.report.tests.push(test);
                    state.reporter.test(test);
                    return setImmediate(next);
                }

                var start = Date.now();
                internals.protect(test, state.options, function (err) {

                    if (err) {
                        state.report.failures++;
                        test.err = err;
                        test.timeout = err.timeout;
                    }

                    test.duration = Date.now() - start;

                    state.report.tests.push(test);
                    state.reporter.test(test);
                    return next();
                });
            },
            function (next) {

                // After each

                return internals.executeDeps(afters, next);
            }
        ], function (err, results) {

            if (err) {
                internals.output(err);
            }

            return nextTest();
        });
    };

    Async.forEachSeries(serial, execute,
    function (err) {

        Async.forEach(parallel, execute, function () {

            return callback(err);
        });
    });
};

internals.collectDeps = function (experiment, key) {

    var set = [];

    if (experiment.parent) {
        set = set.concat(internals.collectDeps(experiment.parent, key));
    }

    set = set.concat(experiment[key] || [])
    return set;
};

internals.protect = function (item, options, callback) {

    var timeoutId = 0;

    var baseDomain = Domain.createDomain();
    var scopeDomain = Domain.createDomain();

    var causes = null;
    var finish = function (err, cause) {

        var first = false;

        if (!causes) {
            causes = {};
            baseDomain.exit();
            scopeDomain.removeAllListeners();
            clearTimeout(timeoutId);
            first = true;
        }

        if (cause === 'done' && causes.done) {
            internals.output(new Error('Callback called twice in test: ' + item.title));
            return;
        }

        causes[cause] = true;

        if (first) {
            return callback(err);
        }
    };

    if (options &&
        (item.options.timeout || options.timeout)) {

        var ms = item.options.timeout || options.timeout;
        timeoutId = setTimeout(function () {

            var error = new Error('Timed out (' + ms + 'ms)');
            error.timeout = true;
            finish(error, 'timeout');
        }, ms);
    }

    scopeDomain.once('error', function (err) {

        finish(err, 'error');
    });

    baseDomain.enter();
    scopeDomain.enter();

    setImmediate(function () {

        item.fn.call(null, function (err) {

            finish(err, err ? 'error' : 'done');
        });
    });
};

internals.output = function (err) {

    process.stderr.write(err.message + '\n' + err.stack + '\n');
};

internals.count = function (experiments, state) {

    state.count = state.count || 0;
    state.seq = state.seq || 0;

    if (experiments) {
        for (var e = 0, el = experiments.length; e < el; ++e) {
            var experiment = experiments[e];

            if (experiment.tests) {
                for (var i = 0, il = experiment.tests.length; i < il; ++i) {
                    var test = experiment.tests[i];
                    test.id = ++state.seq;
                    state.counter += (state.filters.ids.length && state.filters.ids.indexOf(test.id) === -1) || (state.filters.grep && !state.filters.grep.test(test.title)) ? 0 : 1;
                }
            }

           internals.count(experiment.experiments, state);
        }
    }

    return state.count;
};

<|endoftext|>


<commit_before>/**
 * @module echarts/chart/helper/Symbol
 */
define(function (require) {

    var zrUtil = require('zrender/core/util');
    var symbolUtil = require('../../util/symbol');
    var graphic = require('../../util/graphic');
    var numberUtil = require('../../util/number');

    function normalizeSymbolSize(symbolSize) {
        if (!zrUtil.isArray(symbolSize)) {
            symbolSize = [+symbolSize, +symbolSize];
        }
        return symbolSize;
    }

    /**
     * @constructor
     * @alias {module:echarts/chart/helper/Symbol}
     * @param {module:echarts/data/List} data
     * @param {number} idx
     * @extends {module:zrender/graphic/Group}
     */
    function Symbol(data, idx) {
        graphic.Group.call(this);

        this.updateData(data, idx);
    }

    var symbolProto = Symbol.prototype;

    function driftSymbol(dx, dy) {
        this.parent.drift(dx, dy);
    }

    symbolProto._createSymbol = function (symbolType, data, idx) {
        // Remove paths created before
        this.removeAll();

        var seriesModel = data.hostModel;
        var color = data.getItemVisual(idx, 'color');

        var symbolPath = symbolUtil.createSymbol(
            symbolType, -0.5, -0.5, 1, 1, color
        );

        symbolPath.attr({
            style: {
                strokeNoScale: true
            },
            z2: 100,
            scale: [0, 0]
        });
        // Rewrite drift method
        symbolPath.drift = driftSymbol;

        var size = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));

        graphic.initProps(symbolPath, {
            scale: size
        }, seriesModel);

        this._symbolType = symbolType;

        this.add(symbolPath);
    };

    /**
     * Stop animation
     * @param {boolean} toLastFrame
     */
    symbolProto.stopSymbolAnimation = function (toLastFrame) {
        this.childAt(0).stopAnimation(toLastFrame);
    };

    /**
     * Get scale(aka, current symbol size).
     * Including the change caused by animation
     * @param {Array.<number>} toLastFrame
     */
    symbolProto.getScale = function () {
        return this.childAt(0).scale;
    };

    /**
     * Highlight symbol
     */
    symbolProto.highlight = function () {
        this.childAt(0).trigger('emphasis');
    };

    /**
     * Downplay symbol
     */
    symbolProto.downplay = function () {
        this.childAt(0).trigger('normal');
    };

    /**
     * @param {number} zlevel
     * @param {number} z
     */
    symbolProto.setZ = function (zlevel, z) {
        var symbolPath = this.childAt(0);
        symbolPath.zlevel = zlevel;
        symbolPath.z = z;
    };

    symbolProto.setDraggable = function (draggable) {
        var symbolPath = this.childAt(0);
        symbolPath.draggable = draggable;
        symbolPath.cursor = draggable ? 'move' : 'pointer';
    };
    /**
     * Update symbol properties
     * @param  {module:echarts/data/List} data
     * @param  {number} idx
     */
    symbolProto.updateData = function (data, idx) {
        var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
        var seriesModel = data.hostModel;
        var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));
        if (symbolType !== this._symbolType) {
            this._createSymbol(symbolType, data, idx);
        }
        else {
            var symbolPath = this.childAt(0);
            graphic.updateProps(symbolPath, {
                scale: symbolSize
            }, seriesModel);
        }
        this._updateCommon(data, idx, symbolSize);

        this._seriesModel = seriesModel;
    };

    // Update common properties
    var normalStyleAccessPath = ['itemStyle', 'normal'];
    var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
    var normalLabelAccessPath = ['label', 'normal'];
    var emphasisLabelAccessPath = ['label', 'emphasis'];

    symbolProto._updateCommon = function (data, idx, symbolSize) {
        var symbolPath = this.childAt(0);
        var seriesModel = data.hostModel;
        var itemModel = data.getItemModel(idx);
        var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath);
        var color = data.getItemVisual(idx, 'color');

        var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();

        symbolPath.rotation = itemModel.getShallow('symbolRotate') * Math.PI / 180 || 0;

        var symbolOffset = itemModel.getShallow('symbolOffset');
        if (symbolOffset) {
            var pos = symbolPath.position;
            pos[0] = numberUtil.parsePercent(symbolOffset[0], symbolSize[0]);
            pos[1] = numberUtil.parsePercent(symbolOffset[1], symbolSize[1]);
        }

        symbolPath.setColor(color);

        zrUtil.extend(
            symbolPath.style,
            // Color must be excluded.
            // Because symbol provide setColor individually to set fill and stroke
            normalItemStyleModel.getItemStyle(['color'])
        );

        var labelModel = itemModel.getModel(normalLabelAccessPath);
        var hoverLabelModel = itemModel.getModel(emphasisLabelAccessPath);
        var lastDim = data.dimensions[data.dimensions.length - 1];
        var labelText = seriesModel.getFormattedLabel(idx, 'normal')
                    || data.get(lastDim, idx);
        var elStyle = symbolPath.style;

        if (labelModel.get('show')) {
            graphic.setText(elStyle, labelModel, color);
            elStyle.text = labelText;
        }
        else {
            elStyle.text = '';
        }
        if (hoverLabelModel.getShallow('show')) {
            graphic.setText(hoverStyle, hoverLabelModel, color);
            hoverStyle.text = labelText;
        }
        else {
            hoverStyle.text = '';
        }

        graphic.setHoverStyle(symbolPath, hoverStyle);

        var size = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));

        symbolPath.off('mouseover')
            .off('mouseout')
            .off('emphasis')
            .off('normal');
        if (itemModel.getShallow('hoverAnimation')) {
            var onEmphasis = function() {
                var ratio = size[1] / size[0];
                this.animateTo({
                    scale: [
                        Math.max(size[0] * 1.1, size[0] + 3),
                        Math.max(size[1] * 1.1, size[1] + 3 * ratio)
                    ]
                }, 400, 'elasticOut');
            };
            var onNormal = function() {
                this.animateTo({
                    scale: size
                }, 400, 'elasticOut');
            };
            symbolPath.on('mouseover', onEmphasis)
                .on('mouseout', onNormal)
                .on('emphasis', onEmphasis)
                .on('normal', onNormal);
        }
    };

    symbolProto.fadeOut = function (cb) {
        var symbolPath = this.childAt(0);
        // Not show text when animating
        symbolPath.style.text = '';
        graphic.updateProps(symbolPath, {
            scale: [0, 0]
        }, this._seriesModel, cb);
    };

    zrUtil.inherits(Symbol, graphic.Group);

    return Symbol;
});<commit_msg>Scatter emphasis style bug fix<commit_after>/**
 * @module echarts/chart/helper/Symbol
 */
define(function (require) {

    var zrUtil = require('zrender/core/util');
    var symbolUtil = require('../../util/symbol');
    var graphic = require('../../util/graphic');
    var numberUtil = require('../../util/number');

    function normalizeSymbolSize(symbolSize) {
        if (!zrUtil.isArray(symbolSize)) {
            symbolSize = [+symbolSize, +symbolSize];
        }
        return symbolSize;
    }

    /**
     * @constructor
     * @alias {module:echarts/chart/helper/Symbol}
     * @param {module:echarts/data/List} data
     * @param {number} idx
     * @extends {module:zrender/graphic/Group}
     */
    function Symbol(data, idx) {
        graphic.Group.call(this);

        this.updateData(data, idx);
    }

    var symbolProto = Symbol.prototype;

    function driftSymbol(dx, dy) {
        this.parent.drift(dx, dy);
    }

    symbolProto._createSymbol = function (symbolType, data, idx) {
        // Remove paths created before
        this.removeAll();

        var seriesModel = data.hostModel;
        var color = data.getItemVisual(idx, 'color');

        var symbolPath = symbolUtil.createSymbol(
            symbolType, -0.5, -0.5, 1, 1, color
        );

        symbolPath.attr({
            style: {
                strokeNoScale: true
            },
            z2: 100,
            scale: [0, 0]
        });
        // Rewrite drift method
        symbolPath.drift = driftSymbol;

        var size = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));

        graphic.initProps(symbolPath, {
            scale: size
        }, seriesModel);

        this._symbolType = symbolType;

        this.add(symbolPath);
    };

    /**
     * Stop animation
     * @param {boolean} toLastFrame
     */
    symbolProto.stopSymbolAnimation = function (toLastFrame) {
        this.childAt(0).stopAnimation(toLastFrame);
    };

    /**
     * Get scale(aka, current symbol size).
     * Including the change caused by animation
     * @param {Array.<number>} toLastFrame
     */
    symbolProto.getScale = function () {
        return this.childAt(0).scale;
    };

    /**
     * Highlight symbol
     */
    symbolProto.highlight = function () {
        this.childAt(0).trigger('emphasis');
    };

    /**
     * Downplay symbol
     */
    symbolProto.downplay = function () {
        this.childAt(0).trigger('normal');
    };

    /**
     * @param {number} zlevel
     * @param {number} z
     */
    symbolProto.setZ = function (zlevel, z) {
        var symbolPath = this.childAt(0);
        symbolPath.zlevel = zlevel;
        symbolPath.z = z;
    };

    symbolProto.setDraggable = function (draggable) {
        var symbolPath = this.childAt(0);
        symbolPath.draggable = draggable;
        symbolPath.cursor = draggable ? 'move' : 'pointer';
    };
    /**
     * Update symbol properties
     * @param  {module:echarts/data/List} data
     * @param  {number} idx
     */
    symbolProto.updateData = function (data, idx) {
        var symbolType = data.getItemVisual(idx, 'symbol') || 'circle';
        var seriesModel = data.hostModel;
        var symbolSize = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));
        if (symbolType !== this._symbolType) {
            this._createSymbol(symbolType, data, idx);
        }
        else {
            var symbolPath = this.childAt(0);
            graphic.updateProps(symbolPath, {
                scale: symbolSize
            }, seriesModel);
        }
        this._updateCommon(data, idx, symbolSize);

        this._seriesModel = seriesModel;
    };

    // Update common properties
    var normalStyleAccessPath = ['itemStyle', 'normal'];
    var emphasisStyleAccessPath = ['itemStyle', 'emphasis'];
    var normalLabelAccessPath = ['label', 'normal'];
    var emphasisLabelAccessPath = ['label', 'emphasis'];

    symbolProto._updateCommon = function (data, idx, symbolSize) {
        var symbolPath = this.childAt(0);
        var seriesModel = data.hostModel;
        var itemModel = data.getItemModel(idx);
        var normalItemStyleModel = itemModel.getModel(normalStyleAccessPath);
        var color = data.getItemVisual(idx, 'color');

        var hoverStyle = itemModel.getModel(emphasisStyleAccessPath).getItemStyle();

        symbolPath.rotation = itemModel.getShallow('symbolRotate') * Math.PI / 180 || 0;

        var symbolOffset = itemModel.getShallow('symbolOffset');
        if (symbolOffset) {
            var pos = symbolPath.position;
            pos[0] = numberUtil.parsePercent(symbolOffset[0], symbolSize[0]);
            pos[1] = numberUtil.parsePercent(symbolOffset[1], symbolSize[1]);
        }

        symbolPath.setColor(color);

        zrUtil.extend(
            symbolPath.style,
            // Color must be excluded.
            // Because symbol provide setColor individually to set fill and stroke
            normalItemStyleModel.getItemStyle(['color'])
        );

        var labelModel = itemModel.getModel(normalLabelAccessPath);
        var hoverLabelModel = itemModel.getModel(emphasisLabelAccessPath);
        var lastDim = data.dimensions[data.dimensions.length - 1];
        var labelText = seriesModel.getFormattedLabel(idx, 'normal')
                    || data.get(lastDim, idx);
        var elStyle = symbolPath.style;

        if (labelModel.get('show')) {
            graphic.setText(elStyle, labelModel, color);
            elStyle.text = labelText;
        }
        else {
            elStyle.text = '';
        }
        if (hoverLabelModel.getShallow('show')) {
            graphic.setText(hoverStyle, hoverLabelModel, color);
            hoverStyle.text = labelText;
        }
        else {
            hoverStyle.text = '';
        }

        var size = normalizeSymbolSize(data.getItemVisual(idx, 'symbolSize'));

        symbolPath.off('mouseover')
            .off('mouseout')
            .off('emphasis')
            .off('normal');

        graphic.setHoverStyle(symbolPath, hoverStyle);

        if (itemModel.getShallow('hoverAnimation')) {
            var onEmphasis = function() {
                var ratio = size[1] / size[0];
                this.animateTo({
                    scale: [
                        Math.max(size[0] * 1.1, size[0] + 3),
                        Math.max(size[1] * 1.1, size[1] + 3 * ratio)
                    ]
                }, 400, 'elasticOut');
            };
            var onNormal = function() {
                this.animateTo({
                    scale: size
                }, 400, 'elasticOut');
            };
            symbolPath.on('mouseover', onEmphasis)
                .on('mouseout', onNormal)
                .on('emphasis', onEmphasis)
                .on('normal', onNormal);
        }
    };

    symbolProto.fadeOut = function (cb) {
        var symbolPath = this.childAt(0);
        // Not show text when animating
        symbolPath.style.text = '';
        graphic.updateProps(symbolPath, {
            scale: [0, 0]
        }, this._seriesModel, cb);
    };

    zrUtil.inherits(Symbol, graphic.Group);

    return Symbol;
});<|endoftext|>


<commit_before>var protobuf = require('protocol-buffers');

var Schema = function(storage, onReady) {
	if (!(this instanceof Schema)) return new Schema(storage, onReady)
	this._storage = storage
	this.protobuf = null
	this.columns = []
	this.index = {}
	this.reserved = ['id', 'change', 'version', 'deleted']
	this.update(onReady)
}

Schema.prototype.update = function(cb) {
	var self = this
	this._storage.getMeta('schema', {valueEncoding:'json'}, function(err, schema) {
		if (err && err.notFound) err = null // grrrrr
		if (err) return cb(err)
		self.columns = schema || []
		self.compile()
		cb()
	});
}

Schema.prototype.compile = function() {
	var self = this

	this.protobuf = protobuf(this.columns)
	this.names = []

	this.columns.forEach(function(col) {
		self.names.push(col)
	})
}

Schema.prototype.save = function(cb) {
	this._storage.setMeta('schema', this.columns, {valueEncoding:'json'}, cb)
}

Schema.prototype.normalize = function(cols) {
	for (var i = 0; i < cols.length; i++) {
		if (typeof cols[i] === 'string') cols[i] = {name:cols[i], type:'json'}
		if (!cols[i]) cols[i].type = 'json'
	}
	return cols
}

Schema.prototype.encode = function(doc) {
	return this.protobuf.encode(doc)
}

Schema.prototype.decode = function(buf) {
	return this.protobuf.decode(buf)
}

Schema.prototype.validate = function(doc) {
	return this.protobuf.validate(doc)
}

var mismatch = function() {
	var err = new Error('Column mismatch')
	err.type = 'columnMismatch'
	return err
}

Schema.prototype.mergeFromObject = function(obj, cb) {
	var keys = Object.keys(obj)
	var updated = 0

	for (var i = 0; i < keys.length; i++) {
		var key = keys[i]
		var val = obj[key]

		if (val === null || val === undefined) continue
		if (this.reserved.indexOf(key) > -1) continue

		var idx = this.names.indexOf(key)
		if (idx === -1) {
			this.names.push(key)
			this.columns.push({name:key, type:'json'})
			updated++
		} else {
			// TODO: if type !== json type check
		}
	}

	if (!updated) return cb()

	this.compile()
	this.save(cb)
}

Schema.prototype.merge = function(cols, opts, cb) {
	if (typeof opts === 'function') {
		cb = opts
		opts = null
	}

	var updated = 0

	if (opts && opts.strict) {
		for (var i = 0; i < cols.length; i++) {
			var col = cols[i]
			if (i >= this.columns.length) {
				if (!col.type) col.type = 'json'
				this.names.push(col.name)
				this.columns.push(col)
				updated++
			} else {
				if (col.type !== this.columns[i].type) return cb(mismatch())
				if (col.name !== this.columns[i].name) return cb(mismatch())
			}
		}
	} else {
		for (var i = 0; i < cols.length; i++) {
			var col = cols[i]
			var idx = this.names.indexOf(col.name)
			if (idx === -1) {
				if (!col.type) col.type = 'json'
				this.names.push(col.name)
				this.columns.push(col)
				updated++
			} else {
				if (col.type !== this.columns[i].type) return cb(mismatch())
			}
		}
	}

	if (!updated) return cb()

	this.compile()
	this.save(cb)
}

Schema.prototype.toJSON = function() {
	return this.columns
}

module.exports = Schema<commit_msg>fix names array<commit_after>var protobuf = require('protocol-buffers');

var Schema = function(storage, onReady) {
	if (!(this instanceof Schema)) return new Schema(storage, onReady)
	this._storage = storage
	this.protobuf = null
	this.columns = []
	this.index = {}
	this.reserved = ['id', 'change', 'version', 'deleted']
	this.update(onReady)
}

Schema.prototype.update = function(cb) {
	var self = this
	this._storage.getMeta('schema', {valueEncoding:'json'}, function(err, schema) {
		if (err && err.notFound) err = null // grrrrr
		if (err) return cb(err)
		self.columns = schema || []
		self.compile()
		cb()
	});
}

Schema.prototype.compile = function() {
	var self = this

	this.protobuf = protobuf(this.columns)
	this.names = []

	this.columns.forEach(function(col) {
		self.names.push(col.name)
	})
}

Schema.prototype.save = function(cb) {
	this._storage.setMeta('schema', this.columns, {valueEncoding:'json'}, cb)
}

Schema.prototype.normalize = function(cols) {
	for (var i = 0; i < cols.length; i++) {
		if (typeof cols[i] === 'string') cols[i] = {name:cols[i], type:'json'}
		if (!cols[i]) cols[i].type = 'json'
	}
	return cols
}

Schema.prototype.encode = function(doc) {
	return this.protobuf.encode(doc)
}

Schema.prototype.decode = function(buf) {
	return this.protobuf.decode(buf)
}

Schema.prototype.validate = function(doc) {
	return this.protobuf.validate(doc)
}

var mismatch = function() {
	var err = new Error('Column mismatch')
	err.type = 'columnMismatch'
	return err
}

Schema.prototype.mergeFromObject = function(obj, cb) {
	var keys = Object.keys(obj)
	var updated = 0

	for (var i = 0; i < keys.length; i++) {
		var key = keys[i]
		var val = obj[key]

		if (val === null || val === undefined) continue
		if (this.reserved.indexOf(key) > -1) continue

		var idx = this.names.indexOf(key)
		if (idx === -1) {
			this.names.push(key)
			this.columns.push({name:key, type:'json'})
			updated++
		} else {
			// TODO: if type !== json type check
		}
	}

	if (!updated) return cb()

	this.compile()
	this.save(cb)
}

Schema.prototype.merge = function(cols, opts, cb) {
	if (typeof opts === 'function') {
		cb = opts
		opts = null
	}

	var updated = 0

	if (opts && opts.strict) {
		for (var i = 0; i < cols.length; i++) {
			var col = cols[i]
			if (i >= this.columns.length) {
				if (!col.type) col.type = 'json'
				this.names.push(col.name)
				this.columns.push(col)
				updated++
			} else {
				if (col.type !== this.columns[i].type) return cb(mismatch())
				if (col.name !== this.columns[i].name) return cb(mismatch())
			}
		}
	} else {
		for (var i = 0; i < cols.length; i++) {
			var col = cols[i]
			var idx = this.names.indexOf(col.name)
			if (idx === -1) {
				if (!col.type) col.type = 'json'
				this.names.push(col.name)
				this.columns.push(col)
				updated++
			} else {
				if (col.type !== this.columns[i].type) return cb(mismatch())
			}
		}
	}

	if (!updated) return cb()

	this.compile()
	this.save(cb)
}

Schema.prototype.toJSON = function() {
	return this.columns
}

module.exports = Schema<|endoftext|>


<commit_before>/*
 * node-sletatru
 *
 *
 * Copyright (c) 2014 Anton Parkhomenko
 * Licensed under the MIT license.
 */

'use strict';

var soap = require('soap');
var restify = require('restify');

var credentials = require('../credentials.json');
var url = 'http://module.sletat.ru/XmlGate.svc?singleWSDL';

function getSyncClient(callback, error) {
    soap.createClient(url, function(err, client) {
        if (!err) {
            client.addSoapHeader('<AuthInfo xmlns="urn:SletatRu:DataTypes:AuthData:v1">' +
                                    '<Login>' + credentials.Login + '</Login>' +
                                    '<Password>' + credentials.Password + '</Password>' +
                                 '</AuthInfo>');
            callback(client);
        } else {
            error();
        }
    });
}

function getResults(requestId, callback) {
    getSyncClient(function(client) {
        client.GetRequestResult({requestId: requestId}, function(err, result) {
            var tours = result['GetRequestResultResult']['Rows']['XmlTourRecord'].slice(0, 5);  // HOW TO GET IT?!
            callback(tours);
        });
    });
}

function checkResult(requestId, callback, error) {
    setTimeout(function() {
        getSyncClient(function(client) {
            client.GetRequestState({requestId: requestId}, function(err, result) {
                if (!err) {
                    var states = result['GetRequestStateResult']['OperatorLoadState'];
                    var toursCount = 0;
                    states.forEach(function(tourState) { toursCount = toursCount + Number(tourState['RowsCount']); });
                    if  (toursCount > 0) { callback(requestId); }
                } else { error(); }
            });
        });
    }, 2000);
}

function createRequest (params, callback) {
    getSyncClient(function(client) {
        client.CreateRequest(params, function(err, result) {
            var requestId = result['CreateRequestResult'];
            callback(requestId);
        });
    });
}

var server = restify.createServer({
      name: 'SletatRuREST',
      version: '0.0.1'
});

server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());

server.get('/country/:countryId', function (req, res, next) {
    req.params['cityFromId'] = 1281;
    req.params['cacheMode'] = 3;

    createRequest(req.params, function(requestId) {
        checkResult(requestId, function(requestId) {
            getResults(requestId, function(tours) {
                res.send({requestId: tours});
            });
        });
    });
    return next();
});

server.listen(8088, function () {
    console.log('%s listening at %s', server.name, server.url);
});
<commit_msg>Accept POST with JSON<commit_after>/*
 * node-sletatru
 *
 *
 * Copyright (c) 2014 Anton Parkhomenko
 * Licensed under the MIT license.
 */

'use strict';

var soap = require('soap');
var restify = require('restify');

var credentials = require('../credentials.json');
var url = 'http://module.sletat.ru/XmlGate.svc?singleWSDL';

function processSearchParams(req) {
    // I don't know WTF, but ordering of params is important :/
    var params = {};
    params['countryId'] = Number(req.params['countryId']);
    params['cityFromId'] = Number(req.params['cityFromId']);
    params['cacheMode'] = 3;
    return params;
}

function getSyncClient(callback, error) {
    soap.createClient(url, function(err, client) {
        if (!err) {
            client.addSoapHeader('<AuthInfo xmlns="urn:SletatRu:DataTypes:AuthData:v1">' +
                                    '<Login>' + credentials.Login + '</Login>' +
                                    '<Password>' + credentials.Password + '</Password>' +
                                 '</AuthInfo>');
            callback(client);
        } else {
            console.log("Client couldn't be created")
            error();
        }
    });
}

function getResults(requestId, callback) {
    getSyncClient(function(client) {
        client.GetRequestResult({requestId: requestId}, function(err, result) {
            var tours = result['GetRequestResultResult']['Rows']['XmlTourRecord'].slice(0, 5);  // HOW TO GET IT?!
            callback(tours);
        });
    });
}

function checkResult(requestId, callback, error) {
    setTimeout(function() {
        getSyncClient(function(client) {
            client.GetRequestState({requestId: requestId}, function(err, result) {
                if (!err) {
                    var states = result['GetRequestStateResult']['OperatorLoadState'];
                    var toursCount = 0;
                    states.forEach(function(tourState) { toursCount = toursCount + Number(tourState['RowsCount']); });
                    if  (toursCount > 0) { callback(requestId); }
                } else { error(err); }
            });
        });
    }, 2000);
}

function createRequest (params, callback) {
    getSyncClient(function(client) {
        client.CreateRequest(params, function(err, result) {
            var requestId = result['CreateRequestResult'];
            callback(requestId);
        });
    });
}

var server = restify.createServer({
      name: 'SletatRuREST',
      version: '0.0.1'
});

server.use(restify.acceptParser(server.acceptable));
server.use(restify.queryParser());
server.use(restify.bodyParser());

server.post('/search', function (req, res, next) {
    var params = processSearchParams(req);

    createRequest(params, function(requestId) {
        checkResult(requestId, function(requestId) {
            getResults(requestId, function(tours) {
                res.send({requestId: tours});
            });
        }, function (err) {console.log("Can't check tour :( \n" + err)});
    });
    return next();
});

server.listen(8088, function () {
    console.log('%s listening at %s', server.name, server.url);
});
<|endoftext|>


<commit_before>var Board = require("../lib/board.js"),
    events = require("events"),
    util = require("util");

// Sensor instance private data
var priv = new WeakMap(),
    aliases = {
      change: [
        // Generic sensor value change
        "change",
        // Slider sensors (alias)
        "slide",
        // Soft Potentiometer (alias)
        "touch",
        // Force Sensor (alias)
        "force",
        // Flex Sensor (alias)
        "bend"
      ]
    };

/**
 * Sensor
 * @constructor
 *
 * @description Generic analog or digital sensor constructor
 *
 * @param {Object} opts Options: pin, freq, range
 */
function Sensor( opts ) {

  if ( !(this instanceof Sensor) ) {
    return new Sensor( opts );
  }

  var value, last, min, max, vranges, samples;

  value = null;
  last = null;
  min = 1023;
  max = 0;
  samples = [];

  // Initialize a Device instance on a Board
  Board.Device.call(
    this, opts = Board.options( opts )
  );

  // Set the pin to ANALOG (INPUT) mode
  this.mode = this.firmata.MODES.ANALOG;
  this.firmata.pinMode( this.pin, this.mode );

  // Servo instance properties
  this.freq = opts.freq || 25;
  this.range = opts.range || [ 0, 1023 ];
  this.sensitivity = opts.sensitivity === undefined ? 1 : opts.sensitivity;

  // Analog Read event loop
  this.firmata.analogRead( this.pin, function( data ) {

    // In the first 5 seconds, we will receive min/max
    // calibration values which will be used to
    // map and scale all sensor readings from this pin
    // if ( data > max ) {
    //   this.range[1] = max = data;
    // }

    // if ( data < min ) {
    //   this.range[0] = min = data;
    // }

    // Update the closed over `value`
    value = data;

    samples.push( data );

  }.bind(this));

  // Throttle
  setInterval(function() {
    var err, median, low, high;

    err = null;

    // To reduce noise in sensor readings, sort collected samples
    // from high to low and select the value in the center.
    median = (function( input ) {
      var half, len, sorted;
      // faster than default comparitor (even for small n)
      sorted = input.sort(function( a, b ) {
        return a - b;
      });
      len = sorted.length;
      half = Math.floor( len / 2 );

      // If the length is odd, return the midpoint m
      // If the length is even, return average of m & m + 1
      return len % 2 ? sorted[half] : (sorted[half - 1] + sorted[half]) / 2;
    }( samples ));

    // Emit the continuous "read" event
    this.emit( "read", err, median );

    // If the median value for this interval is outside last +/- a threshold
    // fire a change event

    low = last - this.sensitivity;
    high = last + this.sensitivity;

    // Includes all aliases
    // Prevent events from firing if the latest value is the same as
    // the last value to trigger a change event
    if ( median !== last ) {
      if ( median < low || median > high ) {
        aliases.change.forEach(function( change ) {
          this.emit( change, err, median );
        }, this );
      }
    }

    // Store this media value for comparison
    // in next interval
    last = median;

    // Reset samples
    samples.length = 0;
  }.bind(this), this.freq );

  // Create a "state" entry for privately
  // storing the state of the sensor
  priv.set( this, {
    booleanBarrier: 512,
    scale: null,
    value: 0
  });

  Object.defineProperties( this, {
    normalized: {
      get: function() {
        return value === null ? null :
          Board.map( value, this.range[0], this.range[1], 0, 255 );
      }
    },
    constrained: {
      get: function() {
        return value === null ? null :
          Board.constrain( this.normalized, 0, 255 );
      }
    },
    boolean: {
      get: function() {
        return this.value > priv.get( this ).booleanBarrier ?
          true : false;
      }
    },
    scaled: {
      get: function() {
        var mapped, constrain, scale;

        scale = priv.get( this ).scale;

        if ( scale && value !== null ) {
          mapped = Board.map( value, this.range[0], this.range[1], scale[0], scale[1] );
          constrain = Board.constrain( mapped, scale[0], scale[1] );

          return constrain;
        }
        return this.constrained;
      }
    },
    value: {
      get: function() {
        var state;

        state = priv.get( this );

        if ( state.scale ) {
          return this.scaled;
        }

        return value;
      }
    }
  });
}

util.inherits( Sensor, events.EventEmitter );

/**
 * pinMode Change the sensor's pinMode on the fly
 * @param  {Number} mode Sensor pin mode value
 * @return {Object} instance
 */
Sensor.prototype.pinMode = function( mode ) {
  this.mode = mode;
  this.firmata.pinMode( this.pin, mode );
  return this;
};

/**
 * scale/scaleTo Set a value scaling range
 *
 * @param  {Number} low  Lowerbound
 * @param  {Number} high Upperbound
 * @return {Object} instance
 *
 * @param  {Array} [ low, high]  Lowerbound
 * @return {Object} instance
 *
 */
Sensor.prototype.scale = function( low, high ) {
  var range, state;

  range = [ low, high ];

  state = priv.get( this );

  if ( arguments.length === 1 && Array.isArray(low) ) {
    range = low;
  }

  state.scale = range;

  priv.set( this, state );

  return this;
};

Sensor.prototype.scaleTo = Sensor.prototype.scale;

/**
 * booleanAt Set a midpoint barrier value used to calculate returned value of
 *           .boolean property.
 *
 * @param  {Number} barrier
 * @return {Object} instance
 *
 */

Sensor.prototype.booleanAt = function( barrier ) {
  priv.get(this).booleanBarrier = barrier;
  return this;
};

/**
 * EXPERIMENTAL
 *
 * within When value is within the provided range, execute callback
 *
 * @param {Number} range Upperbound, converted into an array,
 *                       where 0 is lowerbound
 * @param {Function} callback Callback to execute when value falls inside range
 * @return {Object} instance
 *
 *
 * @param {Array} range Lower to Upper bounds [ low, high ]
 * @param {Function} callback Callback to execute when value falls inside range
 * @return {Object} instance
 *
 */
Sensor.prototype.within = function( range, callback ) {
  var upper;

  if ( typeof range === "number" ) {
    upper = range;
    range = [ 0, upper ];
  }

  if ( !Array.isArray(range) ) {
    this.emit( "error", { message: "range must be an array" } );
    return;
  }

  // Use the continuous read event for high resolution
  this.on("read", function() {
    if ( this.value >= range[0] && this.value <= range[1] ) {
      callback.call( this, null );
    }
  }.bind(this));

  return this;
};

module.exports = Sensor;

// Reference
// http://itp.nyu.edu/physcomp/Labs/Servo
// http://arduinobasics.blogspot.com/2011/05/arduino-uno-flex-sensor-and-leds.html

// TODO:
// Update comments/docs
<commit_msg>Remove dumb change event guard forever<commit_after>var Board = require("../lib/board.js"),
    events = require("events"),
    util = require("util");

// Sensor instance private data
var priv = new WeakMap(),
    aliases = {
      change: [
        // Generic sensor value change
        "change",
        // Slider sensors (alias)
        "slide",
        // Soft Potentiometer (alias)
        "touch",
        // Force Sensor (alias)
        "force",
        // Flex Sensor (alias)
        "bend"
      ]
    };

/**
 * Sensor
 * @constructor
 *
 * @description Generic analog or digital sensor constructor
 *
 * @param {Object} opts Options: pin, freq, range
 */
function Sensor( opts ) {

  if ( !(this instanceof Sensor) ) {
    return new Sensor( opts );
  }

  var value, last, min, max, vranges, samples;

  value = null;
  last = null;
  min = 1023;
  max = 0;
  samples = [];

  // Initialize a Device instance on a Board
  Board.Device.call(
    this, opts = Board.options( opts )
  );

  // Set the pin to ANALOG (INPUT) mode
  this.mode = this.firmata.MODES.ANALOG;
  this.firmata.pinMode( this.pin, this.mode );

  // Servo instance properties
  this.freq = opts.freq || 25;
  this.range = opts.range || [ 0, 1023 ];
  this.sensitivity = opts.sensitivity === undefined ? 1 : opts.sensitivity;

  // Analog Read event loop
  this.firmata.analogRead( this.pin, function( data ) {

    // In the first 5 seconds, we will receive min/max
    // calibration values which will be used to
    // map and scale all sensor readings from this pin
    // if ( data > max ) {
    //   this.range[1] = max = data;
    // }

    // if ( data < min ) {
    //   this.range[0] = min = data;
    // }

    // Update the closed over `value`
    value = data;

    samples.push( data );

  }.bind(this));

  // Throttle
  setInterval(function() {
    var err, median, low, high;

    err = null;

    // To reduce noise in sensor readings, sort collected samples
    // from high to low and select the value in the center.
    median = (function( input ) {
      var half, len, sorted;
      // faster than default comparitor (even for small n)
      sorted = input.sort(function( a, b ) {
        return a - b;
      });
      len = sorted.length;
      half = Math.floor( len / 2 );

      // If the length is odd, return the midpoint m
      // If the length is even, return average of m & m + 1
      return len % 2 ? sorted[half] : (sorted[half - 1] + sorted[half]) / 2;
    }( samples ));

    // Emit the continuous "read" event
    this.emit( "read", err, median );

    // If the median value for this interval is outside last +/- a threshold
    // fire a change event

    low = last - this.sensitivity;
    high = last + this.sensitivity;

    // Includes all aliases
    // Prevent events from firing if the latest value is the same as
    // the last value to trigger a change event
    if ( median < low || median > high ) {
      aliases.change.forEach(function( change ) {
        this.emit( change, err, median );
      }, this );
    }

    // Store this media value for comparison
    // in next interval
    last = median;

    // Reset samples
    samples.length = 0;
  }.bind(this), this.freq );

  // Create a "state" entry for privately
  // storing the state of the sensor
  priv.set( this, {
    booleanBarrier: 512,
    scale: null,
    value: 0
  });

  Object.defineProperties( this, {
    normalized: {
      get: function() {
        return value === null ? null :
          Board.map( value, this.range[0], this.range[1], 0, 255 );
      }
    },
    constrained: {
      get: function() {
        return value === null ? null :
          Board.constrain( this.normalized, 0, 255 );
      }
    },
    boolean: {
      get: function() {
        return this.value > priv.get( this ).booleanBarrier ?
          true : false;
      }
    },
    scaled: {
      get: function() {
        var mapped, constrain, scale;

        scale = priv.get( this ).scale;

        if ( scale && value !== null ) {
          mapped = Board.map( value, this.range[0], this.range[1], scale[0], scale[1] );
          constrain = Board.constrain( mapped, scale[0], scale[1] );

          return constrain;
        }
        return this.constrained;
      }
    },
    value: {
      get: function() {
        var state;

        state = priv.get( this );

        if ( state.scale ) {
          return this.scaled;
        }

        return value;
      }
    }
  });
}

util.inherits( Sensor, events.EventEmitter );

/**
 * pinMode Change the sensor's pinMode on the fly
 * @param  {Number} mode Sensor pin mode value
 * @return {Object} instance
 */
Sensor.prototype.pinMode = function( mode ) {
  this.mode = mode;
  this.firmata.pinMode( this.pin, mode );
  return this;
};

/**
 * scale/scaleTo Set a value scaling range
 *
 * @param  {Number} low  Lowerbound
 * @param  {Number} high Upperbound
 * @return {Object} instance
 *
 * @param  {Array} [ low, high]  Lowerbound
 * @return {Object} instance
 *
 */
Sensor.prototype.scale = function( low, high ) {
  var range, state;

  range = [ low, high ];

  state = priv.get( this );

  if ( arguments.length === 1 && Array.isArray(low) ) {
    range = low;
  }

  state.scale = range;

  priv.set( this, state );

  return this;
};

Sensor.prototype.scaleTo = Sensor.prototype.scale;

/**
 * booleanAt Set a midpoint barrier value used to calculate returned value of
 *           .boolean property.
 *
 * @param  {Number} barrier
 * @return {Object} instance
 *
 */

Sensor.prototype.booleanAt = function( barrier ) {
  priv.get(this).booleanBarrier = barrier;
  return this;
};

/**
 * EXPERIMENTAL
 *
 * within When value is within the provided range, execute callback
 *
 * @param {Number} range Upperbound, converted into an array,
 *                       where 0 is lowerbound
 * @param {Function} callback Callback to execute when value falls inside range
 * @return {Object} instance
 *
 *
 * @param {Array} range Lower to Upper bounds [ low, high ]
 * @param {Function} callback Callback to execute when value falls inside range
 * @return {Object} instance
 *
 */
Sensor.prototype.within = function( range, callback ) {
  var upper;

  if ( typeof range === "number" ) {
    upper = range;
    range = [ 0, upper ];
  }

  if ( !Array.isArray(range) ) {
    this.emit( "error", { message: "range must be an array" } );
    return;
  }

  // Use the continuous read event for high resolution
  this.on("read", function() {
    if ( this.value >= range[0] && this.value <= range[1] ) {
      callback.call( this, null );
    }
  }.bind(this));

  return this;
};

module.exports = Sensor;

// Reference
// http://itp.nyu.edu/physcomp/Labs/Servo
// http://arduinobasics.blogspot.com/2011/05/arduino-uno-flex-sensor-and-leds.html

// TODO:
// Update comments/docs
<|endoftext|>


<commit_before>'use strict';

var AdminController = require('../Admin');

module.exports = function () {

};
module.exports.prototype = AdminController.prototype.extend({
  name: 'users',

  indexAction: function() {
    var _this = this,
      countPerPage = 20,
      findParams = _this.getFindParams(),
      filterParams = _this.getFilterParams(),
      sortParams = _this.getSortParams();

    _this.mongodb
      .collection('users')
      .find({$and: [filterParams, findParams]})
      .count(function(err, totalCount) {
        _this.setPagination(totalCount, countPerPage);
        _this.mongodb
          .collection('users')
          .find({$and: [filterParams, findParams]})
          .sort(sortParams)
          .skip(_this.getPaginationSkip())
          .limit(_this.getPaginationLimit())
          .toArray(function(err, users){
            _this.view.render({
              title: 'User Verwaltung - ToyBlocks',
              users: users
            });
          });
      });
  },

  updateAction: function() {
    var _this = this;
    _this.mongodb
      .collection('users')
      .update(
        {tuid: _this.request.param('tuid')},
        {$set: {'right_level': parseInt(_this.request.param('right_level'))}},
        {},
        function (err) {
          if(err)
            _this.response.json({result:'error'});
          else
            _this.response.json({result:'success'});
        });
  },

  deleteAction: function() {
    var _this = this,
      id = _this.request.param('id');

    _this.mongodb
      .collection('users')
      .remove({_id: _this.mongo.ObjectID(id)}, 1, function(err) {
          if(err){
            _this.response.json({result:'error'});
          }
          else{
            _this.response.json({result:'success'});
          }
        });
  },

  deleteallusersAction: function() {
    var _this = this;

    _this.mongodb
      .collection('users')
      .remove({student: true, right_level: 300}, 0, function(err) {
          if(err)
            _this.response.json({result:'error'});
          else
            _this.response.json({result:'success'});
        });
  }

});
<commit_msg>Users: made all users visible at once<commit_after>'use strict';

var AdminController = require('../Admin');

module.exports = function () {

};
module.exports.prototype = AdminController.prototype.extend({
  name: 'users',

  indexAction: function() {
    var _this = this,
      findParams = _this.getFindParams(),
      filterParams = _this.getFilterParams(),
      sortParams = _this.getSortParams();

      _this.mongodb
        .collection('users')
        .find({$and: [filterParams, findParams]})
        .sort(sortParams)
        .toArray(function(err, users){
          _this.view.render({
            title: 'User Verwaltung - ToyBlocks',
            users: users
          });
        });

  },

  updateAction: function() {
    var _this = this;
    _this.mongodb
      .collection('users')
      .update(
        {tuid: _this.request.param('tuid')},
        {$set: {'right_level': parseInt(_this.request.param('right_level'))}},
        {},
        function (err) {
          if(err)
            _this.response.json({result:'error'});
          else
            _this.response.json({result:'success'});
        });
  },

  deleteAction: function() {
    var _this = this,
      id = _this.request.param('id');

    _this.mongodb
      .collection('users')
      .remove({_id: _this.mongo.ObjectID(id)}, 1, function(err) {
          if(err){
            _this.response.json({result:'error'});
          }
          else{
            _this.response.json({result:'success'});
          }
        });
  },

  deleteallusersAction: function() {
    var _this = this;

    _this.mongodb
      .collection('users')
      .remove({student: true, right_level: 300}, 0, function(err) {
          if(err)
            _this.response.json({result:'error'});
          else
            _this.response.json({result:'success'});
        });
  }

});
<|endoftext|>


<commit_before>var form = require('express-form')
  , field = form.field
  , utilities = require('../utilities')
  , mongoose = require('mongoose')
  , Confession = mongoose.model('Confession')
  , Event = mongoose.model('Event')
  , User = mongoose.model('User')
  , moment = require('moment')
  , email = require('../email')
  , util = require('util')
  , auth = require('../auth')
  , crypto = require('crypto');

module.exports = function(app){
	app.get('/confessional', function(req, res){
		var query = Confession.find({});
		if(!req.user || req.user.role < 10){
			query.where('active', true);
		}else{
			query.populate('recentEvents');
		}
		query.sort('-number').exec(function(err, confessions){
			for(var i=0; i<confessions.length; i++){
				confessions[i].text = confessions[i].text.replace(/\r\n/gmi, '
').replace(/\r/gmi, '
').replace(/\n/gmi, '
');
			}
			res.render('confessions', {title: 'All Confessions', confessions: confessions, moment: moment});
		});
	});

	app.get('/confessional/numberExisting', auth.authorize(2, 10), function(req, res){
		var start = 1;
		Confession.find().sort('date').exec(function(err, confessions){
			for(var i=0; i<confessions.length; i++){
				if(!confessions[i].number || confessions[i].number == -1){
					confessions[i].number = start++;
					confessions[i].active = true;
					confessions[i].save();
				}
			}
			req.flash('info', 'Done numbering existing confessions.');
			res.redirect('back');
		});
	});

	app.get('/confessional/flag/:id', function(req, res){
		if(!req.params.id){
			req.flash('error', 'Confession ID required.');
			res.redirect('back');
			return;
		}
		Confession.findById(req.params.id).exec(function(err, confession){
			if(err || !confession){
				req.flash('error', 'Confession not found.');
				res.redirect('back');
				return;
			}
			confession.flags++;
			confession.save(function(err){

				var mailOptions = {
			    	to: [{
			    		email: 'experimonth+confessional@lifeandscience.org'
			    	}], // list of receivers
			    	subject: 'Flagged Confession.', // Subject line,
					generateTextFromHTML: true,
					html: 'Confessional #'+confession.number+' was flagged, bringing it\'s total number of flags to '+confession.flags+' on '+moment().format('YYYY-MM-DD hh:mm A')+'\n\n---\n\n'+confession.text
			    };

			    // send mail with defined transport object
				email.sendMail(mailOptions);

				req.flash('info', 'Confession flagged.');
				res.redirect('back');
				return;
			});
			return;
		});
	});

	app.get('/confessional/promote/:id', function(req, res){
		if(!req.params.id){
			req.flash('error', 'Confession ID required.');
			res.redirect('back');
			return;
		}
		Confession.findById(req.params.id).exec(function(err, confession){
			if(err || !confession){
				req.flash('error', 'Confession not found.');
				res.redirect('back');
				return;
			}
			confession.promoted = !confession.promoted;
			confession.save(function(err){
				req.flash('info', 'Confession '+(confession.promoted ? 'promoted.' : 'demoted.'));
				res.redirect('back');
				return;
			});
			return;
		});
	});

	app.get('/confessional/publish/:id', auth.authorize(2, 10), function(req, res){
		if(!req.params.id){
			req.flash('error', 'Confession ID required.');
			res.redirect('back');
			return;
		}
		Confession.findById(req.params.id).exec(function(err, confession){
			if(err || !confession){
				req.flash('error', 'Confession not found.');
				res.redirect('back');
				return;
			}
			confession.active = true;
			confession.save(function(err){
				req.flash('info', 'Confession published.');
				res.redirect('back');
				return;
			});
			return;
		});
	});

	app.get('/confessional/unpublish/:id', auth.authorize(2, 10), function(req, res){
		if(!req.params.id){
			req.flash('error', 'Confession ID required.');
			res.redirect('back');
			return;
		}
		Confession.findById(req.params.id).exec(function(err, confession){
			if(err || !confession){
				req.flash('error', 'Confession not found.');
				res.redirect('back');
				return;
			}
			confession.active = false;
			confession.save(function(err){
				req.flash('info', 'Confession unpublished.');
				res.redirect('back');
				return;
			});
			return;
		});
	});

	// (as, populate, title, object, template, varNames, redirect, beforeRender, beforeSave)
	var as = 'confession'
	  , populate = []
	  , template = 'confessions/form'
	  , varNames = ['text']
	  , redirect = '/confess/thanks'
	  , formValidate = form(
			field('text').trim().required()
		)
	  , beforeRender = function(req, res, item, callback){
			res.locals.timestamp = Date.now();
			res.locals.nonce = crypto.createHash('md5').update(''+res.locals.timestamp).digest('hex');

			if(item.confession && req.params && req.params.number){
				item.confession.text = 'This is in reply to confession #'+req.params.number+': ';
			}
			item.action = '/confess';
			if(req.params.number){
				Confession.find({number: req.params.number}).exec(function(err, confessions){
					if(!err && confessions && confessions.length){
						item.random_confession = confessions[0];
						return callback(item);
					}
					Confession.findRandom(req.user, function(confession){
						item.random_confession = confession;
						return callback(item);
					});
				});
			}else{
				Confession.findRandom(req.user, function(confession){
					item.random_confession = confession;
					return callback(item);
				});
			}
	/* 		return item; */
		}
	  , beforeSave = function(req, res, item, complete){
			if(!req.body.whatareyou || req.body.whatareyou != 'hewmahn'){
				req.flash('error', 'Form not submitted correctly. Try again.');
				return res.redirect('back');
			}
			if(!req.body.timestamp || !req.body.nonce){
				req.flash('error', 'Form not submitted correctly. Try again.');
				return res.redirect('back');
			}
			if(crypto.createHash('md5').update(''+req.body.timestamp).digest('hex') != req.body.nonce){
				req.flash('error', 'Form not submitted correctly. Try again.');
				return res.redirect('back');
			}

			// Email to Beck
			// setup e-mail data with unicode symbols
			Confession.count(function(err, count){
				item.number = count+1;

				var mailOptions = {
					to: [{
						email: 'experimonth+confessional@lifeandscience.org'
					}], // list of receivers
			    	subject: 'New confession.', // Subject line,
					html: 'New Confessional posted on '+moment(item.date).format('YYYY-MM-DD hh:mm A')+'\n\n---\n\n'+item.text
			    };

			    // send mail with defined transport object
				email.sendMail(mailOptions);

				if(req.user){
					// Find 5 recent events from the current user
					return Event.find({user: req.user._id}).sort('date').limit(5).exec(function(err, events){
						if(!err && events && events.length){
							item.recentEvents = events;
						}
						complete(item);
					});
				}
				return complete(item);
			});
		}
	  , layout = 'layout-confessional';

	app.get('/confess', utilities.doForm(as, populate, 'Confess.', Confession, template, varNames, redirect, beforeRender, null, layout));
	app.get('/confess/reply/:number', utilities.doForm(as, populate, 'Confess.', Confession, template, varNames, redirect, beforeRender, null, layout));
	app.post('/confess', formValidate, utilities.doForm(as, populate, 'Confess.', Confession, template, varNames, redirect, beforeRender, beforeSave, layout));

	app.get('/confess/thanks', function(req, res){
		res.render('confessions/thanks', {title: 'Your confession has been recorded.'});
	});
	app.get('/confess/random', function(req, res){
		Confession.findRandom(req.user, function(confession){
			return res.render('confessions/single_confession', {confession: confession});
		});
	});

	app.get('/confessional/export', auth.authorize(2, 10), function(req, res){
		res.writeHead(200, {
			'Content-Type': 'text/tsv',
			'Content-Disposition': 'attachment;filename=confessions.tsv'
		});
		var csv = 'ID\tNumber\tText\tTimestamp\tIs Active\tIs Promoted\tNumber of Flags\tEvent #1 Name\tEvent #1 Value\tEvent #2 Name\tEvent #2 Value\tEvent #3 Name\tEvent #3 Value\tEvent #4 Name\tEvent #4 Value\tEvent #5 Name\tEvent #5 Value\n';
		res.write(csv);

		var numConfessions = 0
		  , stream = null
		  , totallyDone = false
		  , checkDone = function(){
				if(--numConfessions == 0){
					if(totallyDone){
						util.log('totally done.');
						if(hasFoundConfession){
							// We found at least one game
							// Maybe the query needs to be re-run starting at an offset of offset
							createQueryStream(offset);
						}else{
							res.end();
						}
					}
				}
			}
		  , hasFoundConfession = false
		  , offset = 0
		  , userTransformableValues = [
				'frenemy:walkaway',
				'frenemy:walkedAwayFrom',
				'frenemy:viewedCompletedRoundScreen',
				'frenemy:startGame'
			]
		  , queryDataFunction = function(confession){
		  		++offset;

		  		++numConfessions;
		  		hasFoundConfession = true;

		  		var addToCSV = [
		  			confession._id
		  		  , confession.number
		  		  , '"'+confession.text+'"'
		  		  , moment(confession.date).format('YYYY-MM-DD hh:mm A')
		  		  , confession.active ? 'Active' : 'Inactive'
		  		  , confession.promoted ? 'Promoted' : 'Not Promoted'
		  		  , confession.flags
		  		];
		  		if(confession.recentEvents && confession.recentEvents.length){
			  		for(var i=0; i<confession.recentEvents.length; i++){
			  			addToCSV.push(confession.recentEvents[i].name);
						if(userTransformableValues.indexOf(confession.recentEvents[i].name) != -1){
							addToCSV.push(User.getStudyID(confession.recentEvents[i].value));
						}else{
							addToCSV.push(confession.recentEvents[i].value);
						}
			  		}
			  	}
			  	addToCSV = addToCSV.join('\t') + '\n';

				// Determine which of the users was this one in the round
				res.write(addToCSV);
				checkDone();
			}
		  , queryErrorFunction = function(){
				res.end();
			}
		  , queryCloseFunction = function(){
				totallyDone = true;
				++numConfessions;
				checkDone();
			}
		  , createQueryStream = function(skip){
		  		var query = Confession.find().populate('recentEvents').sort('date');
		  		if(skip){
			  		query.skip(skip);
		  		}
		  		hasFoundConfession = false;
		  		stream = query.stream();
				stream.on('data', queryDataFunction);
				stream.on('error', queryErrorFunction);
				stream.on('close', queryCloseFunction); //.run(function(err, games){
		  	};
		createQueryStream();
		return;
	});
}<commit_msg>Fixing double-quote in confessions export.<commit_after>var form = require('express-form')
  , field = form.field
  , utilities = require('../utilities')
  , mongoose = require('mongoose')
  , Confession = mongoose.model('Confession')
  , Event = mongoose.model('Event')
  , User = mongoose.model('User')
  , moment = require('moment')
  , email = require('../email')
  , util = require('util')
  , auth = require('../auth')
  , crypto = require('crypto');

module.exports = function(app){
	app.get('/confessional', function(req, res){
		var query = Confession.find({});
		if(!req.user || req.user.role < 10){
			query.where('active', true);
		}else{
			query.populate('recentEvents');
		}
		query.sort('-number').exec(function(err, confessions){
			for(var i=0; i<confessions.length; i++){
				confessions[i].text = confessions[i].text.replace(/\r\n/gmi, '
').replace(/\r/gmi, '
').replace(/\n/gmi, '
');
			}
			res.render('confessions', {title: 'All Confessions', confessions: confessions, moment: moment});
		});
	});

	app.get('/confessional/numberExisting', auth.authorize(2, 10), function(req, res){
		var start = 1;
		Confession.find().sort('date').exec(function(err, confessions){
			for(var i=0; i<confessions.length; i++){
				if(!confessions[i].number || confessions[i].number == -1){
					confessions[i].number = start++;
					confessions[i].active = true;
					confessions[i].save();
				}
			}
			req.flash('info', 'Done numbering existing confessions.');
			res.redirect('back');
		});
	});

	app.get('/confessional/flag/:id', function(req, res){
		if(!req.params.id){
			req.flash('error', 'Confession ID required.');
			res.redirect('back');
			return;
		}
		Confession.findById(req.params.id).exec(function(err, confession){
			if(err || !confession){
				req.flash('error', 'Confession not found.');
				res.redirect('back');
				return;
			}
			confession.flags++;
			confession.save(function(err){

				var mailOptions = {
			    	to: [{
			    		email: 'experimonth+confessional@lifeandscience.org'
			    	}], // list of receivers
			    	subject: 'Flagged Confession.', // Subject line,
					generateTextFromHTML: true,
					html: 'Confessional #'+confession.number+' was flagged, bringing it\'s total number of flags to '+confession.flags+' on '+moment().format('YYYY-MM-DD hh:mm A')+'\n\n---\n\n'+confession.text
			    };

			    // send mail with defined transport object
				email.sendMail(mailOptions);

				req.flash('info', 'Confession flagged.');
				res.redirect('back');
				return;
			});
			return;
		});
	});

	app.get('/confessional/promote/:id', function(req, res){
		if(!req.params.id){
			req.flash('error', 'Confession ID required.');
			res.redirect('back');
			return;
		}
		Confession.findById(req.params.id).exec(function(err, confession){
			if(err || !confession){
				req.flash('error', 'Confession not found.');
				res.redirect('back');
				return;
			}
			confession.promoted = !confession.promoted;
			confession.save(function(err){
				req.flash('info', 'Confession '+(confession.promoted ? 'promoted.' : 'demoted.'));
				res.redirect('back');
				return;
			});
			return;
		});
	});

	app.get('/confessional/publish/:id', auth.authorize(2, 10), function(req, res){
		if(!req.params.id){
			req.flash('error', 'Confession ID required.');
			res.redirect('back');
			return;
		}
		Confession.findById(req.params.id).exec(function(err, confession){
			if(err || !confession){
				req.flash('error', 'Confession not found.');
				res.redirect('back');
				return;
			}
			confession.active = true;
			confession.save(function(err){
				req.flash('info', 'Confession published.');
				res.redirect('back');
				return;
			});
			return;
		});
	});

	app.get('/confessional/unpublish/:id', auth.authorize(2, 10), function(req, res){
		if(!req.params.id){
			req.flash('error', 'Confession ID required.');
			res.redirect('back');
			return;
		}
		Confession.findById(req.params.id).exec(function(err, confession){
			if(err || !confession){
				req.flash('error', 'Confession not found.');
				res.redirect('back');
				return;
			}
			confession.active = false;
			confession.save(function(err){
				req.flash('info', 'Confession unpublished.');
				res.redirect('back');
				return;
			});
			return;
		});
	});

	// (as, populate, title, object, template, varNames, redirect, beforeRender, beforeSave)
	var as = 'confession'
	  , populate = []
	  , template = 'confessions/form'
	  , varNames = ['text']
	  , redirect = '/confess/thanks'
	  , formValidate = form(
			field('text').trim().required()
		)
	  , beforeRender = function(req, res, item, callback){
			res.locals.timestamp = Date.now();
			res.locals.nonce = crypto.createHash('md5').update(''+res.locals.timestamp).digest('hex');

			if(item.confession && req.params && req.params.number){
				item.confession.text = 'This is in reply to confession #'+req.params.number+': ';
			}
			item.action = '/confess';
			if(req.params.number){
				Confession.find({number: req.params.number}).exec(function(err, confessions){
					if(!err && confessions && confessions.length){
						item.random_confession = confessions[0];
						return callback(item);
					}
					Confession.findRandom(req.user, function(confession){
						item.random_confession = confession;
						return callback(item);
					});
				});
			}else{
				Confession.findRandom(req.user, function(confession){
					item.random_confession = confession;
					return callback(item);
				});
			}
	/* 		return item; */
		}
	  , beforeSave = function(req, res, item, complete){
			if(!req.body.whatareyou || req.body.whatareyou != 'hewmahn'){
				req.flash('error', 'Form not submitted correctly. Try again.');
				return res.redirect('back');
			}
			if(!req.body.timestamp || !req.body.nonce){
				req.flash('error', 'Form not submitted correctly. Try again.');
				return res.redirect('back');
			}
			if(crypto.createHash('md5').update(''+req.body.timestamp).digest('hex') != req.body.nonce){
				req.flash('error', 'Form not submitted correctly. Try again.');
				return res.redirect('back');
			}

			// Email to Beck
			// setup e-mail data with unicode symbols
			Confession.count(function(err, count){
				item.number = count+1;

				var mailOptions = {
					to: [{
						email: 'experimonth+confessional@lifeandscience.org'
					}], // list of receivers
			    	subject: 'New confession.', // Subject line,
					html: 'New Confessional posted on '+moment(item.date).format('YYYY-MM-DD hh:mm A')+'\n\n---\n\n'+item.text
			    };

			    // send mail with defined transport object
				email.sendMail(mailOptions);

				if(req.user){
					// Find 5 recent events from the current user
					return Event.find({user: req.user._id}).sort('date').limit(5).exec(function(err, events){
						if(!err && events && events.length){
							item.recentEvents = events;
						}
						complete(item);
					});
				}
				return complete(item);
			});
		}
	  , layout = 'layout-confessional';

	app.get('/confess', utilities.doForm(as, populate, 'Confess.', Confession, template, varNames, redirect, beforeRender, null, layout));
	app.get('/confess/reply/:number', utilities.doForm(as, populate, 'Confess.', Confession, template, varNames, redirect, beforeRender, null, layout));
	app.post('/confess', formValidate, utilities.doForm(as, populate, 'Confess.', Confession, template, varNames, redirect, beforeRender, beforeSave, layout));

	app.get('/confess/thanks', function(req, res){
		res.render('confessions/thanks', {title: 'Your confession has been recorded.'});
	});
	app.get('/confess/random', function(req, res){
		Confession.findRandom(req.user, function(confession){
			return res.render('confessions/single_confession', {confession: confession});
		});
	});

	app.get('/confessional/export', auth.authorize(2, 10), function(req, res){
		res.writeHead(200, {
			'Content-Type': 'text/tsv',
			'Content-Disposition': 'attachment;filename=confessions.tsv'
		});
		var csv = 'ID\tNumber\tText\tTimestamp\tIs Active\tIs Promoted\tNumber of Flags\tEvent #1 Name\tEvent #1 Value\tEvent #2 Name\tEvent #2 Value\tEvent #3 Name\tEvent #3 Value\tEvent #4 Name\tEvent #4 Value\tEvent #5 Name\tEvent #5 Value\n';
		res.write(csv);

		var numConfessions = 0
		  , stream = null
		  , totallyDone = false
		  , checkDone = function(){
				if(--numConfessions == 0){
					if(totallyDone){
						util.log('totally done.');
						if(hasFoundConfession){
							// We found at least one game
							// Maybe the query needs to be re-run starting at an offset of offset
							createQueryStream(offset);
						}else{
							res.end();
						}
					}
				}
			}
		  , hasFoundConfession = false
		  , offset = 0
		  , userTransformableValues = [
				'frenemy:walkaway',
				'frenemy:walkedAwayFrom',
				'frenemy:viewedCompletedRoundScreen',
				'frenemy:startGame'
			]
		  , queryDataFunction = function(confession){
		  		++offset;

		  		++numConfessions;
		  		hasFoundConfession = true;

		  		var addToCSV = [
		  			confession._id
		  		  , confession.number
		  		  , '"'+confession.text.replace(/"/g, '\"')+'"'
		  		  , moment(confession.date).format('YYYY-MM-DD hh:mm A')
		  		  , confession.active ? 'Active' : 'Inactive'
		  		  , confession.promoted ? 'Promoted' : 'Not Promoted'
		  		  , confession.flags
		  		];
		  		if(confession.recentEvents && confession.recentEvents.length){
			  		for(var i=0; i<confession.recentEvents.length; i++){
			  			addToCSV.push(confession.recentEvents[i].name);
						if(userTransformableValues.indexOf(confession.recentEvents[i].name) != -1){
							addToCSV.push(User.getStudyID(confession.recentEvents[i].value));
						}else{
							addToCSV.push(confession.recentEvents[i].value);
						}
			  		}
			  	}
			  	addToCSV = addToCSV.join('\t') + '\n';

				// Determine which of the users was this one in the round
				res.write(addToCSV);
				checkDone();
			}
		  , queryErrorFunction = function(){
				res.end();
			}
		  , queryCloseFunction = function(){
				totallyDone = true;
				++numConfessions;
				checkDone();
			}
		  , createQueryStream = function(skip){
		  		var query = Confession.find().populate('recentEvents').sort('date');
		  		if(skip){
			  		query.skip(skip);
		  		}
		  		hasFoundConfession = false;
		  		stream = query.stream();
				stream.on('data', queryDataFunction);
				stream.on('error', queryErrorFunction);
				stream.on('close', queryCloseFunction); //.run(function(err, games){
		  	};
		createQueryStream();
		return;
	});
}<|endoftext|>


<commit_before>const DrawCard = require('../../drawcard.js');

class CunningMagistrate extends DrawCard {
    setupCardAbilities(ability) { // eslint-disable-line no-unused-vars
    }
}

CunningMagistrate.id = 'cunning-magistrate'; // This is a guess at what the id might be - please check it!!!

module.exports = CunningMagistrate;
<commit_msg>Implemented Cunning Magistrate<commit_after>const DrawCard = require('../../drawcard.js');

class CunningMagistrate extends DrawCard {
    setupCardAbilities(ability) {
        this.persistentEffect({
            condition: () => this.isAttacking(),
            match: card => card.isParticipating() && card.isDishonored && card !== this,
            targetController: 'any',
            effect: ability.effects.cannotCountForResolution()
        });
    }
}

CunningMagistrate.id = 'cunning-magistrate'; // This is a guess at what the id might be - please check it!!!

module.exports = CunningMagistrate;
<|endoftext|>