<commit_before>/*
 * Wegas
 * http://www.albasim.com/wegas/
 *
 * School of Business and Engineering Vaud, http://www.heig-vd.ch/
 * Media Engineering :: Information Technology Managment :: Comem
 *
 * Copyright (C) 2012
 */

/**
 * @author Francois-Xavier Aeberhard <fx@red-agent.com>
 */

YUI.add('wegas-gaugedisplay', function (Y) {
    "use strict";

    var CONTENTBOX = 'contentBox', GaugeDisplay;

    GaugeDisplay = Y.Base.create("wegas-gauge", Y.Widget, [Y.WidgetChild, Y.Wegas.Widget, Y.Wegas.Editable], {

        CONTENT_TEMPLATE: '
<canvas height="50px" width="100px"></canvas>
',
        MAXVAL: 200,

        // ** Lifecycle Methods ** //

        renderUI: function () {
            var opts = {
                lines: 12,                                                      // The number of lines to draw
                angle: 0.15,                                                    // The length of each line
                lineWidth: 0.44,                                                // The line thickness
                pointer: {
                    length: 0.5,                                                // The radius of the inner circle
                    strokeWidth: 0.035,                                         // The rotation offset
                    color: '#000000'                                            // Fill color
                },
                colorStart: '#0981A9',                                          // Colors
                colorStop: '#000000',
                //strokeColor: '#E0E0E0',
                strokeColor: '#FFFFFF',
                generateGradient: true
            };
            this.gauge = new Gauge(this.get("contentBox").one("canvas").getDOMNode());// create the  gauge!conso
            this.gauge.setOptions(opts);
            this.gauge.maxValue = this.MAXVAL;                                  // set max gauge value
            this.gauge.animationSpeed = 32;                                     // set animation speed (32 is default value)
        },

        bindUI: function () {
            this.handlers = [];
            this.handlers.push(Y.Wegas.VariableDescriptorFacade.after("response", this.syncUI, this));
            this.handlers.push(Y.Wegas.app.after('currentPlayerChange', this.syncUI, this));
        },

        syncUI: function () {
            var maxVal, minVal, value, label,
            variableDescriptor = this.get("variable.evaluated");
            if (!variableDescriptor) {
                return;
            }

            label = this.get("label") || variableDescriptor.getPublicLabel();
            minVal = variableDescriptor.get("minValue");
            maxVal = variableDescriptor.get("maxValue") - minVal;
            value = (variableDescriptor.getInstance().get("value") - minVal) / maxVal * this.MAXVAL;
            if (!value) {
                value = 0.1;                                                    // @hack @fixme unkown bug, value seams to be treated by gauge as false...
            }

            this.gauge.set(value);                                              // set actual value
            this.get(CONTENTBOX).one(".label").setContent(label);
            this.get(CONTENTBOX).one(".percent").setContent(Math.round(value / this.MAXVAL * 100) + "%");
        },

        destructor: function () {
            var i;
            for (i = 0; i < this.handlers.length; i += 1) {
                this.handlers[i].detach();
            }
        }
    }, {
        ATTRS : {
            variable: {
                getter: Y.Wegas.Widget.VARIABLEDESCRIPTORGETTER,
                _inputex: {
                    _type: "variableselect",
                    label: "variable"
                }
            },
            label : {
                type: "string",
                optional: true,
                validator: Y.Lang.isString
            }
        }
    });

    Y.namespace('Wegas').GaugeDisplay = GaugeDisplay;
});
<commit_msg>CEP - fix Issue #93<commit_after>/*
 * Wegas
 * http://www.albasim.com/wegas/
 *
 * School of Business and Engineering Vaud, http://www.heig-vd.ch/
 * Media Engineering :: Information Technology Managment :: Comem
 *
 * Copyright (C) 2012
 */

/**
 * @author Francois-Xavier Aeberhard <fx@red-agent.com>
 */

YUI.add('wegas-gaugedisplay', function (Y) {
    "use strict";

    var CONTENTBOX = 'contentBox', GaugeDisplay;

    GaugeDisplay = Y.Base.create("wegas-gauge", Y.Widget, [Y.WidgetChild, Y.Wegas.Widget, Y.Wegas.Editable], {
        CONTENT_TEMPLATE: '
<canvas height="50px" width="100px"></canvas>
',
        MAXVAL: 200,
        handlers: null,
        gauge: null,
        // ** Lifecycle Methods ** //
        initializer: function () {
            this.handlers = [];
        },
        renderUI: function () {
            var opts = {
                lines: 12, // The number of lines to draw
                angle: 0.15, // The length of each line
                lineWidth: 0.44, // The line thickness
                pointer: {
                    length: 0.5, // The radius of the inner circle
                    strokeWidth: 0.035, // The rotation offset
                    color: '#000000'                                            // Fill color
                },
                colorStart: '#0981A9', // Colors
                colorStop: '#000000',
                //strokeColor: '#E0E0E0',
                strokeColor: '#FFFFFF',
                generateGradient: true
            };
            this.gauge = new Gauge(this.get("contentBox").one("canvas").getDOMNode());// create the  gauge!conso
            this.gauge.setOptions(opts);
            this.gauge.maxValue = this.MAXVAL;                                  // set max gauge value
            this.gauge.animationSpeed = 32;                                     // set animation speed (32 is default value)
        },
        bindUI: function () {
            this.handlers.push(Y.Wegas.VariableDescriptorFacade.after("response", this.syncUI, this));
            this.handlers.push(Y.Wegas.app.after('currentPlayerChange', this.syncUI, this));
        },
        syncUI: function () {
            var maxVal, minVal, value, label,
                    variableDescriptor = this.get("variable.evaluated");
            if (!variableDescriptor) {
                return;
            }

            label = this.get("label") || variableDescriptor.getPublicLabel();
            minVal = variableDescriptor.get("minValue");
            maxVal = variableDescriptor.get("maxValue") - minVal;
            value = (variableDescriptor.getInstance().get("value") - minVal) / maxVal * this.MAXVAL;
            if (!value) {
                value = 0.1;                                                    // @hack @fixme unkown bug, value seams to be treated by gauge as false...
            }

            this.gauge.set(value);                                              // set actual value
            this.get(CONTENTBOX).one(".label").setContent(label);
            this.get(CONTENTBOX).one(".percent").setContent(Math.round(value / this.MAXVAL * 100) + "%");
        },
        destructor: function () {
            var i;
            for (i = 0; i < this.handlers.length; i += 1) {
                this.handlers[i].detach();
            }
        }
    }, {
        ATTRS: {
            variable: {
                getter: Y.Wegas.Widget.VARIABLEDESCRIPTORGETTER,
                _inputex: {
                    _type: "variableselect",
                    label: "variable"
                },
            },
            label: {
                type: "string",
                optional: true,
                validator: Y.Lang.isString,
                _inputex: {
                    label: "Label"
                }
            }
        }
    });

    Y.namespace('Wegas').GaugeDisplay = GaugeDisplay;
});
<|endoftext|>


<commit_before>var amqp = require('amqplib');
var Readable = require('stream').Readable
  || require('readable-stream/readable');
var Writable = require('stream').Writable
  || require('readable-stream/writable');
var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;

var argv = require('yargs')
  .default('url', 'amqp://localhost')
  .default('queue', 'rmqcat')
  .boolean('l')
  .argv;

var debug = (process.env.DEBUG) ? console.warn : function() {};

var url = argv.url;

// I use three different (kinds of) queues: there is the handshake
// queue, which is the common knowledge between the client and the
// server (the "connection point", like a port); then is a stdin queue
// and a stdout queue, both named from the point of view of the
// server.

// The stdin queue is that over which the client sends data to the
// server, and the stdout queue is that over which the server sends
// data to the client. The client creates the stdin queue and annouces
// it to the server (as the 'replyTo' of an empty message sent to the
// handshake queue); the server creates the stdout queue and announces
// it to the client (likewise, sent to the stdout queue).

var handshakeQ = argv.queue;

var ok = amqp.connect(url);
ok.then(function(connection) {

  return connection.createChannel().then(function(ch) {

    // It's convenient, since it's passed around, to use the channel
    // closing a a signal to clean up and leave.
    ch.on('close', function() {
      connection.close().then(function() {
        process.exit(0);
      });
    });

    // Always sure the handshake queue exists, since we don't know who
    // will turn up first
    debug('Asserting handshake queue: %s', handshakeQ);
    ch.assertQueue(handshakeQ);

    if (argv.l) { // act as server
      ch.assertQueue('', {exclusive: true}).then(function(ok) {
        var stdinQ = ok.queue;
        debug('Created stdin queue: %s', stdinQ);

        // I need a channel on which to accept connections. Why
        // another? Because this one only deals with one connection at
        // a time (so it can rewire stdin and stdout appropriately),
        // and to do that, I must use prefetch=1 so I don't get sent
        // all connection requests at once.
        connection.createChannel().then(function(acceptCh) {
          var accepted = null;
          var current = null;
          acceptCh.prefetch(1);
          acceptCh.consume(handshakeQ, function(msg) {
            switch (msg.properties.type) {
            case 'open':
              accepted = msg;
              var stdoutQ = msg.properties.replyTo;
              debug('Recv open: stdout is %s', stdoutQ);
              acceptCh.sendToQueue(stdoutQ, new Buffer(0),
                                   {type: 'open', replyTo: stdinQ});
              debug('Sent open to %s: stdin is %s', stdoutQ, stdinQ);

              current = writableQueue(ch, stdoutQ);
              process.stdin.unpipe();
              process.stdin.pipe(current, {end: true});
              break;
            default:
              console.warn('Something other than open, %s ',
                           msg.properties.type,
                           'received on handshake queue');
            }
          }, {exclusive: true});

          var streams = new QueueStreamServer(ch, stdinQ);
          streams.on('connection', function(stream) {
            stream.pipe(process.stdout, {end: !argv.k});
            stream.on('end', function() {
              acceptCh.ack(accepted);
              if (!argv.k) ch.close();
            });
          });
        });
      });
    }

    else { // act as client
      ch.assertQueue('', {exclusive: true}).then(function(ok) {
        var stdoutQ = ok.queue;
        debug('Created stdout queue %s', stdoutQ);

        ch.consume(stdoutQ, function(msg) {
          switch (msg.properties.type) {
          case 'open':
            var stdinQ = msg.properties.replyTo;
            debug('Recv open: stdin is %s', stdinQ);
            var relay = writableQueue(ch, stdinQ);
            process.stdin.pipe(relay, {end: true});
            process.stdin.on(
              'end', setImmediate.bind(null, ch.close.bind(ch)));
            break;
          case 'data':
            debug('Recv %d bytes on stdout', msg.content.length);
            process.stdout.write(msg.content);
            break;
          case 'eof':
            debug('Recv eof on stdout (%s)', stdoutQ);
            process.stdout.end(); // %% can I do this?
            ch.close();
            break;
          default:
            console.warn('Unknown message type %s',
                         msg.properties.type,
                         ' received on stdout queue');
          }
        }, {noAck: true, exclusive: true});

        ch.sendToQueue(handshakeQ, new Buffer(0),
                       {type: 'open', replyTo: stdoutQ});
        debug('Sent open to handshake queue %s', handshakeQ);
      });
    }
  });
}, console.warn);

function writableQueue(channel, queue) {
  var writable = new Writable();
  writable._write = function(chunk, _enc, cb) {
    debug('Sent %d bytes to %s', chunk.length, queue);
    if (channel.sendToQueue(queue, chunk, {type: 'data'})) {
      cb();
    }
    else channel.once('drain', cb);
  };
  writable.on('finish', function() {
    channel.sendToQueue(queue, new Buffer(0), {type: 'eof'});
    debug('Sent eof to %s', queue);
  });
  return writable;
}

function QueueStreamServer(channel, queue) {
  EventEmitter.call(this);

  var self = this;
  var current = null;

  channel.consume(queue, function(msg) {
    if (current === null) {
      current = new Readable();
      current._read = function() {};
      self.emit('connection', current);
    }

    switch (msg && msg.properties.type) {
    case null: // consume has been cancelled
      debug('Consume cancelled (%s)', queue);
      setImmediate(function() {
        self.emit('error', new Error('Input queue deleted'))}); // fall-through
    case 'eof':
      debug('Recv eof on %s', queue);
      current.push(null);
      current = null;
      break;
    case 'data':
      debug('Recv %d bytes on %s', msg.content.length, queue);
      current.push(msg.content); break;
    default:
      console.warn('Unknown message type %s', msg.properties.type);
    }
  }, {exclusive: true, noAck: true});
}
inherits(QueueStreamServer, EventEmitter);
<commit_msg>Wait for EOF before exiting, at each end<commit_after>var amqp = require('amqplib');
var Readable = require('stream').Readable
  || require('readable-stream/readable');
var Writable = require('stream').Writable
  || require('readable-stream/writable');
var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;

var argv = require('yargs')
  .default('url', 'amqp://localhost')
  .default('queue', 'rmqcat')
  .boolean('l')
  .argv;

var debug = (process.env.DEBUG) ? console.warn : function() {};

var url = argv.url;

// I use three different (kinds of) queues: there is the handshake
// queue, which is the common knowledge between the client and the
// server (the "connection point", like a port); then is a stdin queue
// and a stdout queue, both named from the point of view of the
// server.

// The stdin queue is that over which the client sends data to the
// server, and the stdout queue is that over which the server sends
// data to the client. The client creates the stdin queue and annouces
// it to the server (as the 'replyTo' of an empty message sent to the
// handshake queue); the server creates the stdout queue and announces
// it to the client (likewise, sent to the stdout queue).

var handshakeQ = argv.queue;

var ok = amqp.connect(url);
ok.then(function(connection) {

  return connection.createChannel().then(function(ch) {

    // It's convenient, since it's passed around, to use the channel
    // closing a a signal to clean up and leave.
    ch.on('close', function() {
      connection.close().then(function() {
        process.exit(0);
      });
    });

    // Always sure the handshake queue exists, since we don't know who
    // will turn up first
    debug('Asserting handshake queue: %s', handshakeQ);
    ch.assertQueue(handshakeQ);

    if (argv.l) { // act as server
      ch.assertQueue('', {exclusive: true}).then(function(ok) {
        var stdinQ = ok.queue;
        debug('Created stdin queue: %s', stdinQ);

        // I need a channel on which to accept connections. Why
        // another? Because this one only deals with one connection at
        // a time (so it can rewire stdin and stdout appropriately),
        // and to do that, I must use prefetch=1 so I don't get sent
        // all connection requests at once.
        connection.createChannel().then(function(acceptCh) {
          var accepted = null;
          var current = null;
          acceptCh.prefetch(1);
          acceptCh.consume(handshakeQ, function(msg) {
            switch (msg.properties.type) {
            case 'open':
              accepted = msg;
              var stdoutQ = msg.properties.replyTo;
              debug('Recv open: stdout is %s', stdoutQ);
              acceptCh.sendToQueue(stdoutQ, new Buffer(0),
                                   {type: 'open', replyTo: stdinQ});
              debug('Sent open to %s: stdin is %s', stdoutQ, stdinQ);

              process.stdin.unpipe();
              current = writableQueue(ch, stdoutQ);
              process.stdin.pipe(current, {end: true});
              break;
            default:
              console.warn('Something other than open, %s ',
                           msg.properties.type,
                           'received on handshake queue');
            }
          }, {exclusive: true});

          var streams = new QueueStreamServer(ch, stdinQ);
          streams.on('connection', function(stream) {
            stream.pipe(process.stdout, {end: !argv.k});
            stream.on('end', function() {
              current.end();
              acceptCh.ack(accepted);
              if (!argv.k) {
                ch.close();
              }
            });
          });
        });
      });
    }

    else { // act as client
      ch.assertQueue('', {exclusive: true}).then(function(ok) {
        var stdoutQ = ok.queue;
        debug('Created stdout queue %s', stdoutQ);

        ch.consume(stdoutQ, function(msg) {
          switch (msg.properties.type) {
          case 'open':
            var stdinQ = msg.properties.replyTo;
            debug('Recv open: stdin is %s', stdinQ);
            var relay = writableQueue(ch, stdinQ);
            process.stdin.pipe(relay, {end: true});
            break;
          case 'data':
            debug('Recv %d bytes on stdout', msg.content.length);
            process.stdout.write(msg.content);
            break;
          case 'eof':
            debug('Recv eof on stdout (%s)', stdoutQ);
            ch.close();
            break;
          default:
            console.warn('Unknown message type %s',
                         msg.properties.type,
                         ' received on stdout queue');
          }
        }, {noAck: true, exclusive: true});

        ch.sendToQueue(handshakeQ, new Buffer(0),
                       {type: 'open', replyTo: stdoutQ});
        debug('Sent open to handshake queue %s', handshakeQ);
      });
    }
  });
}, console.warn);

function writableQueue(channel, queue) {
  var writable = new Writable();
  writable._write = function(chunk, _enc, cb) {
    debug('Sent %d bytes to %s', chunk.length, queue);
    if (channel.sendToQueue(queue, chunk, {type: 'data'})) {
      cb();
    }
    else channel.once('drain', cb);
  };
  writable.on('finish', function() {
    channel.sendToQueue(queue, new Buffer(0), {type: 'eof'});
    debug('Sent eof to %s', queue);
  });
  return writable;
}

function QueueStreamServer(channel, queue) {
  EventEmitter.call(this);

  var self = this;
  var current = null;

  channel.consume(queue, function(msg) {
    if (current === null) {
      current = new Readable();
      current._read = function() {};
      self.emit('connection', current);
    }

    switch (msg && msg.properties.type) {
    case null: // consume has been cancelled
      debug('Consume cancelled (%s)', queue);
      setImmediate(function() {
        self.emit('error', new Error('Input queue deleted'))}); // fall-through
    case 'eof':
      debug('Recv eof on %s', queue);
      current.push(null);
      current = null;
      break;
    case 'data':
      debug('Recv %d bytes on %s', msg.content.length, queue);
      current.push(msg.content); break;
    default:
      console.warn('Unknown message type %s', msg.properties.type);
    }
  }, {exclusive: true, noAck: true});
}
inherits(QueueStreamServer, EventEmitter);
<|endoftext|>


<commit_before>/*
 * Wegas
 * http://wegas.albasim.ch
 *
 * Copyright (c) 2015 School of Business and Engineering Vaud, Comem
 * Licensed under the MIT License
 */
/**
 * Wegas Dashboard - V2
 * @author Raphaël Schmutz <raph@hat-owl.cc>
 */
YUI.add('wegas-dashboard', function (Y) {
    "use strict";
    var CONTENTBOX = "contentBox";

    Y.Wegas.Dashboard = Y.Base.create("wegas-dashboard",
        Y.Widget,
        [Y.WidgetParent, Y.WidgetChild, Y.Wegas.Widget, Y.Wegas.Editable], {
            CONTENT_TEMPLATE: "

",
            initializer: function () {
                var context = this;
                context.get("cardsData").forEach(function (data) {
                    if (data.blocs && data.blocs.length > 0) {
                        context.get("cardsData").blocs.forEach(function (bloc) {
                            context._addOriginalBloc(data.id, bloc);
                        });
                    }
                });
                this.handlers = [];
            },
            destructor: function () {
                var i;
                for (i = 0; i < this.handlers.length; i += 1) {
                    this.handlers[i].detach();
                }
            },
            renderUI: function () {
                if (this.toolbar) {
                    this.toolbar.removeAll();

                    var game = Y.Wegas.Facade.Game.cache.getCurrentGame(),
                        teams = game.get("teams"),
                        emptyGame = (teams.length===0 || teams.length===1 && teams[0].get("@class")==="DebugTeam"),
                        cb = this.get(CONTENTBOX);

                    if (emptyGame){
                        this.toolbar.add(new Y.Wegas.Button({
                            label: 'No players have joined yet: click to check for new players',
                            cssClass: 'globalRefreshTitle',
                            on: {
                                click: Y.bind(function (event) {
                                    location.reload(); // That's stupid, same as {@see phenixize}
                                }, this)
                            }
                        }));
                        return;
                    }

                    this.toolbar.add(new Y.Wegas.Button({
                        label: 'Check for new players',
                        cssClass: 'globalRefreshTitle',
                        on: {
                            click: Y.bind(function (event) {
                                location.reload(); // That's stupid, same as {@see phenixize}
                            }, this)
                        }
                    }));

                    this.toolbar.add(new Y.Wegas.Button({
                        label: '',
                        cssClass: 'globalImpacts mailButton',
                        on: {
                            click: Y.bind(function (event) {
                                new Y.Wegas.EmailTeamModal({
                                    "team": game,
                                    "on": {
                                        "email:sent": function() {
                                            this.close();
                                        }
                                    }
                                }).render();
                            }, this)
                        },
                        tooltip: 'Send real E-mail to all players'
                    }));

                    this.toolbar.add(new Y.Wegas.Button({
                        label: '',
                        cssClass: 'globalImpacts impactButton',
                        on: {
                            click: Y.bind(function (event) {
                                new Y.Wegas.ImpactsTeamModal({
                                    "team": game
                                }).render();
                            }, this)
                        },
                        tooltip: 'Impact all players'
                    }));

                    this.toolbar.add(new Y.Wegas.Button({
                        label: 'Monitoring',
                        cssClass: 'globalImpacts monitoredDataTitle',
                        on: {
                            click: Y.bind(function (event) {
                                var button = event.target;
                                //this.phenixize();
                                if (button.get("boundingBox").hasClass("loading")) {
                                    return;
                                }
                                button.get("boundingBox").addClass("loading");
                                this.syncUI().then(function () {
                                    button.get("boundingBox").removeClass("loading");
                                });
                            }, this)
                        }
                    }));

                    this._checkToolbarResize();

                }
            },
            bindUI: function () {
                this.handlers.push(Y.Wegas.Facade.Game.after("update", this.phenixize, this));
            },
            /**
             * BEURK... Dirty Solution
             * @todo replace fuckin dirty clone'n'suicide pattern with slightly more intelligent sync
             * @returns {undefined}
             */
            phenixize: function () {
                return;
                var parent, childIndex,
                    cfg = {
                        "name": "overview",
                        "type": "TeamsOverviewDashboard",
                        "remoteScript": "",
                        "plugins": [
                            {
                                "fn": "WidgetToolbar"
                            }
                        ]
                    };

                parent = this.get("parent");
                if (parent) {
                    childIndex = parent.indexOf(this);
                    if (childIndex >= 0) {
                        parent.remove(childIndex);
                    }
                    parent.add(Y.Wegas.Widget.create(cfg));
                    if (childIndex >= 0) {
                        this.destroy();
                    }
                }
            },
            syncUI: function () {
                var BB = this.get("boundingBox");
                BB.addClass("loading");
                return this._createCards().then(function (data) {
                    BB.removeClass("loading");
                    return data;
                });
            },
            getMonitoredData: function () {
                return this._monitoredData || {};
            },

            /**
             *
             * create cards as child
             * return Promise-> cardsData
             */
            _createCards: function () {
                return this._getMonitoredData().then(Y.bind(function (monitoredBlocs) {
                    this.destroyAll();
                    this._monitoredData = monitoredBlocs;
                    Y.Array.each(this.get("cardsData"), function (data) {
                        var card = {
                            "id": data.id,
                            "title": data.title,
                            "icon": data.icon || null,
                            "blocs": this._combineBlocs(data, monitoredBlocs)
                        };
                        this.add(new Y.Wegas.Card(card));
                    }, this);
                    try {
                        if (this.get("resize")) {
                            this.plug(Y.Wegas.CardsResizable);
                            this.CardsResizable.resetClassSize();
                            this.CardsResizable.resize();
                        }
                    } catch (e) {
                    } finally {
                        this._adjustTitles();
                        this.get("boundingBox").removeClass("loading");
                        return this.get("cardsData");
                    }
                }, this));
            },
            _addOriginalBloc: function (idCard, originalBloc) {
                var originalBlocs = this.get("originalBlocs");
                if (!originalBlocs[idCard]) {
                    originalBlocs[idCard] = [];
                }
                originalBlocs[idCard].push(originalBloc);
                this.set("originalBlocs", originalBlocs);
            },
            _resetToInitialBlocs: function (data) {
                var originalBlocs = this.get("originalBlocs");
                data.blocs = [];
                if (originalBlocs[data.id]) {
                    originalBlocs[data.id].forEach(function (bloc) {
                        data.blocs.push(bloc);
                    });
                }
            },
            _combineBlocs: function (data, monitoredBlocs) {
                var blocs, newBlocs, newBloc;
                this._resetToInitialBlocs(data);
                blocs = data.blocs;
                if (monitoredBlocs !== null && monitoredBlocs.data && monitoredBlocs.data[data.id]) {
                    monitoredBlocs.structure.forEach(function (blocsToAdd) {
                        newBlocs = {
                            "position": "left",
                            "cardBlocType": "monitoring",
                            "items": []
                        };
                        if (blocsToAdd.title) {
                            newBlocs.title = blocsToAdd.title;
                        }
                        if (blocsToAdd.cardBlocType) {
                            newBlocs.cardBlocType = blocsToAdd.cardBlocType;
                        }
                        blocsToAdd.items.forEach(function (bloc) {
                            newBloc = {
                                label: bloc.label,
                                icon: bloc.icon,
                                value: monitoredBlocs.data[data.id][bloc.id],
                                formatter: eval("(" + bloc.formatter + ")"),
                                do: eval("(" + bloc.do + ")")
                            };
                            newBlocs.items.push(newBloc);
                        });
                        blocs.push(newBlocs);
                    });
                }
                return blocs;
            },
            _getMonitoredData: function () {
                var dashboards = Y.namespace("Wegas.Config.Dashboards"), script;
                if (dashboards && this.get("name") && dashboards[this.get("name")]) {
                    script = dashboards[this.get("name")];
                    return new Y.Promise(function (resolve, reject) {
                        Y.Wegas.Facade.Variable.sendRequest({
                            request: "/Script/Run/" + Y.Wegas.Facade.Game.cache.getCurrentPlayer().get("id"),
                            cfg: {
                                method: "POST",
                                headers: {
                                    "Managed-Mode": false
                                },
                                data: {
                                    "@class": "Script",
                                    content: script
                                }
                            },
                            on: {
                                success: function (e) {
                                    resolve(e.response.results);
                                },
                                failure: reject
                            }
                        });
                    });
                } else {
                    return Y.Promise.resolve(null);
                }
            },
            // Centers button/titles if possible, otherwise hides them or reduces them inside their columns.
            _adjustTitles: function () {
                var cb = this.get(CONTENTBOX),
                    card = cb.one(".card"); // We pick just any card
                if (!card){
                    return;
                }
                var monitoringBloc = card.one(".card__blocs--monitoring"),
                    toolbar = cb.get("parentNode").one(".wegas-toolbar"),
                    monitorTitle = toolbar.one(".monitoredDataTitle");
                if (monitoringBloc) {
                    if (monitoringBloc.getY() === card.one(".card__blocs--action").getY()) {
                        // Horizontal space is sufficient:
                        monitorTitle.set("offsetWidth", monitoringBloc.get("offsetWidth") - 2); // Subtract a few pixels for vertical alignment despite borders etc.
                    } else {
                        // Set to minimal width when monitoring and action blocs are misaligned due to lack of horizontal space
                        monitorTitle.setStyle("width", "auto");
                    }
                } else {
                    // Hide monitoring title when there is no monitoring bloc
                    monitorTitle.hide();
                }
            },
            _checkToolbarResize: function () {
                var ctx = this,
                    resizeTimer = null;
                this.resizeHandle = Y.on("windowresize", function () { // use "windowresize" instead of just "resize"
                    clearTimeout(resizeTimer);
                    resizeTimer = setTimeout(function() {
                        ctx._adjustTitles();
                    }, 10);
                });
            },

        },
        {
            "ATTRS": {
                "name": {
                    value: null
                },
                "cardsData": {
                    value: []
                },
                "resize": {
                    value: true
                },
                "quickAccess": {
                    value: null
                },
                "originalBlocs": {
                    value: {}
                }
            }
        });
}, 'V1.0', {
    requires: ['event','event-resize']
});
<commit_msg>Layout correction for monitoring title<commit_after>/*
 * Wegas
 * http://wegas.albasim.ch
 *
 * Copyright (c) 2015 School of Business and Engineering Vaud, Comem
 * Licensed under the MIT License
 */
/**
 * Wegas Dashboard - V2
 * @author Raphaël Schmutz <raph@hat-owl.cc>
 */
YUI.add('wegas-dashboard', function (Y) {
    "use strict";
    var CONTENTBOX = "contentBox";

    Y.Wegas.Dashboard = Y.Base.create("wegas-dashboard",
        Y.Widget,
        [Y.WidgetParent, Y.WidgetChild, Y.Wegas.Widget, Y.Wegas.Editable], {
            CONTENT_TEMPLATE: "

",
            initializer: function () {
                var context = this;
                context.get("cardsData").forEach(function (data) {
                    if (data.blocs && data.blocs.length > 0) {
                        context.get("cardsData").blocs.forEach(function (bloc) {
                            context._addOriginalBloc(data.id, bloc);
                        });
                    }
                });
                this.handlers = [];
            },
            destructor: function () {
                var i;
                for (i = 0; i < this.handlers.length; i += 1) {
                    this.handlers[i].detach();
                }
            },
            renderUI: function () {
                if (this.toolbar) {
                    this.toolbar.removeAll();

                    var game = Y.Wegas.Facade.Game.cache.getCurrentGame(),
                        teams = game.get("teams");

                    if (teams.length===0 || teams.length===1 && teams[0].get("@class")==="DebugTeam"){
                        this.toolbar.add(new Y.Wegas.Button({
                            label: 'No players have joined yet: click to check for new players',
                            cssClass: 'globalRefreshTitle',
                            on: {
                                click: Y.bind(function (event) {
                                    location.reload(); // That's stupid, same as {@see phenixize}
                                }, this)
                            }
                        }));
                        return;
                    }

                    this.toolbar.add(new Y.Wegas.Button({
                        label: 'Check for new players',
                        cssClass: 'globalRefreshTitle',
                        on: {
                            click: Y.bind(function (event) {
                                location.reload(); // That's stupid, same as {@see phenixize}
                            }, this)
                        }
                    }));

                    this.toolbar.add(new Y.Wegas.Button({
                        label: '',
                        cssClass: 'globalImpacts mailButton',
                        on: {
                            click: Y.bind(function (event) {
                                new Y.Wegas.EmailTeamModal({
                                    "team": game,
                                    "on": {
                                        "email:sent": function() {
                                            this.close();
                                        }
                                    }
                                }).render();
                            }, this)
                        },
                        tooltip: 'Send real E-mail to all players'
                    }));

                    this.toolbar.add(new Y.Wegas.Button({
                        label: '',
                        cssClass: 'globalImpacts impactButton',
                        on: {
                            click: Y.bind(function (event) {
                                new Y.Wegas.ImpactsTeamModal({
                                    "team": game
                                }).render();
                            }, this)
                        },
                        tooltip: 'Impact all players'
                    }));

                    this.toolbar.add(new Y.Wegas.Button({
                        label: 'Monitoring',
                        cssClass: 'globalImpacts monitoredDataTitle',
                        on: {
                            click: Y.bind(function (event) {
                                var button = event.target;
                                //this.phenixize();
                                if (button.get("boundingBox").hasClass("loading")) {
                                    return;
                                }
                                button.get("boundingBox").addClass("loading");
                                this.syncUI().then(function () {
                                    button.get("boundingBox").removeClass("loading");
                                });
                            }, this)
                        }
                    }));

                    this._checkToolbarResize();

                }
            },
            bindUI: function () {
                this.handlers.push(Y.Wegas.Facade.Game.after("update", this.phenixize, this));
            },
            /**
             * BEURK... Dirty Solution
             * @todo replace fuckin dirty clone'n'suicide pattern with slightly more intelligent sync
             * @returns {undefined}
             */
            phenixize: function () {
                return;
                var parent, childIndex,
                    cfg = {
                        "name": "overview",
                        "type": "TeamsOverviewDashboard",
                        "remoteScript": "",
                        "plugins": [
                            {
                                "fn": "WidgetToolbar"
                            }
                        ]
                    };

                parent = this.get("parent");
                if (parent) {
                    childIndex = parent.indexOf(this);
                    if (childIndex >= 0) {
                        parent.remove(childIndex);
                    }
                    parent.add(Y.Wegas.Widget.create(cfg));
                    if (childIndex >= 0) {
                        this.destroy();
                    }
                }
            },
            syncUI: function () {
                var BB = this.get("boundingBox");
                BB.addClass("loading");
                return this._createCards().then(function (data) {
                    BB.removeClass("loading");
                    return data;
                });
            },
            getMonitoredData: function () {
                return this._monitoredData || {};
            },

            /**
             *
             * create cards as child
             * return Promise-> cardsData
             */
            _createCards: function () {
                return this._getMonitoredData().then(Y.bind(function (monitoredBlocs) {
                    this.destroyAll();
                    this._monitoredData = monitoredBlocs;
                    Y.Array.each(this.get("cardsData"), function (data) {
                        var card = {
                            "id": data.id,
                            "title": data.title,
                            "icon": data.icon || null,
                            "blocs": this._combineBlocs(data, monitoredBlocs)
                        };
                        this.add(new Y.Wegas.Card(card));
                    }, this);
                    try {
                        if (this.get("resize")) {
                            this.plug(Y.Wegas.CardsResizable);
                            this.CardsResizable.resetClassSize();
                            this.CardsResizable.resize();
                        }
                    } catch (e) {
                    } finally {
                        this._adjustTitles();
                        this.get("boundingBox").removeClass("loading");
                        return this.get("cardsData");
                    }
                }, this));
            },
            _addOriginalBloc: function (idCard, originalBloc) {
                var originalBlocs = this.get("originalBlocs");
                if (!originalBlocs[idCard]) {
                    originalBlocs[idCard] = [];
                }
                originalBlocs[idCard].push(originalBloc);
                this.set("originalBlocs", originalBlocs);
            },
            _resetToInitialBlocs: function (data) {
                var originalBlocs = this.get("originalBlocs");
                data.blocs = [];
                if (originalBlocs[data.id]) {
                    originalBlocs[data.id].forEach(function (bloc) {
                        data.blocs.push(bloc);
                    });
                }
            },
            _combineBlocs: function (data, monitoredBlocs) {
                var blocs, newBlocs, newBloc;
                this._resetToInitialBlocs(data);
                blocs = data.blocs;
                if (monitoredBlocs !== null && monitoredBlocs.data && monitoredBlocs.data[data.id]) {
                    monitoredBlocs.structure.forEach(function (blocsToAdd) {
                        newBlocs = {
                            "position": "left",
                            "cardBlocType": "monitoring",
                            "items": []
                        };
                        if (blocsToAdd.title) {
                            newBlocs.title = blocsToAdd.title;
                        }
                        if (blocsToAdd.cardBlocType) {
                            newBlocs.cardBlocType = blocsToAdd.cardBlocType;
                        }
                        blocsToAdd.items.forEach(function (bloc) {
                            newBloc = {
                                label: bloc.label,
                                icon: bloc.icon,
                                value: monitoredBlocs.data[data.id][bloc.id],
                                formatter: eval("(" + bloc.formatter + ")"),
                                do: eval("(" + bloc.do + ")")
                            };
                            newBlocs.items.push(newBloc);
                        });
                        blocs.push(newBlocs);
                    });
                }
                return blocs;
            },
            _getMonitoredData: function () {
                var dashboards = Y.namespace("Wegas.Config.Dashboards"), script;
                if (dashboards && this.get("name") && dashboards[this.get("name")]) {
                    script = dashboards[this.get("name")];
                    return new Y.Promise(function (resolve, reject) {
                        Y.Wegas.Facade.Variable.sendRequest({
                            request: "/Script/Run/" + Y.Wegas.Facade.Game.cache.getCurrentPlayer().get("id"),
                            cfg: {
                                method: "POST",
                                headers: {
                                    "Managed-Mode": false
                                },
                                data: {
                                    "@class": "Script",
                                    content: script
                                }
                            },
                            on: {
                                success: function (e) {
                                    resolve(e.response.results);
                                },
                                failure: reject
                            }
                        });
                    });
                } else {
                    return Y.Promise.resolve(null);
                }
            },
            // Centers button/titles if possible, otherwise hides them or reduces them inside their columns.
            _adjustTitles: function () {
                var cb = this.get(CONTENTBOX),
                    card = cb.one(".card"); // We pick just any card
                if (!card){
                    return;
                }
                var monitoringBloc = card.one(".card__blocs--monitoring"),
                    toolbar = cb.get("parentNode").one(".wegas-toolbar"),
                    monitorTitle = toolbar.one(".monitoredDataTitle");
                if (monitoringBloc) {
                    if (monitoringBloc.getY() === card.one(".card__blocs--action").getY()) {
                        // Horizontal space is sufficient:
                        monitorTitle.set("offsetWidth", monitoringBloc.get("offsetWidth") - 2); // Subtract a few pixels for vertical alignment despite borders etc.
                    } else {
                        // Set to minimal width when monitoring and action blocs are misaligned due to lack of horizontal space
                        monitorTitle.setStyle("width", "auto");
                    }
                    monitorTitle.show();
                } else {
                    // Hide monitoring title when there is no monitoring bloc
                    monitorTitle.hide();
                }
            },
            _checkToolbarResize: function () {
                var ctx = this,
                    resizeTimer = null;
                this.resizeHandle = Y.on("windowresize", function () { // use "windowresize" instead of just "resize"
                    clearTimeout(resizeTimer);
                    resizeTimer = setTimeout(function() {
                        ctx._adjustTitles();
                    }, 10);
                });
            }

        },
        {
            "ATTRS": {
                "name": {
                    value: null
                },
                "cardsData": {
                    value: []
                },
                "resize": {
                    value: true
                },
                "quickAccess": {
                    value: null
                },
                "originalBlocs": {
                    value: {}
                }
            }
        });
}, 'V1.0', {
    requires: ['event','event-resize']
});
<|endoftext|>


<commit_before>/* Modules */
require("dotenv").config({silent: true}); // Load configuration variables
var http = require("http");
var express = require("express");
var bodyParser = require("body-parser");
var compression = require("compression");
var favicon = require("serve-favicon");
var morgan = require("morgan");
var request = require("request");
var ProtoBuf = require("protobufjs");
var WebSocketServer = require("ws").Server;
var db = require("./db").db;

/* App instantiation */
var app = express();
//var urlencodedParser = bodyParser.urlencoded({extended: false, limit: '50mb'}); // Parses application/x-www-form-urlencoded
var jsonParser = bodyParser.json({limit: '50mb'}); // Parses application/json
app.use(compression()); // Compress all requests
app.use(favicon(__dirname + "/public/favicon.ico")); // Deal with favicon requests
app.use(express.static(__dirname + "/public", {index: false, maxAge: '1d'})); // Static directory
app.set("view engine", "jade"); // Jade template engine
app.use(morgan("tiny")); // Log requests

/* Routes */

// Get collection for all API endpoints
app.param("collection", function(req, res, next, collection) {
  req.collection = db.collection(collection);
  return next();
});

// Return all entries
app.get("/api/:collection", function(req, res, next) {
  req.collection.find({}, {sort: [["timestamp", 1]]}).toArrayAsync()
  .then(function(results) {
    res.send(results);
  })
  .catch(function(err) {
    next(err);
  });
});

// Create new entry
app.post("/api/:collection", jsonParser, function(req, res, next) {
  req.collection.insertAsync(req.body, {})
  .then(function(results) {
    res.send(results[0]);
  })
  .catch(function(err) {
    next(err);
  });
});

// Return single entry
app.get("/api/:collection/:id", function(req, res, next) {
  req.collection.findByIdAsync(req.params.id)
  .then(function(result) {
    res.send(result);
  })
  .catch(function(err) {
    next(err);
  });
});

// Update existing entry
app.put("/api/:collection/:id", jsonParser, function(req, res, next) {
  delete req.body._id; // Delete ID (will not update otherwise)
  req.collection.updateByIdAsync(req.params.id, {$set: req.body}, {safe: true, multi: false})
  .then(function(result) {
    // Update returns the count of affected objects
    res.send((result === 1) ? {msg: "success"} : {msg : "error"});
  })
  .catch(function(err) {
    next(err);
  });
});

// Delete existing entry
app.delete("/api/:collection/:id", function(req, res, next) {
  req.collection.removeByIdAsync(req.params.id)
  .then(function(result) {
    // Remove returns the count of affected objects
    res.send((result === 1) ? {msg: "success"} : {msg : "error"});
  })
  .catch(function(err) {
    next(err);
  });
});

// List projects and machines on homepage
app.get("/", function(req, res, next) {
  // TODO Promisify better
  db.projects.find({}, {sort: [["name", -1]]}).toArray(function(err, projRes) {
    if (err) {
      return next(err);
    }
    db.machines.find({}, {sort: [["hostname", -1]]}).toArrayAsync()
    .then(function(macRes) {
      return res.render("index", {projects: projRes, machines: macRes});
    })
    .catch(function(err) {
      return next(err);
    });
  });
});

// Gets HTML form input type for proto types
var getFormType = function(type) {
  if (type === "double" || type === "float" || type === "int32" || type === "int64" || type === "uint32" || type === "uint64" || type === "sint32" || type === "sint64" || type === "fixed32" || type === "fixed64" || type === "sfixed32" || type === "sfixed64") {
    return "number";
  } else if (type === "bool" || type === "string" || type === "bytes") {
    return "text";
  } else if (type === "enum") {
    return "select";
  } else if (type === "message") {
    return "fieldset";
  }
};

// Processes fields recursively
var procFields = function(builder, name, formFields) {
  // Use reflection
  var reflector = builder.lookup(name);
  var fields = reflector.getChildren(ProtoBuf.Reflect.Message.Field);

  while (fields.length !== 0) {
    var field = fields.shift(); // Get first field
    var fieldObj = {
      name: field.name,
      type: getFormType(field.type.name)
    };
    // Process enums
    if (fieldObj.type === "select") {
      var enums = field.resolvedType.children;
      var enumVals = [];
      enums.forEach(function(enumObj) {
        enumVals.push(enumObj.name);
      });
      fieldObj.values = enumVals;
    }
    // Process messages recursively
    if (fieldObj.type === "fieldset") {
      var messageName = field.resolvedType.name;
      procFields(builder, name + "." + messageName, formFields);
    } else {
      formFields.push(fieldObj);
    }
  }
  return formFields;
};

// Project page
app.get("/projects/:id", function(req, res, next) {
  db.projects.findByIdAsync(req.params.id)
  .then(function(result) {
    var builder = ProtoBuf.loadProto(result.proto);
    // Use reflection to construct form
    var formFields = procFields(builder, result.name, []);
    //var Project = processProto(result.name, result.proto);
    //var p = new Project();
    res.render("project", {project: result, form: formFields});
  })
  .catch(function(err) {
    next(err);
  });
});

// List experiments
app.get("/experiments", function(req, res, next) {
  db.experiments.find({}, {sort: [["timestamp", 1]]}).toArrayAsync()
  .then(function(results) {
    res.render("experiments", {experiments: results});
  })
  .catch(function(err) {
    next(err);
  });
});

// List details of single experiment
app.get("/experiments/:id", function(req, res, next) {
  db.experiments.findByIdAsync(req.params.id)
  .then(function(result) {
    res.render("experiment", {experiment: result});
  })
  .catch(function(err) {
    next(err);
  });
});

// Show live logs
app.get("/logs", function(req, res) {
  res.render("logs", {title: "FGLab"});
});

/* Errors */
// Error handler
app.use(function(err, req, res, next) {
  if (res.headersSent) {
    return next(err); // Delegate to Express' default error handling
  }
  res.status(500);
  res.send("Error: " + err);
});

/* HTTP server */
var server = http.createServer(app); // Create HTTP server
server.listen(process.env.PORT); // Listen for connections

/* WebSocket server */
// Add websocket server
/*
var wss = new WebSocketServer({server: server});

// Call on connection from new client
wss.on("connection", function(ws) {
  console.log("Client opened connection");

  // Send one message
  ws.send("Connected to server");

  // Print received messages
  ws.on("message", function(message) {
    console.log(message);
  });

  // Perform clean up if necessary
  ws.on("close", function() {
    console.log("Client closed connection");
  });
});
*/
<commit_msg>Use Promisify.all<commit_after>/* Modules */
require("dotenv").config({silent: true}); // Load configuration variables
var http = require("http");
var express = require("express");
var bodyParser = require("body-parser");
var compression = require("compression");
var favicon = require("serve-favicon");
var morgan = require("morgan");
var request = require("request");
var ProtoBuf = require("protobufjs");
var WebSocketServer = require("ws").Server;
var db = require("./db").db;

/* App instantiation */
var app = express();
//var urlencodedParser = bodyParser.urlencoded({extended: false, limit: '50mb'}); // Parses application/x-www-form-urlencoded
var jsonParser = bodyParser.json({limit: '50mb'}); // Parses application/json
app.use(compression()); // Compress all requests
app.use(favicon(__dirname + "/public/favicon.ico")); // Deal with favicon requests
app.use(express.static(__dirname + "/public", {index: false, maxAge: '1d'})); // Static directory
app.set("view engine", "jade"); // Jade template engine
app.use(morgan("tiny")); // Log requests

/* Routes */

// Get collection for all API endpoints
app.param("collection", function(req, res, next, collection) {
  req.collection = db.collection(collection);
  return next();
});

// Return all entries
app.get("/api/:collection", function(req, res, next) {
  req.collection.find({}, {sort: [["timestamp", 1]]}).toArrayAsync()
  .then(function(results) {
    res.send(results);
  })
  .catch(function(err) {
    next(err);
  });
});

// Create new entry
app.post("/api/:collection", jsonParser, function(req, res, next) {
  req.collection.insertAsync(req.body, {})
  .then(function(results) {
    res.send(results[0]);
  })
  .catch(function(err) {
    next(err);
  });
});

// Return single entry
app.get("/api/:collection/:id", function(req, res, next) {
  req.collection.findByIdAsync(req.params.id)
  .then(function(result) {
    res.send(result);
  })
  .catch(function(err) {
    next(err);
  });
});

// Update existing entry
app.put("/api/:collection/:id", jsonParser, function(req, res, next) {
  delete req.body._id; // Delete ID (will not update otherwise)
  req.collection.updateByIdAsync(req.params.id, {$set: req.body}, {safe: true, multi: false})
  .then(function(result) {
    // Update returns the count of affected objects
    res.send((result === 1) ? {msg: "success"} : {msg : "error"});
  })
  .catch(function(err) {
    next(err);
  });
});

// Delete existing entry
app.delete("/api/:collection/:id", function(req, res, next) {
  req.collection.removeByIdAsync(req.params.id)
  .then(function(result) {
    // Remove returns the count of affected objects
    res.send((result === 1) ? {msg: "success"} : {msg : "error"});
  })
  .catch(function(err) {
    next(err);
  });
});

// List projects and machines on homepage
app.get("/", function(req, res, next) {
  var projP = db.projects.find({}, {sort: [["name", -1]]}).toArrayAsync();
  var macP = db.machines.find({}, {sort: [["hostname", -1]]}).toArrayAsync();
  Promise.all([projP, macP])
  .then(function(results) {
    return res.render("index", {projects: results[0], machines: results[1]});
  })
  .catch(function(err) {
    return next(err);
  });
});

// Gets HTML form input type for proto types
var getFormType = function(type) {
  if (type === "double" || type === "float" || type === "int32" || type === "int64" || type === "uint32" || type === "uint64" || type === "sint32" || type === "sint64" || type === "fixed32" || type === "fixed64" || type === "sfixed32" || type === "sfixed64") {
    return "number";
  } else if (type === "bool" || type === "string" || type === "bytes") {
    return "text";
  } else if (type === "enum") {
    return "select";
  } else if (type === "message") {
    return "fieldset";
  }
};

// Processes fields recursively
var procFields = function(builder, name, formFields) {
  // Use reflection
  var reflector = builder.lookup(name);
  var fields = reflector.getChildren(ProtoBuf.Reflect.Message.Field);

  while (fields.length !== 0) {
    var field = fields.shift(); // Get first field
    var fieldObj = {
      name: field.name,
      type: getFormType(field.type.name)
    };
    // Process enums
    if (fieldObj.type === "select") {
      var enums = field.resolvedType.children;
      var enumVals = [];
      enums.forEach(function(enumObj) {
        enumVals.push(enumObj.name);
      });
      fieldObj.values = enumVals;
    }
    // Process messages recursively
    if (fieldObj.type === "fieldset") {
      var messageName = field.resolvedType.name;
      procFields(builder, name + "." + messageName, formFields);
    } else {
      formFields.push(fieldObj);
    }
  }
  return formFields;
};

// Project page
app.get("/projects/:id", function(req, res, next) {
  db.projects.findByIdAsync(req.params.id)
  .then(function(result) {
    var builder = ProtoBuf.loadProto(result.proto);
    // Use reflection to construct form
    var formFields = procFields(builder, result.name, []);
    //var Project = processProto(result.name, result.proto);
    //var p = new Project();
    res.render("project", {project: result, form: formFields});
  })
  .catch(function(err) {
    next(err);
  });
});

// List experiments
app.get("/experiments", function(req, res, next) {
  db.experiments.find({}, {sort: [["timestamp", 1]]}).toArrayAsync()
  .then(function(results) {
    res.render("experiments", {experiments: results});
  })
  .catch(function(err) {
    next(err);
  });
});

// List details of single experiment
app.get("/experiments/:id", function(req, res, next) {
  db.experiments.findByIdAsync(req.params.id)
  .then(function(result) {
    res.render("experiment", {experiment: result});
  })
  .catch(function(err) {
    next(err);
  });
});

// Show live logs
app.get("/logs", function(req, res) {
  res.render("logs", {title: "FGLab"});
});

/* Errors */
// Error handler
app.use(function(err, req, res, next) {
  if (res.headersSent) {
    return next(err); // Delegate to Express' default error handling
  }
  res.status(500);
  res.send("Error: " + err);
});

/* HTTP server */
var server = http.createServer(app); // Create HTTP server
server.listen(process.env.PORT); // Listen for connections

/* WebSocket server */
// Add websocket server
/*
var wss = new WebSocketServer({server: server});

// Call on connection from new client
wss.on("connection", function(ws) {
  console.log("Client opened connection");

  // Send one message
  ws.send("Connected to server");

  // Print received messages
  ws.on("message", function(message) {
    console.log(message);
  });

  // Perform clean up if necessary
  ws.on("close", function() {
    console.log("Client closed connection");
  });
});
*/
<|endoftext|>


<commit_before>module.exports = IdbKvStore

var scope = typeof window === 'undefined' ? self : window // eslint-disable-line
var IDB = scope.indexedDB || scope.mozIndexedDB || scope.webkitIndexedDB || scope.msIndexedDB

function IdbKvStore (name, cb) {
  var self = this
  if (typeof name !== 'string') throw new Error('A name must be supplied of type string')
  if (!IDB) throw new Error('IndexedDb not supported')
  if (!(this instanceof IdbKvStore)) return new IdbKvStore(name, cb)

  self._db = null
  self._closed = false
  self._queue = []

  var request = IDB.open(name)

  request.onerror = function (event) {
    self.close()
    onerror(event, cb)
  }

  request.onsuccess = function (event) {
    if (self._closed) return
    self._db = event.target.result
    self._drainQueue()
    if (cb) cb(null)
  }

  request.onupgradeneeded = function (event) {
    if (self._closed) return
    var db = event.target.result
    db.createObjectStore('kv')
  }
}

IdbKvStore.prototype.get = function (key, cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.get, key, defer.cb])
  } else if (Array.isArray(key)) {
    var result = []
    var erroredOut = false
    var successes = 0
    key.forEach(function (_, index) {
      self.get(key[index], function (err, val) {
        if (erroredOut) return
        if (err) {
          erroredOut = true
          defer.cb(err)
        }
        result[index] = val
        successes++
        if (successes === key.length) defer.cb(null, result)
      })
    })
  } else {
    var transaction = self._db.transaction('kv', 'readonly')
    var request = transaction.objectStore('kv').get(key)

    request.onsuccess = function (event) {
      defer.cb(null, event.target.result)
    }

    transaction.onerror = function (event) {
      onerror(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.set = function (key, value, cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.set, key, value, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readwrite')
    var request = transaction.objectStore('kv').put(value, key)

    request.onsuccess = function () {
      defer.cb(null)
    }

    transaction.onerror = function (event) {
      onerror(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.json = function (cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.json, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readonly')
    var request = transaction.objectStore('kv').openCursor()

    var json = {}
    request.onsuccess = function (event) {
      var cursor = event.target.result
      if (cursor) {
        json[cursor.key] = cursor.value
        cursor.continue()
      } else {
        defer.cb(null, json)
      }
    }

    transaction.onerror = function (event) {
      onerror(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.keys = function (cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.keys, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readonly')
    var request = transaction.objectStore('kv').openCursor()

    var keys = []
    request.onsuccess = function (event) {
      var cursor = event.target.result
      if (cursor) {
        keys.push(cursor.key)
        cursor.continue()
      } else {
        defer.cb(null, keys)
      }
    }

    transaction.onerror = function (event) {
      onerror(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.remove = function (key, cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.remove, key, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readwrite')
    var request = transaction.objectStore('kv').delete(key)

    request.onsuccess = function (event) {
      defer.cb(null)
    }

    transaction.onerror = function (event) {
      onerror(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.clear = function (cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.clear, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readwrite')
    var request = transaction.objectStore('kv').clear()

    request.onsuccess = function (event) {
      defer.cb(null)
    }

    transaction.onerror = function (event) {
      onerror(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.count = function (cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.count, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readonly')
    var request = transaction.objectStore('kv').count()

    request.onsuccess = function (event) {
      defer.cb(null, event.target.result)
    }

    transaction.onerror = function (event) {
      onerror(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.add = function (key, value, cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.add, key, value, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readwrite')
    var request = transaction.objectStore('kv').add(value, key)

    request.onsuccess = function (event) {
      defer.cb(null)
    }

    transaction.onerror = function (event) {
      onerror(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.close = function () {
  if (this._closed) return
  this._closed = true
  if (this._db) this._db.close()
  this._queue = null
}

IdbKvStore.prototype._drainQueue = function () {
  var self = this
  for (var i = 0; i < self._queue.length; i++) {
    var item = self._queue[i]
    var args = item.splice(1)
    item[0].apply(self, args)
  }
  self._queue = null
}

function promisify (cb) {
  var defer = {cb: cb}

  if (typeof Promise === 'function' && cb == null) {
    defer.promise = new Promise(function (resolve, reject) {
      defer.cb = function (err, result) {
        if (err) return reject(err)
        else return resolve(result)
      }
    })
  }

  if (!defer.cb) defer.cb = function noop () {}

  return defer
}

function onerror (event, cb) {
  var err = new Error('IDB error')
  err.event = event

  if (cb) {
    cb(err)
  } else {
    throw err
  }
}
<commit_msg>Handling IDB close event<commit_after>module.exports = IdbKvStore

var scope = typeof window === 'undefined' ? self : window // eslint-disable-line
var IDB = scope.indexedDB || scope.mozIndexedDB || scope.webkitIndexedDB || scope.msIndexedDB

function IdbKvStore (name, cb) {
  var self = this
  if (typeof name !== 'string') throw new Error('A name must be supplied of type string')
  if (!IDB) throw new Error('IndexedDb not supported')
  if (!(this instanceof IdbKvStore)) return new IdbKvStore(name, cb)

  self._db = null
  self._closed = false
  self._queue = []

  var request = IDB.open(name)
  request.onerror = onerror
  request.onsuccess = onsuccess
  request.onupgradeneeded = onupgradeneeded

  function onerror (event) {
    self.close()
    handleError(event, cb)
  }

  function onsuccess (event) {
    if (self._closed) {
      event.target.result.close()
    } else {
      self._db = event.target.result
      self._db.onclose = onclose
      self._drainQueue()
      if (cb) cb(null)
    }
  }

  function onupgradeneeded (event) {
    if (self._closed) return
    var db = event.target.result
    db.createObjectStore('kv')
  }

  function onclose () {
    self.close()
  }
}

IdbKvStore.prototype.get = function (key, cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.get, key, defer.cb])
  } else if (Array.isArray(key)) {
    var result = []
    var erroredOut = false
    var successes = 0
    key.forEach(function (_, index) {
      self.get(key[index], function (err, val) {
        if (erroredOut) return
        if (err) {
          erroredOut = true
          defer.cb(err)
        }
        result[index] = val
        successes++
        if (successes === key.length) defer.cb(null, result)
      })
    })
  } else {
    var transaction = self._db.transaction('kv', 'readonly')
    var request = transaction.objectStore('kv').get(key)

    request.onsuccess = function (event) {
      defer.cb(null, event.target.result)
    }

    transaction.onerror = function (event) {
      handleError(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.set = function (key, value, cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.set, key, value, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readwrite')
    var request = transaction.objectStore('kv').put(value, key)

    request.onsuccess = function () {
      defer.cb(null)
    }

    transaction.onerror = function (event) {
      handleError(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.json = function (cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.json, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readonly')
    var request = transaction.objectStore('kv').openCursor()

    var json = {}
    request.onsuccess = function (event) {
      var cursor = event.target.result
      if (cursor) {
        json[cursor.key] = cursor.value
        cursor.continue()
      } else {
        defer.cb(null, json)
      }
    }

    transaction.onerror = function (event) {
      handleError(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.keys = function (cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.keys, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readonly')
    var request = transaction.objectStore('kv').openCursor()

    var keys = []
    request.onsuccess = function (event) {
      var cursor = event.target.result
      if (cursor) {
        keys.push(cursor.key)
        cursor.continue()
      } else {
        defer.cb(null, keys)
      }
    }

    transaction.onerror = function (event) {
      handleError(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.remove = function (key, cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.remove, key, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readwrite')
    var request = transaction.objectStore('kv').delete(key)

    request.onsuccess = function (event) {
      defer.cb(null)
    }

    transaction.onerror = function (event) {
      handleError(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.clear = function (cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.clear, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readwrite')
    var request = transaction.objectStore('kv').clear()

    request.onsuccess = function (event) {
      defer.cb(null)
    }

    transaction.onerror = function (event) {
      handleError(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.count = function (cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.count, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readonly')
    var request = transaction.objectStore('kv').count()

    request.onsuccess = function (event) {
      defer.cb(null, event.target.result)
    }

    transaction.onerror = function (event) {
      handleError(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.add = function (key, value, cb) {
  var self = this
  if (self._closed) throw new Error('Database is closed')
  var defer = promisify(cb)

  if (!self._db) {
    self._queue.push([self.add, key, value, defer.cb])
  } else {
    var transaction = self._db.transaction('kv', 'readwrite')
    var request = transaction.objectStore('kv').add(value, key)

    request.onsuccess = function (event) {
      defer.cb(null)
    }

    transaction.onerror = function (event) {
      handleError(event, defer.cb)
    }
  }

  return defer.promise
}

IdbKvStore.prototype.close = function () {
  if (this._closed) return
  this._closed = true
  if (this._db) this._db.close()
  this._queue = null
}

IdbKvStore.prototype._drainQueue = function () {
  var self = this
  for (var i = 0; i < self._queue.length; i++) {
    var item = self._queue[i]
    var args = item.splice(1)
    item[0].apply(self, args)
  }
  self._queue = null
}

function promisify (cb) {
  var defer = {cb: cb}

  if (typeof Promise === 'function' && cb == null) {
    defer.promise = new Promise(function (resolve, reject) {
      defer.cb = function (err, result) {
        if (err) return reject(err)
        else return resolve(result)
      }
    })
  }

  if (!defer.cb) defer.cb = function noop () {}

  return defer
}

function handleError (event, cb) {
  var err = new Error('IDB error')
  err.event = event

  if (cb) {
    cb(err)
  } else {
    throw err
  }
}
<|endoftext|>


<commit_before>// (Any) => Any
var _ = function (x) { return x }

// collection fns
// (String, Any) => Object
_.pair = function (key, val) {
  var o = {}
  o[key] = val
  return o
}

// (Object, String) => Boolean
_.contains = function (obj, key) {
  for (var k in obj) {
    if (k === key) {
      return true
    }
  }
  return false
}

// quantifiers

// type Predicate : (value: Any, key?: String) => Boolean

// (Object, Predicate) => Boolean
_.some = function (obj, predicate) {
  predicate = predicate || function () { return true }
  for (var k in obj) {
    if (predicate(obj[k], k)) {
      return true
    }
  }
  return false
}

// (Object, Predicate) => Boolean
_.every = function (obj, predicate) {
  for (var k in obj) {
    if (!predicate(obj[k], k)) {
      return false
    }
  }
  return true
}

// collection

// (Object, Predicate?) => Int
_.count = function (obj, predicate) {
  if (typeof predicate !== 'function') {
    return Object.keys(obj).length
  }
  var c = 0
  for (var k in obj) {
    if (predicate(obj[k])) {
      c++
    }
  }
  return c
}

// (Object, Predicate) => Object
_.filter = function (obj, predicate) {
  var o = {}
  for (var k in obj) {
    if (predicate(obj[k])) {
      o[k] = obj[k]
    }
  }
  return o
}

// (Object, Function) => Object
_.forEach = function (obj, iterator) {
  for (var k in obj) {
    iterator(obj[k], k)
  }
  return obj
}

// algebraic fns

// (Object, (val: Any, key: String) => Any) => Object
_.map = function (obj, fn) {
  var o = {}
  for (var k in obj) {
    o[k] = fn(obj[k], k)
  }
  return o
}

// type Reducer : (accumulator: Any, val: Any, key: String) => Any

// (Object, Reducer, seed: Any) => Any
_.reduce = function (obj, fn, seed) {
  var val = seed || {}
  for (var k in obj) {
    val = fn(val, obj[k], k)
  }
  return val
}

// (Object, Object) => Object
_.concat = function (objA, objB) {
  for (var k in objB) {
    objA[k] = objB[k]
  }
  return objA
}

/* I might be doing this wrong:
 * this applies a function to each key-value pair in a dictionary
 * where the function is (Pair) => Array
 * and returns a flattened Array
 */
// (Object, Reducer) => Array
_.flatMap = function (obj, fn) {
  return _.reduce(obj, function (arr, val, key) {
    return arr.concat(fn(val, key))
  }, [])
}

module.exports = _<commit_msg>add generic functions _.eq and _.assert<commit_after>// (Any) => Any
var _ = function (x) { return x }

// collection fns
// (String, Any) => Object
_.pair = function (key, val) {
  var o = {}
  o[key] = val
  return o
}

// (Object, String) => Boolean
_.contains = function (obj, key) {
  for (var k in obj) {
    if (k === key) {
      return true
    }
  }
  return false
}

// quantifiers

// type Predicate : (value: Any, key?: String) => Boolean

// (Object, Predicate) => Boolean
_.some = function (obj, predicate) {
  predicate = predicate || function () { return true }
  for (var k in obj) {
    if (predicate(obj[k], k)) {
      return true
    }
  }
  return false
}

// (Object, Predicate) => Boolean
_.every = function (obj, predicate) {
  for (var k in obj) {
    if (!predicate(obj[k], k)) {
      return false
    }
  }
  return true
}

// collection

// (Object, Predicate?) => Int
_.count = function (obj, predicate) {
  if (typeof predicate !== 'function') {
    return Object.keys(obj).length
  }
  var c = 0
  for (var k in obj) {
    if (predicate(obj[k])) {
      c++
    }
  }
  return c
}

// (Object, Predicate) => Object
_.filter = function (obj, predicate) {
  var o = {}
  for (var k in obj) {
    if (predicate(obj[k])) {
      o[k] = obj[k]
    }
  }
  return o
}

// (Object, Function) => Object
_.forEach = function (obj, iterator) {
  for (var k in obj) {
    iterator(obj[k], k)
  }
  return obj
}

// algebraic fns

// (Object, (val: Any, key: String) => Any) => Object
_.map = function (obj, fn) {
  var o = {}
  for (var k in obj) {
    o[k] = fn(obj[k], k)
  }
  return o
}

// type Reducer : (accumulator: Any, val: Any, key: String) => Any

// (Object, Reducer, seed: Any) => Any
_.reduce = function (obj, fn, seed) {
  var val = seed || {}
  for (var k in obj) {
    val = fn(val, obj[k], k)
  }
  return val
}

// (Object, Object) => Object
_.concat = function (objA, objB) {
  for (var k in objB) {
    objA[k] = objB[k]
  }
  return objA
}

/* I might be doing this wrong:
 * this applies a function to each key-value pair in a dictionary
 * where the function is (Pair) => Array
 * and returns a flattened Array
 */
// (Object, Reducer) => Array
_.flatMap = function (obj, fn) {
  return _.reduce(obj, function (arr, val, key) {
    return arr.concat(fn(val, key))
  }, [])
}

// generic functions
// (Any, Any) => Boolean
_.eq = function (a, b) { return a === b }

// type Comparator : (Any, Any) => Boolean
// (Comparator, Any, Any) => void
// (Comparator, Any) => (Any) => void
// (Any, Any) => void
// (Any) => (Any) => void
// `fn` defaults to the Equality Comparator (_.eq)
// Optionally curries `val`
_.assert = function (fn, expect, val) {
  if (typeof fn !== 'function') {
    val = expect
    expect = fn
    fn = eq
  }
  if (val === undefined) {
    // return partially applied function
    return function (val) {
      return assert(fn, expect, val)
    }
  }
  if (!eq(expect, val)) {
    throw new Error('Assertion error', expect, val)
  }
}

module.exports = _<|endoftext|>


<commit_before>'use strict'

module.exports = [
  '0.0.1'
, '0.0.2'
, '0.0.3'
, '0.0.4'
, '0.0.5'
, '0.0.6'
, '0.1.0'
, '0.1.1'
, '0.1.2'
, '0.1.3'
, '0.1.4'
, '0.1.5'
, '0.1.6'
, '0.1.7'
, '0.1.8'
, '0.1.9'
, '0.1.10'
, '0.1.11'
, '0.1.12'
, '0.1.13'
, '0.1.14'
, '0.1.15'
, '0.1.16'
, '0.1.17'
, '0.1.18'
, '0.1.19'
, '0.1.20'
, '0.1.21'
, '0.1.22'
, '0.1.23'
, '0.1.24'
, '0.1.25'
, '0.1.26'
, '0.1.27'
, '0.1.28'
, '0.1.29'
, '0.1.30'
, '0.1.31'
, '0.1.32'
, '0.1.33'
, '0.1.90'
, '0.1.91'
, '0.1.92'
, '0.1.93'
, '0.1.94'
, '0.1.95'
, '0.1.96'
, '0.1.97'
, '0.1.98'
, '0.1.99'
, '0.1.100'
, '0.1.101'
, '0.1.102'
, '0.1.103'
, '0.1.104'
, '0.2.0'
, '0.2.1'
, '0.2.2'
, '0.2.3'
, '0.2.4'
, '0.2.5'
, '0.2.6'
, '0.3.0'
, '0.3.1'
, '0.3.2'
, '0.3.3'
, '0.3.4'
, '0.3.5'
, '0.3.6'
, '0.3.7'
, '0.3.8'
, '0.4.0'
, '0.4.1'
, '0.4.2'
, '0.4.3'
, '0.4.4'
, '0.4.5'
, '0.4.6'
, '0.4.7'
, '0.4.8'
, '0.4.9'
, '0.4.10'
, '0.4.11'
, '0.4.12'
, '0.5.0'
, '0.5.1'
, '0.5.2'
, '0.5.3'
, '0.5.4'
, '0.5.5'
, '0.5.6'
, '0.5.7'
, '0.5.8'
, '0.5.9'
, '0.5.10'
, '0.6.0'
, '0.6.1'
, '0.6.2'
, '0.6.3'
, '0.6.4'
, '0.6.5'
, '0.6.6'
, '0.6.7'
, '0.6.8'
, '0.6.9'
, '0.6.10'
, '0.6.11'
, '0.6.12'
, '0.6.13'
, '0.6.14'
, '0.6.15'
, '0.6.16'
, '0.6.17'
, '0.6.18'
, '0.6.19'
, '0.6.20'
, '0.6.21'
, '0.7.0'
, '0.7.1'
, '0.7.2'
, '0.7.3'
, '0.7.4'
, '0.7.5'
, '0.7.6'
, '0.7.7'
, '0.7.8'
, '0.7.9'
, '0.7.10'
, '0.7.11'
, '0.7.12'
, '0.8.0'
, '0.8.1'
, '0.8.2'
, '0.8.3'
, '0.8.4'
, '0.8.5'
, '0.8.6'
, '0.8.7'
, '0.8.8'
, '0.8.9'
, '0.8.10'
, '0.8.11'
, '0.8.12'
, '0.8.13'
, '0.8.14'
, '0.8.15'
, '0.8.16'
, '0.8.17'
, '0.8.18'
, '0.8.19'
, '0.8.20'
, '0.8.21'
, '0.8.22'
, '0.8.23'
, '0.8.24'
, '0.8.25'
, '0.8.26'
, '0.8.27'
, '0.8.28'
, '0.9.0'
, '0.9.1'
, '0.9.2'
, '0.9.3'
, '0.9.4'
, '0.9.5'
, '0.9.6'
, '0.9.7'
, '0.9.8'
, '0.9.9'
, '0.9.10'
, '0.9.11'
, '0.9.12'
, '0.10.0'
, '0.10.1'
, '0.10.2'
, '0.10.3'
, '0.10.4'
, '0.10.5'
, '0.10.6'
, '0.10.7'
, '0.10.8'
, '0.10.9'
, '0.10.10'
, '0.10.11'
, '0.10.12'
, '0.10.13'
, '0.10.14'
, '0.10.15'
, '0.10.16'
, '0.10.17'
, '0.10.18'
, '0.10.19'
, '0.10.20'
, '0.10.21'
, '0.10.22'
, '0.10.23'
, '0.10.24'
, '0.10.25'
, '0.10.26'
, '0.10.27'
, '0.10.28'
, '0.10.29'
, '0.10.30'
, '0.10.31'
, '0.10.32'
, '0.10.33'
, '0.10.34'
, '0.10.35'
, '0.10.36'
, '0.10.37'
, '0.10.38'
, '0.10.39'
, '0.10.40'
, '0.10.41'
, '0.10.42'
, '0.11.0'
, '0.11.1'
, '0.11.2'
, '0.11.3'
, '0.11.4'
, '0.11.5'
, '0.11.6'
, '0.11.7'
, '0.11.8'
, '0.11.9'
, '0.11.10'
, '0.11.11'
, '0.11.12'
, '0.11.13'
, '0.11.14'
, '0.11.15'
, '0.11.16'
, '0.12.0'
, '0.12.1'
, '0.12.2'
, '0.12.3'
, '0.12.4'
, '0.12.5'
, '0.12.6'
, '0.12.7'
, '0.12.8'
, '0.12.9'
, '0.12.10'
]
<commit_msg>add v0.10.43<commit_after>'use strict'

module.exports = [
  '0.0.1'
, '0.0.2'
, '0.0.3'
, '0.0.4'
, '0.0.5'
, '0.0.6'
, '0.1.0'
, '0.1.1'
, '0.1.2'
, '0.1.3'
, '0.1.4'
, '0.1.5'
, '0.1.6'
, '0.1.7'
, '0.1.8'
, '0.1.9'
, '0.1.10'
, '0.1.11'
, '0.1.12'
, '0.1.13'
, '0.1.14'
, '0.1.15'
, '0.1.16'
, '0.1.17'
, '0.1.18'
, '0.1.19'
, '0.1.20'
, '0.1.21'
, '0.1.22'
, '0.1.23'
, '0.1.24'
, '0.1.25'
, '0.1.26'
, '0.1.27'
, '0.1.28'
, '0.1.29'
, '0.1.30'
, '0.1.31'
, '0.1.32'
, '0.1.33'
, '0.1.90'
, '0.1.91'
, '0.1.92'
, '0.1.93'
, '0.1.94'
, '0.1.95'
, '0.1.96'
, '0.1.97'
, '0.1.98'
, '0.1.99'
, '0.1.100'
, '0.1.101'
, '0.1.102'
, '0.1.103'
, '0.1.104'
, '0.2.0'
, '0.2.1'
, '0.2.2'
, '0.2.3'
, '0.2.4'
, '0.2.5'
, '0.2.6'
, '0.3.0'
, '0.3.1'
, '0.3.2'
, '0.3.3'
, '0.3.4'
, '0.3.5'
, '0.3.6'
, '0.3.7'
, '0.3.8'
, '0.4.0'
, '0.4.1'
, '0.4.2'
, '0.4.3'
, '0.4.4'
, '0.4.5'
, '0.4.6'
, '0.4.7'
, '0.4.8'
, '0.4.9'
, '0.4.10'
, '0.4.11'
, '0.4.12'
, '0.5.0'
, '0.5.1'
, '0.5.2'
, '0.5.3'
, '0.5.4'
, '0.5.5'
, '0.5.6'
, '0.5.7'
, '0.5.8'
, '0.5.9'
, '0.5.10'
, '0.6.0'
, '0.6.1'
, '0.6.2'
, '0.6.3'
, '0.6.4'
, '0.6.5'
, '0.6.6'
, '0.6.7'
, '0.6.8'
, '0.6.9'
, '0.6.10'
, '0.6.11'
, '0.6.12'
, '0.6.13'
, '0.6.14'
, '0.6.15'
, '0.6.16'
, '0.6.17'
, '0.6.18'
, '0.6.19'
, '0.6.20'
, '0.6.21'
, '0.7.0'
, '0.7.1'
, '0.7.2'
, '0.7.3'
, '0.7.4'
, '0.7.5'
, '0.7.6'
, '0.7.7'
, '0.7.8'
, '0.7.9'
, '0.7.10'
, '0.7.11'
, '0.7.12'
, '0.8.0'
, '0.8.1'
, '0.8.2'
, '0.8.3'
, '0.8.4'
, '0.8.5'
, '0.8.6'
, '0.8.7'
, '0.8.8'
, '0.8.9'
, '0.8.10'
, '0.8.11'
, '0.8.12'
, '0.8.13'
, '0.8.14'
, '0.8.15'
, '0.8.16'
, '0.8.17'
, '0.8.18'
, '0.8.19'
, '0.8.20'
, '0.8.21'
, '0.8.22'
, '0.8.23'
, '0.8.24'
, '0.8.25'
, '0.8.26'
, '0.8.27'
, '0.8.28'
, '0.9.0'
, '0.9.1'
, '0.9.2'
, '0.9.3'
, '0.9.4'
, '0.9.5'
, '0.9.6'
, '0.9.7'
, '0.9.8'
, '0.9.9'
, '0.9.10'
, '0.9.11'
, '0.9.12'
, '0.10.0'
, '0.10.1'
, '0.10.2'
, '0.10.3'
, '0.10.4'
, '0.10.5'
, '0.10.6'
, '0.10.7'
, '0.10.8'
, '0.10.9'
, '0.10.10'
, '0.10.11'
, '0.10.12'
, '0.10.13'
, '0.10.14'
, '0.10.15'
, '0.10.16'
, '0.10.17'
, '0.10.18'
, '0.10.19'
, '0.10.20'
, '0.10.21'
, '0.10.22'
, '0.10.23'
, '0.10.24'
, '0.10.25'
, '0.10.26'
, '0.10.27'
, '0.10.28'
, '0.10.29'
, '0.10.30'
, '0.10.31'
, '0.10.32'
, '0.10.33'
, '0.10.34'
, '0.10.35'
, '0.10.36'
, '0.10.37'
, '0.10.38'
, '0.10.39'
, '0.10.40'
, '0.10.41'
, '0.10.42'
, '0.10.43'
, '0.11.0'
, '0.11.1'
, '0.11.2'
, '0.11.3'
, '0.11.4'
, '0.11.5'
, '0.11.6'
, '0.11.7'
, '0.11.8'
, '0.11.9'
, '0.11.10'
, '0.11.11'
, '0.11.12'
, '0.11.13'
, '0.11.14'
, '0.11.15'
, '0.11.16'
, '0.12.0'
, '0.12.1'
, '0.12.2'
, '0.12.3'
, '0.12.4'
, '0.12.5'
, '0.12.6'
, '0.12.7'
, '0.12.8'
, '0.12.9'
, '0.12.10'
]
<|endoftext|>


<commit_before>var fs = require('fs');

var ChromeBrowser = function(baseBrowserDecorator, args) {
  baseBrowserDecorator(this);

  var flags = args.flags || [];

  this._getOptions = function(url) {
    // Chrome CLI options
    // http://peter.sh/experiments/chromium-command-line-switches/
    return [
      '--user-data-dir=' + this._tempDir,
      '--no-default-browser-check',
      '--no-first-run',
      '--disable-default-apps',
      '--disable-popup-blocking',
      '--disable-translate'
    ].concat(flags, [url]);
  };
};

// Return location of chrome.exe file for a given Chrome directory (available: "Chrome", "Chrome SxS").
function getChromeExe(chromeDirName) {
  if (process.platform !== 'win32') {
    return null;
  }
  var windowsChromeDirectory, i, prefix;
  var suffix = '\\Google\\'+ chromeDirName + '\\Application\\chrome.exe';
  var prefixes = [process.env.LOCALAPPDATA, process.env.PROGRAMFILES, process.env['PROGRAMFILES(X86)']];

  for (i = 0; i < prefixes.length; i++) {
    prefix = prefixes[i];
    if (fs.existsSync(prefix + suffix)) {
      windowsChromeDirectory = prefix + suffix;
      break;
    }
  }

  return windowsChromeDirectory;
}

ChromeBrowser.prototype = {
  name: 'Chrome',

  DEFAULT_CMD: {
    linux: 'google-chrome',
    darwin: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
    win32: getChromeExe('Chrome')
  },
  ENV_CMD: 'CHROME_BIN'
};

ChromeBrowser.$inject = ['baseBrowserDecorator', 'args'];

var ChromeCanaryBrowser = function(baseBrowserDecorator, args) {
  ChromeBrowser.call(this, baseBrowserDecorator, args);

  var parentOptions = this._getOptions;
  this._getOptions = function(url) {
    // disable crankshaft optimizations, as it causes lot of memory leaks (as of Chrome 23.0)
    return parentOptions.call(this, url).concat(['--js-flags="--nocrankshaft --noopt"']);
  };
};

ChromeCanaryBrowser.prototype = {
  name: 'ChromeCanary',

  DEFAULT_CMD: {
    linux: 'google-chrome-canary',
    darwin: '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
    win32: getChromeExe('Chrome SxS')
  },
  ENV_CMD: 'CHROME_CANARY_BIN'
};

ChromeCanaryBrowser.$inject = ['baseBrowserDecorator', 'args'];

var DartiumBrowser = function(baseBrowserDecorator, args) {
    ChromeBrowser.call(this, baseBrowserDecorator, args);

    var checkedFlag = '--checked';
    var dartFlags = process.env['DART_FLAGS'] || '';
    var flags = dartFlags.split(' ')
    if(flags.indexOf(checkedFlag) == -1) {
        flags.push(checkedFlag);
        process.env['DART_FLAGS'] = flags.join(' ');
    }
};

DartiumBrowser.prototype = {
    name: 'Dartium',

    ENV_CMD: 'DARTIUM_BIN'
};

DartiumBrowser.$inject = ['baseBrowserDecorator', 'args'];

// PUBLISH DI MODULE
module.exports = {
  'launcher:Chrome': ['type', ChromeBrowser],
  'launcher:ChromeCanary': ['type', ChromeCanaryBrowser],
  'launcher:Dartium': ['type', DartiumBrowser]
};
<commit_msg>fix: better error when DARTIUM_BIN not set<commit_after>var fs = require('fs');

var ChromeBrowser = function(baseBrowserDecorator, args) {
  baseBrowserDecorator(this);

  var flags = args.flags || [];

  this._getOptions = function(url) {
    // Chrome CLI options
    // http://peter.sh/experiments/chromium-command-line-switches/
    return [
      '--user-data-dir=' + this._tempDir,
      '--no-default-browser-check',
      '--no-first-run',
      '--disable-default-apps',
      '--disable-popup-blocking',
      '--disable-translate'
    ].concat(flags, [url]);
  };
};

// Return location of chrome.exe file for a given Chrome directory (available: "Chrome", "Chrome SxS").
function getChromeExe(chromeDirName) {
  if (process.platform !== 'win32') {
    return null;
  }
  var windowsChromeDirectory, i, prefix;
  var suffix = '\\Google\\'+ chromeDirName + '\\Application\\chrome.exe';
  var prefixes = [process.env.LOCALAPPDATA, process.env.PROGRAMFILES, process.env['PROGRAMFILES(X86)']];

  for (i = 0; i < prefixes.length; i++) {
    prefix = prefixes[i];
    if (fs.existsSync(prefix + suffix)) {
      windowsChromeDirectory = prefix + suffix;
      break;
    }
  }

  return windowsChromeDirectory;
}

ChromeBrowser.prototype = {
  name: 'Chrome',

  DEFAULT_CMD: {
    linux: 'google-chrome',
    darwin: '/Applications/Google Chrome.app/Contents/MacOS/Google Chrome',
    win32: getChromeExe('Chrome')
  },
  ENV_CMD: 'CHROME_BIN'
};

ChromeBrowser.$inject = ['baseBrowserDecorator', 'args'];

var ChromeCanaryBrowser = function(baseBrowserDecorator, args) {
  ChromeBrowser.call(this, baseBrowserDecorator, args);

  var parentOptions = this._getOptions;
  this._getOptions = function(url) {
    // disable crankshaft optimizations, as it causes lot of memory leaks (as of Chrome 23.0)
    return parentOptions.call(this, url).concat(['--js-flags="--nocrankshaft --noopt"']);
  };
};

ChromeCanaryBrowser.prototype = {
  name: 'ChromeCanary',

  DEFAULT_CMD: {
    linux: 'google-chrome-canary',
    darwin: '/Applications/Google Chrome Canary.app/Contents/MacOS/Google Chrome Canary',
    win32: getChromeExe('Chrome SxS')
  },
  ENV_CMD: 'CHROME_CANARY_BIN'
};

ChromeCanaryBrowser.$inject = ['baseBrowserDecorator', 'args'];

var DartiumBrowser = function(baseBrowserDecorator, args) {
    ChromeBrowser.call(this, baseBrowserDecorator, args);

    var checkedFlag = '--checked';
    var dartFlags = process.env['DART_FLAGS'] || '';
    var flags = dartFlags.split(' ')
    if(flags.indexOf(checkedFlag) == -1) {
        flags.push(checkedFlag);
        process.env['DART_FLAGS'] = flags.join(' ');
    }
};

DartiumBrowser.prototype = {
    name: 'Dartium',
    DEFAULT_CMD: {},
    ENV_CMD: 'DARTIUM_BIN'
};

DartiumBrowser.$inject = ['baseBrowserDecorator', 'args'];

// PUBLISH DI MODULE
module.exports = {
  'launcher:Chrome': ['type', ChromeBrowser],
  'launcher:ChromeCanary': ['type', ChromeCanaryBrowser],
  'launcher:Dartium': ['type', DartiumBrowser]
};
<|endoftext|>


<commit_before>
/**
 * Module dependencies.
 */

var debug = require('debug')('koa-views');
var resolve = require('path').resolve;
var dirname = require('path').dirname;
var fmt = require('util').format;
var merge = require('deepmerge');
var join = require('path').join;
var cons = require('co-views');
var send = require('koa-send');

/**
 * Add `render` method and define `locals` getter and
 * setters.
 *
 * @param {String} path (optional)
 * @param {Object} opts (optional)
 * @api public
 */

module.exports = function (path, opts) {
  var base = dirname(module.parent.filename)

  // set path relative to the directory the function was called + path
  if (!path || typeof path == 'object') {
    opts = path;
    path = base;
  } else {
    path = resolve(base, path);
  }

  if (!opts) opts = {};

  // default extension to `html`
  if (!opts.default) opts.default = 'html';

  for (var prop in opts) {
    var opt = opts[prop];
    if (opt == opts.map) opt = JSON.stringify(opt);
    debug(fmt('set `%s` to `%s`', prop, opt));
  }

  return function *views (next) {
    if (this.locals && this.render) return;

    /**
     * App-specific `locals`, but honor upstream
     * middlewares that may have already set this.locals.
     */

    this.locals = this.locals || {};

    /**
     * Render `view` with `locals`.
     *
     * @param {String} view
     * @param {Object} locals
     * @return {GeneratorFunction}
     * @api public
     */

    this.render = function *(view, locals) {
      if (!locals) locals = {};
      locals = merge(locals, this.locals);
      var ext = opts.default;
      var file = fmt('%s.%s', view, ext);
      debug(fmt('render `%s` with %j', file, locals));

      if (ext == 'html' && !opts.map) {
        yield send(this, join(path, file));
      } else {
        var render = cons(path, opts);
        this.body = yield render(view, locals);
      }

      this.type = 'text/html';
    }

    yield next;
  }
}
<commit_msg>code: small cosmetic changes<commit_after>
/**
 * Module dependencies.
 */

var debug = require('debug')('koa-views');
var resolve = require('path').resolve;
var dirname = require('path').dirname;
var fmt = require('util').format;
var merge = require('deepmerge');
var join = require('path').join;
var cons = require('co-views');
var send = require('koa-send');

/**
 * Add `render` method
 *
 * @param {String} path (optional)
 * @param {Object} opts (optional)
 * @api public
 */

module.exports = function (path, opts) {
  var base = dirname(module.parent.filename);

  // set path relative to the directory the function was called + path
  if (!path || typeof path == 'object') {
    opts = path;
    path = base;
  } else {
    path = resolve(base, path);
  }

  if (!opts) opts = {};

  // default extension to `html`
  if (!opts.default) opts.default = 'html';

  for (var prop in opts) {
    var opt = opts[prop];
    if (opt == opts.map) opt = JSON.stringify(opt);
    debug(fmt('set `%s` to `%s`', prop, opt));
  }

  return function *views (next) {
    if (this.render) return;

    /**
     * App-specific `locals`, but honor upstream
     * middlewares that may have already set this.locals.
     */

    this.locals = this.locals || {};

    /**
     * Render `view` with `locals`.
     *
     * @param {String} view
     * @param {Object} locals
     * @return {GeneratorFunction}
     * @api public
     */

    this.render = function *(view, locals) {
      var ext = opts.default;
      var file = fmt('%s.%s', view, ext);

      locals = locals || {};
      locals = merge(locals, this.locals);

      debug(fmt('render `%s` with %j', file, locals));

      if (ext == 'html' && !opts.map) {
        yield send(this, join(path, file));
      } else {
        var render = cons(path, opts);
        this.body = yield render(view, locals);
      }

      this.type = 'text/html';
    }

    yield next;
  }
}
<|endoftext|>