<commit_before>var AdditionalTaskView = Backbone.View.extend({
  el: '#additional-task-view',
  additionalTaskContainerView: null,
  events: {
    'hide': 'onHide'
  },
  initialize: function(additionalTaskSequenceID)
  {
    this.additionalTaskContainerView = new AdditionalTaskContainerView(additionalTaskSequenceID);
  },
  onHide: function()
  {
    var taskAppView = this.additionalTaskContainerView.additionalTaskApp_view;
    if (taskAppView && taskAppView.customTempView) {
      taskAppView.customTempView.stopListening();
    }
  }
});

var AdditionalTaskContainerView = Backbone.View.extend({
  el: '#additional-task-app-container',
  additionalTaskApp: null,
  additionalTaskApp_view: null,
  initialize: function(additionalTaskSequenceID)
  {
    if (app.router.additionalTasksView) {
      this.additionalTaskApp = app.router.additionalTasksView.additionalTasksListView.additionalTaskCollection.findWhere({ id: additionalTaskSequenceID });
      this.render();
    } else {
      this.getSequence(additionalTaskSequenceID).then(
        _.bind(function(success) {
          this.render();
        }, this),
        _.bind(function(error) {
          console.error('error', error);
          this.render();
        }, this)
      );
    }
  },
  getSequence: function(additionalTaskSequenceID)
  {
    return $.getJSON(API_BASEURL + 'additional-tasks', null, _.bind(function(data) {
      if (data.utilities && data.utilities.length) {
        for (var i = 0; i < data.utilities.length; i++) {
          var ca = data.utilities[i];
          if (ca.id == additionalTaskSequenceID && ca.visibility) {
            this.additionalTaskApp = new AdditionalTask(ca);
          }
        }
      }
    }, this))
    .fail(function() {
      noty({text: "There was an error getting additional task.", timeout: 3000});
    })
  },

  render: function()
  {
    var actionEl = this.$el.find('.additional-tasks-app');
    var noActionEl = this.$el.find('#additional-task');

    actionEl.empty();
    noActionEl.hide();

    if (this.additionalTaskApp) {
      var row = new AdditionalTaskAppView({ additionalTaskApp: this.additionalTaskApp});
      actionEl.append(row.render().el);
      this.additionalTaskApp_view = row;
    } else {
      noActionEl.show();
      setTimeout(function() {
        window.location.href = window.location.origin+"/#additional-tasks"
      }, 2500);
    }
  }
});

var AdditionalTaskAppView = Backbone.View.extend({
  className: 'additional-task-row',
  additionalTaskApp: null,
  currentIndexStep: 1,
  currentStep: null,
  customTempView: null,
  events: {
    "click .close": "closeClicked",
    "click .next": "nextClicked",
    "click .action": "actionClicked",
    "click .repeat": "repeatClicked"
  },
  template: _.template($("#additional-task-app-template").html()),
  initialize: function (params)
  {
    this.additionalTaskApp = params.additionalTaskApp;
    this.currentStep = this.additionalTaskApp.get('steps')[this.currentIndexStep-1]
    this.$el.attr('id', this.additionalTaskApp.get('id'));
  },
  closeClicked: function (e)
  {
    e.preventDefault();
    this.doClose();
  },

  doClose: function()
  {
    window.history.back();
  },

  currentStepManagement: function()
  {
    this.currentStep = this.additionalTaskApp.get('steps')[this.currentIndexStep-1]
    // If Show temp view
    if (this.currentStep.type == "set_temperature") {
      var loadingBtn = this.$('button.next').closest('.loading-button');
      loadingBtn.addClass('inactive');
      setTimeout( function() {
        this.customTempView = new CustomTempView();
      }.bind(this), 300);
    }
  },

  nextClicked: function (e)
  {
    e.preventDefault();
    this.doNext();
  },

  doNext: function()
  {
    var loadingBtn = this.$('button.next').closest('.loading-button');

    switch (this.currentStep.type) {
      case "set_extruder":
        // Change active extruder
        this._sendChangeToolCommand(this.$('#extruder-count').val())
          .done(_.bind( function() {
            loadingBtn.removeClass('loading');
            this.checkNextStep();
          }, this))
          .fail(function() {
            loadingBtn.addClass('failed');
            noty({ text: "There was an error sending a command.", timeout: 3000 });
            setTimeout(function () {
              loadingBtn.removeClass('failed');
            }, 3000);
          });
        break;
      case "set_temperature":
        this.customTempView.stopListening();
        this.checkNextStep();
        break;
      case "action":
        loadingBtn.addClass('loading');
        if (this.currentStep.commands_on_next) {
          this.sendCommands("next")
            .done(function() {
              console.info('All the commands have been sent');
              loadingBtn.removeClass('loading');
              this.checkNextStep();
            })
            .fail(function() {
              loadingBtn.addClass('failed');
              noty({ text: "There was an error sending a command.", timeout: 3000 });
              setTimeout(function () {
                loadingBtn.removeClass('failed');
              }, 3000);
            });
        } else {
          this.checkNextStep();
        }

        break;
      case "information":
        this.checkNextStep();
        break;
    }
  },

  actionClicked: function (e)
  {
    e.preventDefault();
    this.doAction();
  },

  doAction: function()
  {
    var action_commands = this.currentStep.commands_on_action;
    var isLink = false;
    if (action_commands && action_commands[0]) {
      isLink = action_commands[0].startsWith("#");
    }
    if (isLink) {
      var stepID = action_commands[0].replace('#', '');
      this.linkToStep(stepID);
    } else {
      this.sendCommands("action");
    }
  },

  linkToStep: function(stepID)
  {
    var stepToGoData = this._getStepByID(stepID);

    this.currentIndexStep = stepToGoData.index+1;
    this.currentStep = stepToGoData.step;
    this.render()
  },

  repeatClicked: function (e)
  {
    e.preventDefault();
    this.doRepeat();
  },

  doRepeat: function()
  {
    this.currentIndexStep = 1;
    this.currentStep = this.additionalTaskApp.get('steps')[this.currentIndexStep-1]
    this.render();
  },

  checkNextStep: function()
  {
    // If no Last step
    if (this.currentIndexStep < this.additionalTaskApp.get('steps').length) {
      this.currentIndexStep++;
      this.currentStep = this.additionalTaskApp.get('steps')[this.currentIndexStep-1]
      this.render();
    // If Last step
    } else {
      this.doClose();
    }
  },

  sendCommands: function(type, commandsIndex, promise)
  {
    if (!commandsIndex) {
      var commandsIndex = 0;
    }
    if (!promise) {
      var promise = $.Deferred();
    }

    var arrayCommands = type == "action" ? this.currentStep.commands_on_action : this.currentStep.commands_on_next;
     $.ajax({

      url: API_BASEURL + 'printer/comm/send',
      method: 'POST',
      data: {
        command: arrayCommands[commandsIndex]
      }
    })
      .success( _.bind(function() {
        if (arrayCommands[commandsIndex + 1]) {
          this.sendCommands(type, ++commandsIndex, promise);
        } else {
          promise.resolve();
        }
      }, this))

      .fail(_.bind(function () {
        promise.reject()
      }, this))

      return promise;
  },

  _sendChangeToolCommand: function(tool)
  {
    var data = {
      command: "select",
      tool: 'tool'+tool
    }

    return $.ajax({
      url: API_BASEURL + "printer/tool",
      type: "POST",
      dataType: "json",
      contentType: "application/json; charset=UTF-8",
      data: JSON.stringify(data)
    });
  },

  _getStepByID: function(ID)
  {
    var steps = this.additionalTaskApp.get('steps');
    var result = null;

    for (i = 0; i < steps.length; i++) {
      if (steps[i].id == ID) {
        result = {"step" : steps[i],"index": i};
      }
    }
    return result;
  },

  render: function ()
  {
    this.$el.empty();
    this.$el.html(this.template({currentStep: this.currentStep, currentIndexStep: this.currentIndexStep, additionalTaskApp: this.additionalTaskApp.toJSON() }));
    this.currentStepManagement();
    return this;
  },
});

var CustomTempView = Backbone.View.extend({
  className: 'control-temps small-12 columns',
  el: '#custom-temp-control-template',
  semiCircleTempView: null,
  currentExtruder: 0,
  socketTemps: null,
  initialize: function()
  {
    new SemiCircleProgress();
    var profile = app.printerProfile.toJSON();
    if (app.socketData.get('tool') >= 0) {
      this.currentExtruder = app.socketData.get('tool');
    }
    this.renderCircleTemps();
    this.listenTo(app.socketData, 'change:temps', this.onTempsChanged);
    this.listenTo(app.socketData, 'change:paused', this.onPausedChanged);
    this.listenTo(app.socketData, 'change:tool', this.onToolChanged);
  },
  renderCircleTemps: function() {
    if (app.socketData.attributes.temps != this.socketTemps) {
      this.socketTemps = app.socketData.attributes.temps;
    }
    var temps = null;

    this.$el.find('#slider-nav').empty();
    this.$el.find('#slider').empty();
    this.$el.find('.bed').empty();

    this.semiCircleTempView = new TempSemiCircleView({'tool': this.currentExtruder, enableOff: false, hideBed: true, preHeat: true});

    this.$el.find('#slider').append(this.semiCircleTempView.render().el);

    if (this.socketTemps.extruders) {
      temps = {
        current: this.socketTemps.extruders[this.currentExtruder].current,
        target: this.socketTemps.extruders[this.currentExtruder].target
      };
    } else {
      temps = {current: null, target: null};
    }

    this.semiCircleTempView.setTemps(temps.current, temps.target);

    // Draw circle
    this.$el.find("#"+this.semiCircleTempView.el.id+" .progress-temp-circle").circleProgress({
      arcCoef: 0.55,
      size: 180,
      thickness: 20,
      fill: { gradient: ['#60D2E5', '#E8A13A', '#F02E19'] }
    });
    if (this.socketTemps.extruders) {
      this.updateTemps(this.socketTemps);
    }
  },

  onTempsChanged: function(socketTempData)
  {
    var temp_values = socketTempData.get('temps');
    this.updateTemps(temp_values);
  },

  updateTemps: function(temp_values)
  {
    var temps = { 'current': temp_values.extruders[this.currentExtruder].current, 'target': temp_values.extruders[this.currentExtruder].target };

    (this.semiCircleTempView).updateValues(temps);

    if (this.semiCircleTempView.type == 'tool') {

      var tempValue = '- -';
      if (this.semiCircleTempView.actual != null) {
        tempValue = Math.round(this.semiCircleTempView.actual) + 'º';
      }
      this.$el.find("#tool"+this.currentExtruder).find('.all-temps').text(tempValue);
    }

    this.$("#"+this.semiCircleTempView.el.id+" .progress-temp-circle").circleProgress({
      arcCoef: 0.55,
      size: 180,
      thickness: 20,
      fill: { gradient: ['#60D2E5', '#E8A13A', '#F02E19'] }
    });

    if (temp_values.extruders[this.currentExtruder].current >= temp_values.extruders[this.currentExtruder].target ) {
      var loadingBtn = $('button.next').closest('.loading-button');
      loadingBtn.removeClass('inactive');
    }

  }
});
<commit_msg>Using "@" instead "#" for linking steps and fix next button logic<commit_after>var AdditionalTaskView = Backbone.View.extend({
  el: '#additional-task-view',
  additionalTaskContainerView: null,
  events: {
    'hide': 'onHide'
  },
  initialize: function(additionalTaskSequenceID)
  {
    this.additionalTaskContainerView = new AdditionalTaskContainerView(additionalTaskSequenceID);
  },
  onHide: function()
  {
    var taskAppView = this.additionalTaskContainerView.additionalTaskApp_view;
    if (taskAppView && taskAppView.customTempView) {
      taskAppView.customTempView.stopListening();
    }
  }
});

var AdditionalTaskContainerView = Backbone.View.extend({
  el: '#additional-task-app-container',
  additionalTaskApp: null,
  additionalTaskApp_view: null,
  initialize: function(additionalTaskSequenceID)
  {
    if (app.router.additionalTasksView) {
      this.additionalTaskApp = app.router.additionalTasksView.additionalTasksListView.additionalTaskCollection.findWhere({ id: additionalTaskSequenceID });
      this.render();
    } else {
      this.getSequence(additionalTaskSequenceID).then(
        _.bind(function(success) {
          this.render();
        }, this),
        _.bind(function(error) {
          console.error('error', error);
          this.render();
        }, this)
      );
    }
  },
  getSequence: function(additionalTaskSequenceID)
  {
    return $.getJSON(API_BASEURL + 'additional-tasks', null, _.bind(function(data) {
      if (data.utilities && data.utilities.length) {
        for (var i = 0; i < data.utilities.length; i++) {
          var ca = data.utilities[i];
          if (ca.id == additionalTaskSequenceID && ca.visibility) {
            this.additionalTaskApp = new AdditionalTask(ca);
          }
        }
      }
    }, this))
    .fail(function() {
      noty({text: "There was an error getting additional task.", timeout: 3000});
    })
  },

  render: function()
  {
    var actionEl = this.$el.find('.additional-tasks-app');
    var noActionEl = this.$el.find('#additional-task');

    actionEl.empty();
    noActionEl.hide();

    if (this.additionalTaskApp) {
      var row = new AdditionalTaskAppView({ additionalTaskApp: this.additionalTaskApp});
      actionEl.append(row.render().el);
      this.additionalTaskApp_view = row;
    } else {
      noActionEl.show();
      setTimeout(function() {
        window.location.href = window.location.origin+"/#additional-tasks"
      }, 2500);
    }
  }
});

var AdditionalTaskAppView = Backbone.View.extend({
  className: 'additional-task-row',
  additionalTaskApp: null,
  currentIndexStep: 1,
  currentStep: null,
  customTempView: null,
  events: {
    "click .close": "closeClicked",
    "click .next": "nextClicked",
    "click .action": "actionClicked",
    "click .repeat": "repeatClicked"
  },
  template: _.template($("#additional-task-app-template").html()),
  initialize: function (params)
  {
    this.additionalTaskApp = params.additionalTaskApp;
    this.currentStep = this.additionalTaskApp.get('steps')[this.currentIndexStep-1]
    this.$el.attr('id', this.additionalTaskApp.get('id'));
  },
  closeClicked: function (e)
  {
    e.preventDefault();
    this.doClose();
  },

  doClose: function()
  {
    window.history.back();
  },

  currentStepManagement: function()
  {
    this.currentStep = this.additionalTaskApp.get('steps')[this.currentIndexStep-1]
    // If Show temp view
    if (this.currentStep.type == "set_temperature") {
      var loadingBtn = this.$('button.next').closest('.loading-button');
      loadingBtn.addClass('inactive');
      setTimeout( function() {
        this.customTempView = new CustomTempView();
      }.bind(this), 300);
    }
  },

  nextClicked: function (e)
  {
    e.preventDefault();
    this.doNext();
  },

  doNext: function()
  {
    var loadingBtn = this.$('button.next').closest('.loading-button');

    switch (this.currentStep.type) {
      case "set_extruder":
        // Change active extruder
        this._sendChangeToolCommand(this.$('#extruder-count').val())
          .done(_.bind( function() {
            loadingBtn.removeClass('loading');
            this.checkNextStep();
          }, this))
          .fail(function() {
            loadingBtn.addClass('failed');
            noty({ text: "There was an error sending a command.", timeout: 3000 });
            setTimeout(function () {
              loadingBtn.removeClass('failed');
            }, 3000);
          });
        break;
      case "set_temperature":
        this.customTempView.stopListening();
        this.checkNextStep();
        break;
      case "action":
        loadingBtn.addClass('loading');
        if (this.currentStep.commands_on_next) {
          this.sendCommands("next")
            .done(_.bind(function() {
              console.info('All the commands have been sent');
              loadingBtn.removeClass('loading');
              this.checkNextStep();
            },this))
            .fail(function() {
              loadingBtn.addClass('failed');
              noty({ text: "There was an error sending a command.", timeout: 3000 });
              setTimeout(function () {
                loadingBtn.removeClass('failed');
              }, 3000);
            });
        } else {
          this.checkNextStep();
        }

        break;
      case "information":
        this.checkNextStep();
        break;
    }
  },

  actionClicked: function (e)
  {
    e.preventDefault();
    this.doAction();
  },

  doAction: function()
  {
    var action_commands = this.currentStep.commands_on_action;
    var isLink = false
    if (action_commands && action_commands[0]) {
      isLink = action_commands[0].startsWith("@");
    }
    if (isLink) {
      var stepID = action_commands[0].replace('@', '');
      this.linkToStep(stepID);
    } else {
      this.sendCommands("action");
    }
  },

  linkToStep: function(stepID)
  {
    var stepToGoData = this._getStepByID(stepID);

    this.currentIndexStep = stepToGoData.index+1;
    this.currentStep = stepToGoData.step;
    this.render()
  },

  repeatClicked: function (e)
  {
    e.preventDefault();
    this.doRepeat();
  },

  doRepeat: function()
  {
    this.currentIndexStep = 1;
    this.currentStep = this.additionalTaskApp.get('steps')[this.currentIndexStep-1]
    this.render();
  },

  checkNextStep: function()
  {
    // If no Last step
    if (this.currentIndexStep < this.additionalTaskApp.get('steps').length) {
      this.currentIndexStep++;
      this.currentStep = this.additionalTaskApp.get('steps')[this.currentIndexStep-1]
      this.render();
    // If Last step
    } else {
      this.doClose();
    }
  },

  sendCommands: function(type, commandsIndex, promise)
  {
    if (!commandsIndex) {
      var commandsIndex = 0;
    }
    if (!promise) {
      var promise = $.Deferred();
    }

    var arrayCommands = type == "action" ? this.currentStep.commands_on_action : this.currentStep.commands_on_next;
     $.ajax({

      url: API_BASEURL + 'printer/comm/send',
      method: 'POST',
      data: {
        command: arrayCommands[commandsIndex]
      }
    })
      .success( _.bind(function() {
        if (arrayCommands[commandsIndex + 1]) {
          this.sendCommands(type, ++commandsIndex, promise);
        } else {
          promise.resolve();
        }
      }, this))

      .fail(_.bind(function () {
        promise.reject()
      }, this))

      return promise;
  },

  _sendChangeToolCommand: function(tool)
  {
    var data = {
      command: "select",
      tool: 'tool'+tool
    }

    return $.ajax({
      url: API_BASEURL + "printer/tool",
      type: "POST",
      dataType: "json",
      contentType: "application/json; charset=UTF-8",
      data: JSON.stringify(data)
    });
  },

  _getStepByID: function(ID)
  {
    var steps = this.additionalTaskApp.get('steps');
    var result = null;

    for (i = 0; i < steps.length; i++) {
      if (steps[i].id == ID) {
        result = {"step" : steps[i],"index": i};
      }
    }
    return result;
  },

  render: function ()
  {
    this.$el.empty();
    this.$el.html(this.template({currentStep: this.currentStep, currentIndexStep: this.currentIndexStep, additionalTaskApp: this.additionalTaskApp.toJSON() }));
    this.currentStepManagement();
    return this;
  },
});

var CustomTempView = Backbone.View.extend({
  className: 'control-temps small-12 columns',
  el: '#custom-temp-control-template',
  semiCircleTempView: null,
  currentExtruder: 0,
  socketTemps: null,
  initialize: function()
  {
    new SemiCircleProgress();
    var profile = app.printerProfile.toJSON();
    if (app.socketData.get('tool') >= 0) {
      this.currentExtruder = app.socketData.get('tool');
    }
    this.renderCircleTemps();
    this.listenTo(app.socketData, 'change:temps', this.onTempsChanged);
    this.listenTo(app.socketData, 'change:paused', this.onPausedChanged);
    this.listenTo(app.socketData, 'change:tool', this.onToolChanged);
  },
  renderCircleTemps: function() {
    if (app.socketData.attributes.temps != this.socketTemps) {
      this.socketTemps = app.socketData.attributes.temps;
    }
    var temps = null;

    this.$el.find('#slider-nav').empty();
    this.$el.find('#slider').empty();
    this.$el.find('.bed').empty();

    this.semiCircleTempView = new TempSemiCircleView({'tool': this.currentExtruder, enableOff: false, hideBed: true, preHeat: true});

    this.$el.find('#slider').append(this.semiCircleTempView.render().el);

    if (this.socketTemps.extruders) {
      temps = {
        current: this.socketTemps.extruders[this.currentExtruder].current,
        target: this.socketTemps.extruders[this.currentExtruder].target
      };
    } else {
      temps = {current: null, target: null};
    }

    this.semiCircleTempView.setTemps(temps.current, temps.target);

    // Draw circle
    this.$el.find("#"+this.semiCircleTempView.el.id+" .progress-temp-circle").circleProgress({
      arcCoef: 0.55,
      size: 180,
      thickness: 20,
      fill: { gradient: ['#60D2E5', '#E8A13A', '#F02E19'] }
    });
    if (this.socketTemps.extruders) {
      this.updateTemps(this.socketTemps);
    }
  },

  onTempsChanged: function(socketTempData)
  {
    var temp_values = socketTempData.get('temps');
    this.updateTemps(temp_values);
  },

  updateTemps: function(temp_values)
  {
    var temps = { 'current': temp_values.extruders[this.currentExtruder].current, 'target': temp_values.extruders[this.currentExtruder].target };

    (this.semiCircleTempView).updateValues(temps);

    if (this.semiCircleTempView.type == 'tool') {

      var tempValue = '- -';
      if (this.semiCircleTempView.actual != null) {
        tempValue = Math.round(this.semiCircleTempView.actual) + 'º';
      }
      this.$el.find("#tool"+this.currentExtruder).find('.all-temps').text(tempValue);
    }

    this.$("#"+this.semiCircleTempView.el.id+" .progress-temp-circle").circleProgress({
      arcCoef: 0.55,
      size: 180,
      thickness: 20,
      fill: { gradient: ['#60D2E5', '#E8A13A', '#F02E19'] }
    });

    if (temp_values.extruders[this.currentExtruder].current >= temp_values.extruders[this.currentExtruder].target ) {
      var loadingBtn = $('button.next').closest('.loading-button');
      loadingBtn.removeClass('inactive');
    }

  }
});
<|endoftext|>


<commit_before>#!/usr/bin/env node
/*
 * Create a large number of socket connections to simulate a lot of traffic in
 * event/1 and its sessions. Requires the configuration setting
 * ``MOCK_AUTH=true`` to function.
 */

var logger = require("../lib/logging.js").getLogger(),
    _ = require("underscore"),
    events = require("events"),
    config = require("../conf.json"),
    createUsers = require("../lib/passport-mock.js").createUsers,
    sock_client = require("sockjs-client-ws"),
    unhangoutServer = require("../lib/unhangout-server.js");

function AuthSock(options) {
    this.state = "disconnected";
    this.server = options.server;
    this.sockKey = options.sockKey;
    this.user = this.server.db.users.findWhere({"sock-key": this.sockKey});
    this.sock = sock_client.create(this.server.options.baseUrl + "/sock");
    this.init();
}
AuthSock.prototype = _.extend({
    init: function() {
        _.bindAll(this, "onerror", "write");
        this.sock.on("connection", _.bind(function() {
            this.write("auth", {key: this.sockKey, id: this.user.id});
        }, this));
        this.sock.on("data", _.bind(function(message) {
            var msg = JSON.parse(message);
            if (msg.type.indexOf("-err") != -1) {
                this.onerror(msg);
            } else if (msg.type == "auth-ack") {
                this.state = "authorized";
            } else if (msg.type == "join-ack") {
                this.state = "joined";
            }
            this.emit("data", msg);
        }, this));
        this.sock.on("error", this.onerror);
    },
    onerror: function(err) {
        logger.error(this.sockKey + " error", err);

    },
    write: function(type, args) {
        this.sock.write(JSON.stringify({type: type, args: args}));
    }
}, events.EventEmitter.prototype);

/*
 * Class representing a random user.  It periodically sends chat messages,
 * joins sessions, and connects and disconnects, and focuses/unfocuses.
 */
function Rando(options) {
    this.server = options.server;
    this.event = options.event;
    this.sockKey = options.sockKey;
    // Initialize with a random timeout, to mix up the clock ticks.
    setTimeout(_.bind(function() {
        this.init();
    }, this), Math.random() * 1000);
};
Rando.prototype = {
    init: function() {
        _.bindAll(this, "ontick");
        this.eventSock = new AuthSock({server: this.server, sockKey: this.sockKey});
        this.sessionSock = new AuthSock({server: this.server, sockKey: this.sockKey});
        setInterval(this.ontick, 1000);
    },
    ontick: function() {
        // Event actions
        switch (this.eventSock.state) {
            case "disconnected":
            case "joining":
                break;
            case "authorized":
                // If we're authorized, but haven't started joining, join the
                // event with a 50% probability.
                if (Math.random() > 0.5) {
                    logger.debug(this.sockKey + " joining");
                    this.eventSock.state = "joining";
                    this.eventSock.write("join", {id: this.event.getRoomId()});
                }
                break;
            case "joined":
                if (Math.random() > 0.99) {
                    logger.debug(this.sockKey + " chatting");
                    this.eventSock.write("chat", {
                        roomId: this.event.getRoomId(),
                        text: this.chatMessages[
                            Math.floor(Math.random() * this.chatMessages.length)
                        ]
                    });
                } else if (Math.random() > 0.99) {
                    this.eventSock.write("leave", {
                        id: this.event.getRoomId(),
                    });
                    this.eventSock.state = "authorized";
                } else if (Math.random() > 0.9) {
                    if (this.eventSock.focused) {
                        this.eventSock.write("blur", {roomId: this.event.getRoomId()});
                        this.eventSock.focused = false;
                    } else {
                        this.eventSock.write("focus", {roomId: this.event.getRoomId()});
                        this.eventSock.focused = true;
                    }
                }
                break;
        };
        // Session actions
        switch (this.sessionSock.state) {
            case "disconnected":
            case "joining":
                break;
            case "authorized":
                if (this.event.get("sessionsOpen") && Math.random() > 0.9) {
                    var sessions = this.event.get("sessions");
                    var session = sessions.at(Math.floor(sessions.length * Math.random()));
                    if (session.getNumConnectedParticipants() < 10) {
                        this.sessionSock.write("join", {id: session.getRoomId()});
                        this.sessionSock.state = "joining";
                        this.sessionSock.room = session.getRoomId();
                    }
                }
                break;
            case "joined":
                if (Math.random() > 0.9) {
                    this.sessionSock.write("leave", {id: this.sessionSock.room});
                    this.sessionSock.state = "authorized";
                    this.sessionSock.room = null;
                }
                break;
        };
    },
    write: function(type, args, sock) {
        (sock || this.sock).write(JSON.stringify({type: type, args: args}));
    },
    chatMessages: [
        "From fairest creatures we desire increase,",
        "That thereby beauty's rose might never die,",
        "But as the riper should by time decease,",
        "His tender heir might bear his memory;",
        "But thou, contracted to thine own bright eyes,",
        "Feed'st thy light's flame with self-substantial fuel,",
        "Making a famine where abundance lies,",
        "Thyself thy foe, to thy sweet self too cruel.",
        "Thou, that art now the world's fresh ornament",
        "And only herald to the gaudy spring,",
        "Within thine own bud buriest thy content",
        "And, tender churl, mak'st waste in niggarding.",
        "    Pity the world, or else this glutton be,",
        "    To eat the world's due, by the grave and thee."
    ]
};

function init(done) {
    var server = new unhangoutServer.UnhangoutServer();
    server.on("inited", function() {
        server.start();
    });
    server.on("started", function() {
        createUsers(server.db.users);
        done();
    });
    var options = _.extend({}, config, {mockAuth: true, UNHANGOUT_USE_SSL: false});
    _.each(options, function(value, key) {
        if (key.indexOf('UNHANGOUT_') != -1) {
            options[key.slice(10)] = value;
        }
    });
    server.init(options);
    return server;
}
function main() {
    var server = init(function() {
        var event = server.db.events.at(0)
        for (var i = 0; i < 100; i++) {
            new Rando({
                server: server,
                sockKey: "loader" + i,
                event: event
            });
        }
        logger.warn("Random users loading page: " + server.options.baseUrl + "/event/" + event.id);
    });
}

if (require.main === module) {
    main();
}
<commit_msg>Minor cleanup of load-simulator<commit_after>#!/usr/bin/env node
//
// Fire up the server, and create a large number of socket connections to
// simulate a lot of traffic in ``event/1`` and its sessions.
//
// NOTE: always runs with USE_SSL=false and mockAuth=true, as required by the
// mock users' sockets.
//

var logger = require("../lib/logging.js").getLogger(),
    _ = require("underscore"),
    events = require("events"),
    config = require("../conf.json"),
    createUsers = require("../lib/passport-mock.js").createUsers,
    sock_client = require("sockjs-client-ws"),
    unhangoutServer = require("../lib/unhangout-server.js");

/*
 * Object holding a socket and its authorization/join state.
 */
function AuthSock(options) {
    this.state = "disconnected";
    this.server = options.server;
    this.sockKey = options.sockKey;
    this.user = this.server.db.users.findWhere({"sock-key": this.sockKey});
    this.sock = sock_client.create(this.server.options.baseUrl + "/sock");
    this.init();
}
AuthSock.prototype = _.extend({
    init: function() {
        _.bindAll(this, "onerror", "write");
        this.sock.on("connection", _.bind(function() {
            this.write("auth", {key: this.sockKey, id: this.user.id});
        }, this));
        this.sock.on("data", _.bind(function(message) {
            var msg = JSON.parse(message);
            if (msg.type.indexOf("-err") != -1) {
                this.onerror(msg);
            } else if (msg.type == "auth-ack") {
                this.state = "authorized";
            } else if (msg.type == "join-ack") {
                this.state = "joined";
            }
            this.emit("data", msg);
        }, this));
        this.sock.on("error", this.onerror);
    },
    onerror: function(err) {
        logger.error(this.sockKey + " error", err);

    },
    write: function(type, args) {
        this.sock.write(JSON.stringify({type: type, args: args}));
    }
}, events.EventEmitter.prototype);

/*
 * Class representing a random user.  It periodically sends chat messages,
 * joins sessions, and connects and disconnects, and focuses/unfocuses.
 */
function Rando(options) {
    this.server = options.server;
    this.event = options.event;
    this.sockKey = options.sockKey;
    // Initialize with a random timeout, to mix up the clock ticks.
    setTimeout(_.bind(function() {
        this.init();
    }, this), Math.random() * 1000);
};
Rando.prototype = {
    init: function() {
        _.bindAll(this, "ontick");
        this.eventSock = new AuthSock({server: this.server, sockKey: this.sockKey});
        this.sessionSock = new AuthSock({server: this.server, sockKey: this.sockKey});
        setInterval(this.ontick, 1000);
    },
    ontick: function() {
        // Event actions
        switch (this.eventSock.state) {
            case "disconnected":
            case "joining":
                break;
            case "authorized":
                // If we're authorized, but haven't started joining, join the
                // event with a 50% probability.
                if (Math.random() > 0.5) {
                    logger.debug(this.sockKey + " joining");
                    this.eventSock.state = "joining";
                    this.eventSock.write("join", {id: this.event.getRoomId()});
                }
                break;
            case "joined":
                if (Math.random() > 0.99) {
                    logger.debug(this.sockKey + " chatting");
                    this.eventSock.write("chat", {
                        roomId: this.event.getRoomId(),
                        text: this.chatMessages[
                            Math.floor(Math.random() * this.chatMessages.length)
                        ]
                    });
                } else if (Math.random() > 0.99) {
                    this.eventSock.write("leave", {
                        id: this.event.getRoomId(),
                    });
                    this.eventSock.state = "authorized";
                } else if (Math.random() > 0.9) {
                    if (this.eventSock.focused) {
                        this.eventSock.write("blur", {roomId: this.event.getRoomId()});
                        this.eventSock.focused = false;
                    } else {
                        this.eventSock.write("focus", {roomId: this.event.getRoomId()});
                        this.eventSock.focused = true;
                    }
                }
                break;
        };
        // Session actions
        switch (this.sessionSock.state) {
            case "disconnected":
            case "joining":
                break;
            case "authorized":
                if (this.event.get("sessionsOpen") && Math.random() > 0.9) {
                    var sessions = this.event.get("sessions");
                    var session = sessions.at(Math.floor(sessions.length * Math.random()));
                    if (session.getNumConnectedParticipants() < 10) {
                        this.sessionSock.write("join", {id: session.getRoomId()});
                        this.sessionSock.state = "joining";
                        this.sessionSock.room = session.getRoomId();
                    }
                }
                break;
            case "joined":
                if (Math.random() > 0.9) {
                    this.sessionSock.write("leave", {id: this.sessionSock.room});
                    this.sessionSock.state = "authorized";
                    this.sessionSock.room = null;
                }
                break;
        };
    },
    write: function(type, args) {
        this.sock.write(JSON.stringify({type: type, args: args}));
    },
    chatMessages: [
        "From fairest creatures we desire increase,",
        "That thereby beauty's rose might never die,",
        "But as the riper should by time decease,",
        "His tender heir might bear his memory;",
        "But thou, contracted to thine own bright eyes,",
        "Feed'st thy light's flame with self-substantial fuel,",
        "Making a famine where abundance lies,",
        "Thyself thy foe, to thy sweet self too cruel.",
        "Thou, that art now the world's fresh ornament",
        "And only herald to the gaudy spring,",
        "Within thine own bud buriest thy content",
        "And, tender churl, mak'st waste in niggarding.",
        "    Pity the world, or else this glutton be,",
        "    To eat the world's due, by the grave and thee."
    ]
};

function init(callback) {
    var server = new unhangoutServer.UnhangoutServer();
    server.on("inited", function() {
        server.start();
    });
    server.on("started", function() {
        createUsers(server.db.users);
        callback(server);
    });
    var options = _.extend({}, config, {mockAuth: true, UNHANGOUT_USE_SSL: false});
    _.each(options, function(value, key) {
        if (key.indexOf('UNHANGOUT_') != -1) {
            options[key.slice(10)] = value;
        }
    });
    server.init(options);
    return server;
}
function main() {
    init(function(server) {
        var event = server.db.events.at(0)
        for (var i = 0; i < 100; i++) {
            new Rando({
                server: server,
                sockKey: "loader" + i,
                event: event
            });
        }
        logger.warn("Random users loading page: " + server.options.baseUrl + "/event/" + event.id);
    });
}

if (require.main === module) {
    main();
}
<|endoftext|>


<commit_before>const obj = {
  log: ['a', 'b', 'c'],
  get latest() {
    if (this.log.length === 0) {
      return undefined;
    }
    return this.log[this.log.length - 1];
  }
};

console.log(obj.latest);
// expected output: "c"
<commit_msg>Removed redundant guard clause (#2060)<commit_after>const obj = {
  log: ['a', 'b', 'c'],
  get latest() {
    return this.log[this.log.length - 1];
  }
};

console.log(obj.latest);
// expected output: "c"
<|endoftext|>


<commit_before>var _ = require('lodash');

var repositories = [
{ "name": "kjunine/ubuntu", "description": "Docker for Ubuntu Trusty" },
{ "name": "partlab/ubuntu-elasticsearch", "description": "Docker image to run an out of the box Elasticsearch." },
{ "name": "pmdevel/ubuntu", "description": "Ubuntu 14.04 with character set ISO-8859-15" },
{ "name": "partlab/ubuntu-mariadb", "description": "Docker image to run an out of the box MariaDB." },
{ "name": "partlab/ubuntu-redis", "description": "Docker image to run an out of the box Redis server." },
{ "name": "rangalo/ubuntu", "description": "Ubuntu 14.10 with some basic tools like wget, unzip and expect" },
{ "name": "partlab/ubuntu-php5", "description": "Simple base docker image to run PHP5 applications." },
{ "name": "partlab/ubuntu-java", "description": "Simple base docker image to run java applications" },
{ "name": "doomkin/ubuntu-ssh", "description": "Ubuntu with OpenSSH server Dockerfile for trusted automated Docker builds." },
{ "name": "yesops/ubuntu", "description": "" },
{ "name": "khaio/ubuntu", "description": "Trusted build of Ubuntu Saucy. Created with Debootstrap with:\n\n$ sudo debootstrap saucy saucy > /dev/null\n$ tar -zcvf saucy.tar.gz saucy/" },
{ "name": "partlab/ubuntu-mongodb", "description": "Docker image to run an out of the box MongoDB." },
{ "name": "esycat/ubuntu", "description": "Ubuntu LTS" },
{ "name": "trobz/ubuntu", "description": "" },
{ "name": "saltstack/ubuntu-13.10", "description": "" },
{ "name": "rtux/ubuntu-opencv", "description": "Builds OpenCV 2.4.8 on Ubuntu:latest" },
{ "name": "wow73611/ubuntu", "description": "" },
{ "name": "eddelbuettel/docker-ubuntu-r", "description": "" },
{ "name": "itdevdixons/ubuntu", "description": "" },
{ "name": "arimakouyou/ubuntu-japanese", "description": "Ubuntu 14.04 に日本語環境とよく使うものを入れたもの" },
{ "name": "playlist/ubuntu", "description": "" },
{ "name": "larmar/ubuntu", "description": "" },
{ "name": "partlab/ubuntu-couchdb", "description": "Docker image to run an out of the box CouchDB." },
{ "name": "nitrousio/ubuntu-bare", "description": "" },
{ "name": "partlab/ubuntu-postgresql", "description": "Docker image to run an out of the box PostgreSQL." },
{ "name": "kaysoft/ubuntu-upgrade", "description": "Ubuntu 14.04 LTS " },
{ "name": "walchl/cuda-ubuntu", "description": "" },
{ "name": "infusionsoft/ubuntu-base", "description": "Ubuntu base image" },
{ "name": "saltstack/ubuntu-12.10-minimal", "description": "" },
{ "name": "dianpou/ubuntu", "description": "" },
{ "name": "saltstack/ubuntu-13.04", "description": "" },
{ "name": "saltstack/ubuntu-13.04-minimal", "description": "" },
{ "name": "abhid/ubuntu", "description": "ubuntu container with some common utilities" },
{ "name": "pinterb/ubuntu-python", "description": "" },
{ "name": "partlab/ubuntu-typesafe", "description": "Docker image to run an out of the box Typesafe Activator." },
{ "name": "sirile/ubuntu", "description": "" },
{ "name": "saltstack/ubuntu-12.04", "description": "" },
{ "name": "cato1971/ubuntu", "description": "Base 32-bit Ubuntu image from cato1971/ubuntu-32bit" },
{ "name": "neroinc/ubuntu-crosscompile", "description": "" },
{ "name": "partlab/ubuntu-ruby", "description": "Simple base docker image to run Ruby applications." },
{ "name": "jeyk/ubuntu", "description": "" },
{ "name": "jrwesolo/ubuntu-with-chef", "description": "" },
{ "name": "concretesolutions/ubuntu-dev", "description": "" },
{ "name": "usertaken/ubuntu-owncloud-stable", "description": "ownCloud Version 8.0" },
{ "name": "jianhuiz/ubuntu-docker", "description": "ubuntu images that runs in nova-docker" },
{ "name": "akyshr/ubuntu-lxde-tigervnc", "description": "Ubuntu Desktop(LXDE) with tigervnc and xdm" },
{ "name": "saltstack/ubuntu-12.10", "description": "" },
{ "name": "grams/ubuntu-base", "description": "" },
{ "name": "partlab/ubuntu-hhvm", "description": "Simple base docker image to run PHP applications with HHVM." },
{ "name": "nacyot/ubuntu", "description": "" },
{ "name": "tutum/ubuntu-lucid", "description": "DEPRECATED: Please use `tutum/ubuntu:lucid` or `tutum/ubuntu:10.04` instead." },
{ "name": "partlab/ubuntu-nginx", "description": "Docker image to run an out of the box Nginx." },
{ "name": "wmarinho/ubuntu", "description": "" },
{ "name": "jprjr/ubuntu-kibana", "description": "" },
{ "name": "pertino/ubuntu", "description": "" },
{ "name": "partlab/ubuntu-jenkins", "description": "Docker image to run an out of the box Jenkins." },
{ "name": "siomiz/ubuntu-ttyjs", "description": "non-root tty.js running in _/node (ubuntu)" },
{ "name": "cedvan/ubuntu", "description": "" },
{ "name": "dlin/ubuntu-ssh", "description": "" },
{ "name": "neroinc/ubuntu-golang-crosscompile", "description": "" },
{ "name": "ganiutomo/ubuntu-jmeter", "description": "" },
{ "name": "dlin/ubuntu-duckbox", "description": "" },
{ "name": "exoplatform/ubuntu-jdk7-exo", "description": "" },
{ "name": "exoplatform/ubuntu-jdk7-exo-chat", "description": "" },
{ "name": "norsystechteam/ubuntu", "description": "" },
{ "name": "inftec/ubuntu-java", "description": "" },
{ "name": "silvershell/ubuntu", "description": "" },
{ "name": "ggtools/busybox-ubuntu", "description": "Busybox ubuntu version with extra goodies" },
{ "name": "jmoati/ubuntu-dev", "description": "" },
{ "name": "onesysadmin/ubuntu-postfix", "description": "" },
{ "name": "reliableembeddedsystems/ubuntu-base", "description": "I use this as a base for my yocto stuff" },
{ "name": "saltstack/ubuntu-12.04-minimal", "description": "" },
{ "name": "exoplatform/ubuntu-jdk7", "description": "" },
{ "name": "jayofdoom/docker-ubuntu-14.04", "description": "This is a simple docker image that updates the stackforge/ubuntu:13.10 image to Ubuntu Trusty." },
{ "name": "partlab/ubuntu-droneci", "description": "Docker image to run an out of the box Drone CI" },
{ "name": "saltstack/ubuntu-14.04-minimal", "description": "" },
{ "name": "tutum/ubuntu-raring", "description": "DEPRECATED: Please use `tutum/ubuntu:raring` or `tutum/ubuntu:13.04` instead." },
{ "name": "teamrock/ubuntu", "description": "" },
{ "name": "jgeiger/ubuntu", "description": "" },
{ "name": "rolymobile/ubuntu", "description": "" },
{ "name": "pinterb/ubuntu-perl", "description": "" },
{ "name": "vvoronin/ubuntu-tools", "description": "" },
{ "name": "saltstack/ubuntu-14.04", "description": "" },
{ "name": "panoptix/ubuntu", "description": "" },
{ "name": "tutum/ubuntu-trusty", "description": "DEPRECATED: Please use `tutum/ubuntu:trusty` or `tutum/ubuntu:14.04` instead." },
{ "name": "eternnoir/ubuntu-java", "description": "" },
{ "name": "vubui/ubuntu", "description": "" },
{ "name": "mullnerz/ubuntu", "description": "" },
{ "name": "dockitapp/single-redis-ubuntu", "description": "" },
{ "name": "sbminimal/docker-ubuntu-apache-php-compo", "description": "Minimal Docker Image for Apache+PHP+composer (based on minimal ubuntu)" },
{ "name": "crsmithdev/ubuntu", "description": "" },
{ "name": "alexisno/ubuntu-dev", "description": "" },
{ "name": "frodenas/ubuntu", "description": "A Docker Image for Ubuntu" },
{ "name": "zlim/ubuntu-dev", "description": "" },
{ "name": "jinglemansweep/ubuntu-base", "description": "Standard Ubuntu Trusty (14.04 LTS) container with a few useful packages pre-installed." },
{ "name": "labstack/ubuntu", "description": "" },
{ "name": "larrycai/ubuntu-sshd", "description": "" },
{ "name": "leanix/ubuntu-ansible", "description": "" },
{ "name": "undancer/ubuntu", "description": "" },
{ "name": "st2py/ubuntu", "description": "" },
];

var tags = _.zipObject(_.map(repositories, 'name'), _.map(repositories, _.constant([
	{ name: 'latest', layer: '10c37f0780ca1d1602fcb720b29b3542a2d24ea9' },
	{ name: '1.0.1', layer: 'cfc5fe3a1d6f7e773eb019d04681697648d23e76' },
	{ name: '2.0.0', layer: '3861a21803fcd9eb92a403027b0da2bb7add4de1' }
])));

var getQueryFromPath = function(path) {
	return require('querystring').parse(path.substring(path.indexOf('?') + 1));
};

var getRepositories = function(queries) {
	var pageSize = queries.n || 25;
	var results = _.filter(repositories, function(repository) {
		return repository.name.indexOf(queries.q) >= 0;
	});
	return {
		'num_pages': Math.ceil(results.length/pageSize),
		'num_results': results.length,
		'page_size': pageSize,
		'query': queries.q,
		'page': queries.page,
		'results': results.slice((queries.page - 1) * pageSize, queries.page * pageSize)
	};
};

var getDetails = function(options, match) {
	var id = match[1];
	return {
		'id': id,
		'parent': '06a7195811199d4eaee18482fc151c2443cd73e0',
		'created': '2011-01-01',
		'architecture': 'amd64',
		'os': 'linux',
		'Size': 501,
	};
};

var getAncestry = function() {
	return [
		'10c37f0780ca1d1602fcb720b29b3542a2d24ea9',
		'cfc5fe3a1d6f7e773eb019d04681697648d23e76',
		'3861a21803fcd9eb92a403027b0da2bb7add4de1',
	];
}

var FakeClient = function() {
	this.patterns = [];
	this.defaultPattern = {
		code: 404,
		action: _.constant('Not found'),
	};
};

FakeClient.prototype.request = function(options, callback) {
	var match;
	var path = options.path.replace(/[\/\?]+$/, '');
	var pattern = _.find(this.patterns, function(pattern) {
		return !!(match = path.match(pattern.match)) && options.method.indexOf(pattern.method) >= 0;
	}) || this.defaultPattern;

	callback({
		statusCode: pattern.code,
		headers: { 'content-type': 'application/json' },
		on: function(trigger, callback) {
			if (trigger === 'data') {
				var data = JSON.stringify(pattern.action(options, match));
				callback(data);
			} else if (trigger === 'end') {
				callback();
			}
			return this;
		},
	});
	return {
		end: function() { return this; },
		on: function() { return this; },
		setTimeout: function() { return this; },
	};
};

var escapeRegex = function(text) {
	return text.replace(/[.*+? ${}()|[\]\\]/g, '\\$&');
};

FakeClient.prototype.when = function(match, method) {
	method = method || 'GET';
	match = _.reduce(match.split('**'), function(a, b, c, d) {
		return _.map(d, function(dd) {
			return _.reduce(dd.split('*'), function(e1, e2, e3, e4) {
				return _.map(e4, escapeRegex).join('([^/]+)');
			});
		}).join('(.*)');
	}, '');
	var self = this;
	return {
		then: function(response, code) {
			self.patterns.push({
				match: match,
				method: _.isArray(method) ? method : [method],
				code: code || 200,
				action: _.isFunction(response) ? response : _.constant(response),
			});
			return self;
		}
	};
};

var mockClient = new FakeClient();

module.exports = mockClient
	.when('/v1/search*').then(function (options) { return getRepositories(getQueryFromPath(options.path)); })
	.when('/v1/repositories/**/tags').then(function(options, args) { return tags[args[1]]; })
	.when('/v1/repositories/**/tags/*', 'DELETE').then(function(options, args) {
		tags[args[1]] = _.without(tags[args[1]], _.find(tags[args[1]], 'name', args[2]));
		return "";
	 })
	.when('/v1/repositories/**', 'DELETE').then(function(options, args) {
		repositories = _.without(repositories, _.find(repositories, {name: args[1]}));
		return "";
	})
	.when('/v1/images/*/json').then(getDetails)
	.when('/v1/images/*/ancestry').then(getAncestry());
<commit_msg>Introduce a MemoryRegistry to cleanup mock client<commit_after>var _ = require('lodash');
var querystring = require('querystring');

var repositories = [
{ "name": "kjunine/ubuntu", "description": "Docker for Ubuntu Trusty" },
{ "name": "partlab/ubuntu-elasticsearch", "description": "Docker image to run an out of the box Elasticsearch." },
{ "name": "pmdevel/ubuntu", "description": "Ubuntu 14.04 with character set ISO-8859-15" },
{ "name": "partlab/ubuntu-mariadb", "description": "Docker image to run an out of the box MariaDB." },
{ "name": "partlab/ubuntu-redis", "description": "Docker image to run an out of the box Redis server." },
{ "name": "rangalo/ubuntu", "description": "Ubuntu 14.10 with some basic tools like wget, unzip and expect" },
{ "name": "partlab/ubuntu-php5", "description": "Simple base docker image to run PHP5 applications." },
{ "name": "partlab/ubuntu-java", "description": "Simple base docker image to run java applications" },
{ "name": "doomkin/ubuntu-ssh", "description": "Ubuntu with OpenSSH server Dockerfile for trusted automated Docker builds." },
{ "name": "yesops/ubuntu", "description": "" },
{ "name": "khaio/ubuntu", "description": "Trusted build of Ubuntu Saucy. Created with Debootstrap with:\n\n$ sudo debootstrap saucy saucy > /dev/null\n$ tar -zcvf saucy.tar.gz saucy/" },
{ "name": "partlab/ubuntu-mongodb", "description": "Docker image to run an out of the box MongoDB." },
{ "name": "esycat/ubuntu", "description": "Ubuntu LTS" },
{ "name": "trobz/ubuntu", "description": "" },
{ "name": "saltstack/ubuntu-13.10", "description": "" },
{ "name": "rtux/ubuntu-opencv", "description": "Builds OpenCV 2.4.8 on Ubuntu:latest" },
{ "name": "wow73611/ubuntu", "description": "" },
{ "name": "eddelbuettel/docker-ubuntu-r", "description": "" },
{ "name": "itdevdixons/ubuntu", "description": "" },
{ "name": "arimakouyou/ubuntu-japanese", "description": "Ubuntu 14.04 に日本語環境とよく使うものを入れたもの" },
{ "name": "playlist/ubuntu", "description": "" },
{ "name": "larmar/ubuntu", "description": "" },
{ "name": "partlab/ubuntu-couchdb", "description": "Docker image to run an out of the box CouchDB." },
{ "name": "nitrousio/ubuntu-bare", "description": "" },
{ "name": "partlab/ubuntu-postgresql", "description": "Docker image to run an out of the box PostgreSQL." },
{ "name": "kaysoft/ubuntu-upgrade", "description": "Ubuntu 14.04 LTS " },
{ "name": "walchl/cuda-ubuntu", "description": "" },
{ "name": "infusionsoft/ubuntu-base", "description": "Ubuntu base image" },
{ "name": "saltstack/ubuntu-12.10-minimal", "description": "" },
{ "name": "dianpou/ubuntu", "description": "" },
{ "name": "saltstack/ubuntu-13.04", "description": "" },
{ "name": "saltstack/ubuntu-13.04-minimal", "description": "" },
{ "name": "abhid/ubuntu", "description": "ubuntu container with some common utilities" },
{ "name": "pinterb/ubuntu-python", "description": "" },
{ "name": "partlab/ubuntu-typesafe", "description": "Docker image to run an out of the box Typesafe Activator." },
{ "name": "sirile/ubuntu", "description": "" },
{ "name": "saltstack/ubuntu-12.04", "description": "" },
{ "name": "cato1971/ubuntu", "description": "Base 32-bit Ubuntu image from cato1971/ubuntu-32bit" },
{ "name": "neroinc/ubuntu-crosscompile", "description": "" },
{ "name": "partlab/ubuntu-ruby", "description": "Simple base docker image to run Ruby applications." },
{ "name": "jeyk/ubuntu", "description": "" },
{ "name": "jrwesolo/ubuntu-with-chef", "description": "" },
{ "name": "concretesolutions/ubuntu-dev", "description": "" },
{ "name": "usertaken/ubuntu-owncloud-stable", "description": "ownCloud Version 8.0" },
{ "name": "jianhuiz/ubuntu-docker", "description": "ubuntu images that runs in nova-docker" },
{ "name": "akyshr/ubuntu-lxde-tigervnc", "description": "Ubuntu Desktop(LXDE) with tigervnc and xdm" },
{ "name": "saltstack/ubuntu-12.10", "description": "" },
{ "name": "grams/ubuntu-base", "description": "" },
{ "name": "partlab/ubuntu-hhvm", "description": "Simple base docker image to run PHP applications with HHVM." },
{ "name": "nacyot/ubuntu", "description": "" },
{ "name": "tutum/ubuntu-lucid", "description": "DEPRECATED: Please use `tutum/ubuntu:lucid` or `tutum/ubuntu:10.04` instead." },
{ "name": "partlab/ubuntu-nginx", "description": "Docker image to run an out of the box Nginx." },
{ "name": "wmarinho/ubuntu", "description": "" },
{ "name": "jprjr/ubuntu-kibana", "description": "" },
{ "name": "pertino/ubuntu", "description": "" },
{ "name": "partlab/ubuntu-jenkins", "description": "Docker image to run an out of the box Jenkins." },
{ "name": "siomiz/ubuntu-ttyjs", "description": "non-root tty.js running in _/node (ubuntu)" },
{ "name": "cedvan/ubuntu", "description": "" },
{ "name": "dlin/ubuntu-ssh", "description": "" },
{ "name": "neroinc/ubuntu-golang-crosscompile", "description": "" },
{ "name": "ganiutomo/ubuntu-jmeter", "description": "" },
{ "name": "dlin/ubuntu-duckbox", "description": "" },
{ "name": "exoplatform/ubuntu-jdk7-exo", "description": "" },
{ "name": "exoplatform/ubuntu-jdk7-exo-chat", "description": "" },
{ "name": "norsystechteam/ubuntu", "description": "" },
{ "name": "inftec/ubuntu-java", "description": "" },
{ "name": "silvershell/ubuntu", "description": "" },
{ "name": "ggtools/busybox-ubuntu", "description": "Busybox ubuntu version with extra goodies" },
{ "name": "jmoati/ubuntu-dev", "description": "" },
{ "name": "onesysadmin/ubuntu-postfix", "description": "" },
{ "name": "reliableembeddedsystems/ubuntu-base", "description": "I use this as a base for my yocto stuff" },
{ "name": "saltstack/ubuntu-12.04-minimal", "description": "" },
{ "name": "exoplatform/ubuntu-jdk7", "description": "" },
{ "name": "jayofdoom/docker-ubuntu-14.04", "description": "This is a simple docker image that updates the stackforge/ubuntu:13.10 image to Ubuntu Trusty." },
{ "name": "partlab/ubuntu-droneci", "description": "Docker image to run an out of the box Drone CI" },
{ "name": "saltstack/ubuntu-14.04-minimal", "description": "" },
{ "name": "tutum/ubuntu-raring", "description": "DEPRECATED: Please use `tutum/ubuntu:raring` or `tutum/ubuntu:13.04` instead." },
{ "name": "teamrock/ubuntu", "description": "" },
{ "name": "jgeiger/ubuntu", "description": "" },
{ "name": "rolymobile/ubuntu", "description": "" },
{ "name": "pinterb/ubuntu-perl", "description": "" },
{ "name": "vvoronin/ubuntu-tools", "description": "" },
{ "name": "saltstack/ubuntu-14.04", "description": "" },
{ "name": "panoptix/ubuntu", "description": "" },
{ "name": "tutum/ubuntu-trusty", "description": "DEPRECATED: Please use `tutum/ubuntu:trusty` or `tutum/ubuntu:14.04` instead." },
{ "name": "eternnoir/ubuntu-java", "description": "" },
{ "name": "vubui/ubuntu", "description": "" },
{ "name": "mullnerz/ubuntu", "description": "" },
{ "name": "dockitapp/single-redis-ubuntu", "description": "" },
{ "name": "sbminimal/docker-ubuntu-apache-php-compo", "description": "Minimal Docker Image for Apache+PHP+composer (based on minimal ubuntu)" },
{ "name": "crsmithdev/ubuntu", "description": "" },
{ "name": "alexisno/ubuntu-dev", "description": "" },
{ "name": "frodenas/ubuntu", "description": "A Docker Image for Ubuntu" },
{ "name": "zlim/ubuntu-dev", "description": "" },
{ "name": "jinglemansweep/ubuntu-base", "description": "Standard Ubuntu Trusty (14.04 LTS) container with a few useful packages pre-installed." },
{ "name": "labstack/ubuntu", "description": "" },
{ "name": "larrycai/ubuntu-sshd", "description": "" },
{ "name": "leanix/ubuntu-ansible", "description": "" },
{ "name": "undancer/ubuntu", "description": "" },
{ "name": "st2py/ubuntu", "description": "" },
];

var ancestries = _.map(_.range(5), function() {
	return _.sample('0123456789abcdef0123456789abcdef0123456789abcdef', 40).join('');
});

_.forEach(repositories, function(repository) {
	repository._tags = [
		{ name: 'latest', layer: ancestries[0] },
		{ name: '1.0.1', layer: ancestries[1] },
		{ name: '2.0.0', layer: ancestries[2] }
	];
});

repositories = _.indexBy(repositories, 'name');

var MemoryRegistry = function(repositories, ancestries) {
	this.repositories = repositories;
	this.ancestries = ancestries;
};

MemoryRegistry.prototype.search = function(query, page, pageSize) {
	page = page || 1;
	pageSize = pageSize || 25;
	var results = _.filter(this.repositories, function(repository) {
		return repository.name.indexOf(query) >= 0;
	});
	var resultPage = _.map(results.slice((page - 1) * pageSize, page * pageSize), function(result) {
		return _.omit(result, function(value, key) { return key.indexOf('_') === 0; });
	});
	return {
		'num_pages': Math.ceil(results.length / pageSize),
		'num_results': results.length,
		'page_size': pageSize,
		'query': query,
		'page': page,
		'results': resultPage,
	};
};

MemoryRegistry.prototype.tags = function(repositoryName) {
	return this.repositories[repositoryName]._tags;
};

MemoryRegistry.prototype.deleteRepository = function(repositoryName) {
	delete this.repositories[repositoryName];
};

MemoryRegistry.prototype.deleteTag = function(repositoryName, tagName) {
	_.remove(this.repositories[repositoryName]._tags, function(tag) { return tag.name === tagName; });
};

MemoryRegistry.prototype.image = function(id) {
	return {
		'id': id,
		'parent': this.ancestries[this.ancestries.indexOf(id) + 1],
		'created': '2011-01-01',
		'architecture': 'amd64',
		'os': 'linux',
		'Size': 501,
	};
};

MemoryRegistry.prototype.ancestry = function(imageId) {
	return this.ancestries.slice(this.ancestries.indexOf(imageId));
};

var FakeClient = function(registry) {
	this.registry = registry;
	this.patterns = [];
	this.defaultPattern = {
		code: 404,
		action: _.constant('Not found'),
	};
};

FakeClient.prototype.request = function(options, callback) {
	var args;
	var path = options.path.replace(/\/*\?.*$/, '');
	var pattern = _.find(this.patterns, function(pattern) {
		return !!(args = path.match(pattern.match)) && options.method.indexOf(pattern.method) >= 0;
	}) || this.defaultPattern;

	var self = this;
	callback({
		statusCode: pattern.code,
		headers: { 'content-type': 'application/json' },
		on: function(trigger, callback) {
			if (trigger === 'data') {
				var data = JSON.stringify(pattern.action(self.registry, args, options));
				callback(data);
			} else if (trigger === 'end') {
				callback();
			}
			return this;
		},
	});
	return {
		end: function() { return this; },
		on: function() { return this; },
		setTimeout: function() { return this; },
	};
};

var escapeRegex = function(text) {
	return text.replace(/[.*+? ${}()|[\]\\]/g, '\\$&');
};

FakeClient.prototype.when = function(match, method) {
	method = method || 'GET';
	match = _.reduce(match.split('**'), function(a, b, c, d) {
		return _.map(d, function(dd) {
			return _.reduce(dd.split('*'), function(e1, e2, e3, e4) {
				return _.map(e4, escapeRegex).join('([^/]+)');
			});
		}).join('(.*)');
	}, '');
	var self = this;
	return {
		then: function(response, code) {
			self.patterns.push({
				match: match,
				method: _.isArray(method) ? method : [method],
				code: code || 200,
				action: _.isFunction(response) ? response : _.constant(response),
			});
			return self;
		}
	};
};

module.exports = new FakeClient(new MemoryRegistry(repositories, ancestries))
.when('/v1/search').then(function (registry, args, options) {
	var query = querystring.parse(options.path.match(/.*\?(.*)/)[1] || '');
	return registry.search(query.q, query.page, query.n);
})
.when('/v1/repositories/**/tags').then(function(registry, args) {
	return registry.tags(args[1]);
})
.when('/v1/repositories/**/tags/*', 'DELETE').then(function(registry, args) {
	registry.deleteTag(args[1], args[2]);
	return "";
})
.when('/v1/repositories/**', 'DELETE').then(function(registry, args) {
	registry.deleteRepository(args[1]);
	return "";
})
.when('/v1/images/*/json').then(function(registry, args) {
	return registry.image(args[1]);
})
.when('/v1/images/*/ancestry').then(function(registry, args) {
	return registry.ancestry(args[1]);
});
<|endoftext|>


<commit_before>(function() {
  var Controller = function(id, callback) {
    if (!id) {
      console.error("ERROR: No id given");
      return;
    }

    var path = "/map/" + id;

    // The renderer renders everything in the #map div
    this.renderer = new Renderer(document.getElementById("map"));
    this.hasInitialized = false;

    console.log("Just finished creating renderer");
    $.get(path, function(data) {
      this.data = data;
      this.reset(data, callback);
    }.bind(this));
    window.initEditor(this);
  };

  Controller.prototype.parseGoal = function (goal, player1, player2) {
    for (key in goal) {
      var location = {};
      location['row'] = goal[key][0];
      location['column'] = goal[key][1];
      if (key == "1") {
        player1.setGoal(location);
      } else if (key == "2") {
        player2.setGoal(location);
      }
    }
  }
  Controller.prototype.reset = function(data, callback) {
    this.id = data.id;
    this.title = data.title;
    this.description = data.description;
    $("#description .title").text(this.title);
    $("#description .description").text(this.description);
    this.objects = data.objects;
    this.goal = data.goal;

    var obj = parseMap(data.map);
    this.map = new Map(obj.map, data.width, data.height);
    this.switches = obj.switches;
    this.flags = obj.flags;
    this.fogs = obj.fogs;

    if (this.player1) {
      this.player1.removeSelf();
    }
    if (this.player2) {
      this.player2.removeSelf();
    }

    this.hasInitialized = false;

    this.player1 = obj.players["1"];
    this.player2 = obj.players["2"];

    var goal = this.parseGoal(data.goal, this.player1, this.player2);

    this.renderer.initializeTiles(this.map);
    // this.renderer.initializeSwitches(this.switches);
    this.renderer.initializeFlags(this.flags);
    this.renderer.initializeFogs(this.fogs);
    this.renderer.initializePlayer(this.player1);
    this.renderer.initializePlayer(this.player2);
    this.renderer.render();

    if (callback) {
      callback();
    }
  };

  /**
   * To be called by the main JS, script.js
   */
  Controller.prototype.render = function() {
    // The tiles only need to be rendered once
    if (!this.hasInitialized) {
      this.renderer.initialRender(this.map, this.fogs, this.flags);
      this.hasInitialized = true;
    }
    this.renderer.render();
  };

  Controller.prototype.animate = function() {
    this.renderer.animate(this.player1, this.player2);
  };

  Controller.prototype.performActions = function(f1, f2) {
    var b1;
    var b2;
    var anim1;
    var anim2;

    if (f1) {
      b1 = anim1 = f1.apply(this.player1);
    }
    if (f2) {
      b2 = anim2 = f2.apply(this.player2);
    }

    function anim() {
      if (b1) {
        b1 = anim1.apply(this.player1);
      }
      if (b2) {
        b2 = anim2.apply(this.player2);
      }
      if (!b1 && !b2) {
        this.player1.resetState();
        this.player2.resetState();
        this.renderer.render();
        return;
      }
      this.renderer.render();
      requestAnimationFrame(anim.bind(this));
    };
    anim.apply(this);
    this.renderer.render();
  };

  Controller.prototype.run = function(code) {
    this.stop();
    this.reset(this.data);
    this.numTicks = 0;
    setStatementCount(0);
    var controller = this;
    this.workerDfds = [Q.defer(), Q.defer()];
    this.workers = _.map(code, function(item, i) {
      var worker = new Worker('js/userCodeWorker.js');
      var id = '#console' + i;
      worker.addEventListener("message", function(e) {
        if (e.data.type === 'log') {
          logResult(e.data.value, id);
        } else if (e.data.type === 'action') {
          if (!e.data.value.done) {
            logResult(e.data.value.value, id); // TODO change to process data
            controller.workerDfds[i].resolve(e.data.value.value);
          } else {
            controller.workerDfds[i].reject();
          }
        }
      });
      worker.postMessage({type: 'begin', value: item});
      worker.postMessage({type: 'next', conditionals: controller.getConditionals(i)})
      return worker;
    });
    setSpinner(true);

    Q.spread(_.map(this.workerDfds, function(dfd) {
      return dfd.promise;
    }), this.tick, setSpinner);
  };

  Controller.prototype.tick = function(result1, result2) {
    var controller = this.controller;
    if (controller.player1.isOnGoal() && controller.player2.isOnGoal()) {
      onWin(controller.levelId, controller.numTicks);
      return;
    }
    controller.numTicks++;
    setStatementCount(controller.numTicks);
    console.log(result1, result2);
    try {
      controller.performActions(controller.functions[result1], controller.functions[result2]);
    } catch (ex) {
      logResult(ex.toString(), '#console' + 0);
      logResult(ex.toString(), '#console' + 1);
      controller.stop();
    }
    controller.workerDfds = [Q.defer(), Q.defer()];
    Q.spread(_.map(controller.workerDfds, function(dfd) {
      return dfd.promise;
    }), controller.tick, setSpinner);
    setTimeout(function() {
      _.each(controller.workers, function(worker, i) {
        worker.postMessage({type: 'next', conditionals: controller.getConditionals(i)});
      });
    }, 1000);
  };

  Controller.prototype.stop = function() {
    _.each(this.workers, function(worker) {
      worker.terminate();
    });
    this.workers = [];
    setSpinner(false);
  };

  Controller.prototype.isBlocked = function(player) {
    return !player.isValidLocation(player.getCoordinateForward());
  }

  Controller.prototype.getConditionals = function(playerId) {
    var player = playerId == 0 ? this.player1 : this.player2;
    return {
      isBlocked: this.isBlocked(player),
      isOnGoal: player.isOnGoal()
    };
  };

  Controller.prototype.functions = {
    moveForward: Player.prototype.moveForward,
    turnLeft: Player.prototype.turnLeft,
    turnRight: Player.prototype.turnRight
  };

  function setSpinner(visible) {
    $('#executing').css('visibility', visible ? 'visible' : 'hidden');
    $('#statementCount').css('visibility', visible ? 'visible' : 'hidden');
  }

  function setStatementCount(count) {
    $('#statementCount').text(count);
  }

  function logResult(message, id) {
    $(id).val($(id).val() + message + '\n');
  }

  function onWin(levelId, statementCount) {
    $('#winModal').modal();
    $('#winModalBody').text('You successfully completed level ' + levelId
      + ' using ' + (statementCount || 0) + ' moves!');
  }

  window.Controller = Controller;
}) ();
<commit_msg>Move win check to after move<commit_after>(function() {
  var Controller = function(id, callback) {
    if (!id) {
      console.error("ERROR: No id given");
      return;
    }

    var path = "/map/" + id;

    // The renderer renders everything in the #map div
    this.renderer = new Renderer(document.getElementById("map"));
    this.hasInitialized = false;

    console.log("Just finished creating renderer");
    $.get(path, function(data) {
      this.data = data;
      this.reset(data, callback);
    }.bind(this));
    window.initEditor(this);
  };

  Controller.prototype.parseGoal = function (goal, player1, player2) {
    for (key in goal) {
      var location = {};
      location['row'] = goal[key][0];
      location['column'] = goal[key][1];
      if (key == "1") {
        player1.setGoal(location);
      } else if (key == "2") {
        player2.setGoal(location);
      }
    }
  }
  Controller.prototype.reset = function(data, callback) {
    this.id = data.id;
    this.title = data.title;
    this.description = data.description;
    $("#description .title").text(this.title);
    $("#description .description").text(this.description);
    this.objects = data.objects;
    this.goal = data.goal;

    var obj = parseMap(data.map);
    this.map = new Map(obj.map, data.width, data.height);
    this.switches = obj.switches;
    this.flags = obj.flags;
    this.fogs = obj.fogs;

    if (this.player1) {
      this.player1.removeSelf();
    }
    if (this.player2) {
      this.player2.removeSelf();
    }

    this.hasInitialized = false;

    this.player1 = obj.players["1"];
    this.player2 = obj.players["2"];

    var goal = this.parseGoal(data.goal, this.player1, this.player2);

    this.renderer.initializeTiles(this.map);
    // this.renderer.initializeSwitches(this.switches);
    this.renderer.initializeFlags(this.flags);
    this.renderer.initializeFogs(this.fogs);
    this.renderer.initializePlayer(this.player1);
    this.renderer.initializePlayer(this.player2);
    this.renderer.render();

    if (callback) {
      callback();
    }
  };

  /**
   * To be called by the main JS, script.js
   */
  Controller.prototype.render = function() {
    // The tiles only need to be rendered once
    if (!this.hasInitialized) {
      this.renderer.initialRender(this.map, this.fogs, this.flags);
      this.hasInitialized = true;
    }
    this.renderer.render();
  };

  Controller.prototype.animate = function() {
    this.renderer.animate(this.player1, this.player2);
  };

  Controller.prototype.performActions = function(f1, f2) {
    var b1;
    var b2;
    var anim1;
    var anim2;

    if (f1) {
      b1 = anim1 = f1.apply(this.player1);
    }
    if (f2) {
      b2 = anim2 = f2.apply(this.player2);
    }

    function anim() {
      if (b1) {
        b1 = anim1.apply(this.player1);
      }
      if (b2) {
        b2 = anim2.apply(this.player2);
      }
      if (!b1 && !b2) {
        this.player1.resetState();
        this.player2.resetState();
        this.renderer.render();
        return;
      }
      this.renderer.render();
      requestAnimationFrame(anim.bind(this));
    };
    anim.apply(this);
    this.renderer.render();
  };

  Controller.prototype.run = function(code) {
    this.stop();
    this.reset(this.data);
    this.numTicks = 0;
    setStatementCount(0);
    var controller = this;
    this.workerDfds = [Q.defer(), Q.defer()];
    this.workers = _.map(code, function(item, i) {
      var worker = new Worker('js/userCodeWorker.js');
      var id = '#console' + i;
      worker.addEventListener("message", function(e) {
        if (e.data.type === 'log') {
          logResult(e.data.value, id);
        } else if (e.data.type === 'action') {
          if (!e.data.value.done) {
            logResult(e.data.value.value, id); // TODO change to process data
            controller.workerDfds[i].resolve(e.data.value.value);
          } else {
            controller.workerDfds[i].reject();
          }
        }
      });
      worker.postMessage({type: 'begin', value: item});
      worker.postMessage({type: 'next', conditionals: controller.getConditionals(i)})
      return worker;
    });
    setSpinner(true);

    Q.spread(_.map(this.workerDfds, function(dfd) {
      return dfd.promise;
    }), this.tick, setSpinner);
  };

  Controller.prototype.tick = function(result1, result2) {
    var controller = this.controller;
    controller.numTicks++;
    setStatementCount(controller.numTicks);
    console.log(result1, result2);
    try {
      controller.performActions(controller.functions[result1], controller.functions[result2]);
    } catch (ex) {
      logResult(ex.toString(), '#console' + 0);
      logResult(ex.toString(), '#console' + 1);
      controller.stop();
    }
    if (controller.player1.isOnGoal() && controller.player2.isOnGoal()) {
      controller.stop();
      onWin(controller.levelId, controller.numTicks);
      return;
    }
    controller.workerDfds = [Q.defer(), Q.defer()];
    Q.spread(_.map(controller.workerDfds, function(dfd) {
      return dfd.promise;
    }), controller.tick, setSpinner);
    setTimeout(function() {
      _.each(controller.workers, function(worker, i) {
        worker.postMessage({type: 'next', conditionals: controller.getConditionals(i)});
      });
    }, 1000);
  };

  Controller.prototype.stop = function() {
    _.each(this.workers, function(worker) {
      worker.terminate();
    });
    this.workers = [];
    setSpinner(false);
  };

  Controller.prototype.isBlocked = function(player) {
    return !player.isValidLocation(player.getCoordinateForward());
  }

  Controller.prototype.getConditionals = function(playerId) {
    var player = playerId == 0 ? this.player1 : this.player2;
    return {
      isBlocked: this.isBlocked(player),
      isOnGoal: player.isOnGoal()
    };
  };

  Controller.prototype.functions = {
    moveForward: Player.prototype.moveForward,
    turnLeft: Player.prototype.turnLeft,
    turnRight: Player.prototype.turnRight
  };

  function setSpinner(visible) {
    $('#executing').css('visibility', visible ? 'visible' : 'hidden');
    $('#statementCount').css('visibility', visible ? 'visible' : 'hidden');
  }

  function setStatementCount(count) {
    $('#statementCount').text(count);
  }

  function logResult(message, id) {
    $(id).val($(id).val() + message + '\n');
  }

  function onWin(levelId, statementCount) {
    $('#winModal').modal();
    $('#winModalBody').text('You successfully completed level ' + levelId
      + ' using ' + (statementCount || 0) + ' moves!');
  }

  window.Controller = Controller;
}) ();
<|endoftext|>


<commit_before>var express = require('express');
var router = express.Router();

router.get('/delivery-receipt-webhook', function(req, res) {
    handleWebhook(req.query, res);
});

router.post('/delivery-receipt-webhook', function(req, res) {
    handleWebhook(req.body, res);
});

function handleWebhook(params, res) {
    if (!params['status'] || !params['messageId']) {
        console.log('This is not a delivery receipt');
    } else {
        //This is a DLR, check that your message has been delivered correctly
        if (params['status'] !== 'delivered') {
            console.log("Fail:", params['status'], ": ", params['err-code']);
        } else {
            console.log("Success");
            console.log(params);
          /*
            * The following parameters in the delivery receipt should match the ones
            * in your request:
            * Request - from, dlr - to\n
            * Response - message-id, dlr - messageId
            * Request - to, Responese - to, dlr - msisdn
            * Request - client-ref, dlr - client-ref
           */
        }
    }
    res.sendStatus(200);
}

module.exports = router;<commit_msg>find out more about sms params<commit_after>var express = require('express');
var router = express.Router();

router.get('/delivery-receipt-webhook', function(req, res) {
    console.log(req.query);
    handleWebhook(req.query, res);
});

router.post('/delivery-receipt-webhook', function(req, res) {
    console.log(req.body);
    handleWebhook(req.body, res);
});

function handleWebhook(params, res) {
    if (!params['status'] || !params['messageId']) {
        console.log('This is not a delivery receipt');
    } else {
        //This is a DLR, check that your message has been delivered correctly
        if (params['status'] !== 'delivered') {
            console.log("Fail:", params['status'], ": ", params['err-code']);
        } else {
            console.log("Success");
            console.log(params);
          /*
            * The following parameters in the delivery receipt should match the ones
            * in your request:
            * Request - from, dlr - to\n
            * Response - message-id, dlr - messageId
            * Request - to, Responese - to, dlr - msisdn
            * Request - client-ref, dlr - client-ref
           */
        }
    }
    res.sendStatus(200);
}

module.exports = router;<|endoftext|>


<commit_before>"use strict";

jsns.define("edity.widgets.treemenu.editorSync", [
    "htmlrest.lateboundeventhandler"
], function (exports, module, LateBoundEvent) {
    var itemAdded = new LateBoundEvent();
    var createRootNodeControls = new LateBoundEvent();

    function fireItemAdded(saveUrl, itemData, bindListenerCb) {
        itemAdded.fire(saveUrl, itemData, bindListenerCb);
    }
    exports.fireItemAdded = fireItemAdded;

    function fireCreateRootNodeControls(controllerElementName, menuData, updateCb, saveUrl, parentBindings) {
        createRootNodeControls.fire(controllerElementName, menuData, updateCb, saveUrl, parentBindings);
    }
    exports.fireCreateRootNodeControls = fireCreateRootNodeControls;

    function setEditorListener(value) {
        //Important order, need to create root nodes first
        createRootNodeControls.modifier.add(value, value.createRootNodeControls);
        itemAdded.modifier.add(value, value.itemAdded);
    }
    exports.setEditorListener = setEditorListener;
});

jsns.define("edity.widgets.treemenu.controller", [
    "htmlrest.storage",
    "htmlrest.rest",
    "htmlrest.controller",
    "edity.widgets.treemenu.editorSync"
], function (exports, module, storage, rest, controller, editorSync) {

    /**
     * This function builds a controller that handles a tree menu on the page.
     * @param {type} bindings
     */
    function TreeMenuController(bindings) {
        var rootModel = bindings.getModel('children');
        var config = bindings.getConfig();
        var editMode = config["treemenu-editmode"] === 'true';
        var version = config["treemenu-version"];

        var ajaxurl = rootModel.getSrc();
        var getNextId = (function () {
            var i = -1;
            return function () {
                return ++i;
            }
        })();

        var menuStorageId = 'treemenu-cache-' + ajaxurl;
        var sessionData = storage.getSessionJson(menuStorageId, null);
        var menuCache = null;
        var menuData = null;
        var createdItems = {
        };
        window.onbeforeunload = function (e) {
            if (editMode) {
                removeParents(menuData);
            }
            storage.storeJsonInSession(menuStorageId, {
                cache: menuCache,
                data: menuData,
                version: version
            });
        };

        if (sessionData === null || sessionData.version !== version) {
            //No data, get it
            menuCache = {
            };
            rest.get(ajaxurl, function (data) {
                initialSetup(data);
            });
        }
        else {
            //Use what we had
            menuCache = sessionData.cache;
            initialSetup(sessionData.data);
        }

        function initialSetup(data) {
            menuData = data;
            if (menuData !== null) {
                if (data['menuItemId'] === undefined) {
                    createIds(data);
                }

                if (editMode) {
                    findParents(data, null);
                    editorSync.fireCreateRootNodeControls("treeMenuEditRoot", menuData, rebuildMenu, ajaxurl, bindings); //This isn't really right, will create controllers for all tree menus on the page, need to single out somehow
                }

                var menuCacheInfo = getMenuCacheInfo(data.menuItemId);
                buildMenu(bindings, menuCacheInfo, menuData, false);
            }
        }

        function rebuildMenu() {
            createdItems = {
            };
            var childModel = bindings.getModel('children');
            childModel.setData([]);
            var menuCacheInfo = getMenuCacheInfo(menuData.menuItemId);
            buildMenu(bindings, menuCacheInfo, menuData, false);
        }

        function createIds(data) {
            data.menuItemId = getNextId();
            var folders = data.folders;
            for (var i = 0; i < folders.length; ++i) {
                //Recursion, I don't care, how nested is your menu that you run out of stack space here? Can a user really use that?
                createIds(folders[i]);
            }
        }

        function findParents(data, parent) {
            data.parent = parent;
            var folders = data.folders;
            for (var i = 0; i < folders.length; ++i) {
                //Recursion, I don't care, how nested is your menu that you run out of stack space here? Can a user really use that?
                findParents(folders[i], data);
            }
            var links = data.links;
            for (var i = 0; i < links.length; ++i) {
                links[i].parent = data;
            }
        }

        function removeParents(data) {
            delete data.parent;
            var folders = data.folders;
            for (var i = 0; i < folders.length; ++i) {
                //Recursion, I don't care, how nested is your menu that you run out of stack space here? Can a user really use that?
                removeParents(folders[i]);
            }
            var links = data.links;
            for (var i = 0; i < links.length; ++i) {
                delete links[i].parent;
            }
        }

        function getMenuCacheInfo(parentCategoryId) {
            if (!menuCache.hasOwnProperty(parentCategoryId)) {
                menuCache[parentCategoryId] = {
                    expanded: false,
                    id: parentCategoryId
                };
            }
            return menuCache[parentCategoryId];
        }

        function buildMenu(parentBindings, menuCacheInfo, folder, autoHide) {
            if (autoHide === undefined) {
                autoHide = true;
            }

            if (!createdItems[menuCacheInfo.id]) {
                var parentModel = parentBindings.getModel('children');
                var list = null;
                parentModel.setData({
                }, function (created) {
                    list = created;
                });
                createdItems[menuCacheInfo.id] = true;

                var foldersModel = list.getModel('folders');
                var linksModel = list.getModel('links');

                foldersModel.setData(folder.folders, function (folderComponent, data) {
                    var id = data.menuItemId;
                    var menuCacheInfo = getMenuCacheInfo(id);

                    var listener = {
                        toggleMenuItem: function (evt) {
                            evt.preventDefault();

                            buildMenu(folderComponent, menuCacheInfo, data);
                            toggleMenu(menuCacheInfo, folderComponent.getToggle('children'));
                        }
                    };
                    if (editMode) {
                        editorSync.fireItemAdded(ajaxurl, data, function (editListener) { folderComponent.setListener(editListener); });
                    }
                    folderComponent.setListener(listener);

                    if (menuCacheInfo.expanded) {
                        buildMenu(folderComponent, menuCacheInfo, data, autoHide);
                    }
                });

                if (editMode) {
                    linksModel.setData(folder.links, function (component, data) {
                        var listener = {
                        };
                        editorSync.fireItemAdded(ajaxurl, data, function (editListener) { component.setListener(editListener); });
                        component.setListener(listener);
                    });
                }
                else {
                    linksModel.setData(folder.links);
                }
            }
        }

        function toggleMenu(menuCacheInfo, toggle, transitionTime) {
            if (transitionTime === undefined) {
                transitionTime = 200;
            }

            if (menuCacheInfo.expanded) {
                menuCacheInfo.expanded = false;
                toggle.off();
            }
            else {
                menuCacheInfo.expanded = true;
                toggle.on();
            }
        }
    }

    exports.TreeMenuController = TreeMenuController;
});

jsns.run([
    "htmlrest.controller",
    "edity.widgets.treemenu.controller"
], function (exports, module, controller, treemenu) {
    controller.create("treeMenu", treemenu.TreeMenuController);
});<commit_msg>Made treemenu widget able to handle unified folders and links.<commit_after>"use strict";

jsns.define("edity.widgets.treemenu.editorSync", [
    "htmlrest.lateboundeventhandler"
], function (exports, module, LateBoundEvent) {
    var itemAdded = new LateBoundEvent();
    var createRootNodeControls = new LateBoundEvent();

    function fireItemAdded(saveUrl, itemData, bindListenerCb) {
        itemAdded.fire(saveUrl, itemData, bindListenerCb);
    }
    exports.fireItemAdded = fireItemAdded;

    function fireCreateRootNodeControls(controllerElementName, menuData, updateCb, saveUrl, parentBindings) {
        createRootNodeControls.fire(controllerElementName, menuData, updateCb, saveUrl, parentBindings);
    }
    exports.fireCreateRootNodeControls = fireCreateRootNodeControls;

    function setEditorListener(value) {
        //Important order, need to create root nodes first
        createRootNodeControls.modifier.add(value, value.createRootNodeControls);
        itemAdded.modifier.add(value, value.itemAdded);
    }
    exports.setEditorListener = setEditorListener;
});

jsns.define("edity.widgets.treemenu.controller", [
    "htmlrest.storage",
    "htmlrest.rest",
    "htmlrest.controller",
    "edity.widgets.treemenu.editorSync"
], function (exports, module, storage, rest, controller, editorSync) {

    function isFolder(menuItem) {
        return !menuItem.hasOwnProperty("link");
    }

    /**
     * This function builds a controller that handles a tree menu on the page.
     * @param {type} bindings
     */
    function TreeMenuController(bindings) {
        var rootModel = bindings.getModel('children');
        var config = bindings.getConfig();
        var editMode = false;//config["treemenu-editmode"] === 'true';
        var version = config["treemenu-version"];

        var ajaxurl = rootModel.getSrc();
        var getNextId = (function () {
            var i = -1;
            return function () {
                return ++i;
            }
        })();

        var menuStorageId = 'treemenu-cache-' + ajaxurl;
        var sessionData = storage.getSessionJson(menuStorageId, null);
        var menuCache = null;
        var menuData = null;
        var createdItems = {
        };
        window.onbeforeunload = function (e) {
            if (editMode) {
                removeParents(menuData);
            }
            storage.storeJsonInSession(menuStorageId, {
                cache: menuCache,
                data: menuData,
                version: version
            });
        };

        if (sessionData === null || sessionData.version !== version) {
            //No data, get it
            menuCache = {
            };
            rest.get(ajaxurl, function (data) {
                initialSetup(data);
            });
        }
        else {
            //Use what we had
            menuCache = sessionData.cache;
            initialSetup(sessionData.data);
        }

        function initialSetup(data) {
            menuData = data;
            if (menuData !== null) {
                if (data['menuItemId'] === undefined) {
                    createIds(data);
                }

                if (editMode) {
                    findParents(data, null);
                    editorSync.fireCreateRootNodeControls("treeMenuEditRoot", menuData, rebuildMenu, ajaxurl, bindings); //This isn't really right, will create controllers for all tree menus on the page, need to single out somehow
                }

                var menuCacheInfo = getMenuCacheInfo(data.menuItemId);
                buildMenu(bindings, menuCacheInfo, menuData, false);
            }
        }

        function rebuildMenu() {
            createdItems = {
            };
            var childModel = bindings.getModel('children');
            childModel.setData([]);
            var menuCacheInfo = getMenuCacheInfo(menuData.menuItemId);
            buildMenu(bindings, menuCacheInfo, menuData, false);
        }

        function createIds(data) {
            if (isFolder(data)) {
                data.menuItemId = getNextId();
                var children = data.children;
                for (var i = 0; i < children.length; ++i) {
                    //Recursion, I don't care, how nested is your menu that you run out of stack space here? Can a user really use that?
                    createIds(children[i]);
                }
            }
        }

        function findParents(data, parent) {
            data.parent = parent;
            var children = data.children;
            for (var i = 0; i < children.length; ++i) {
                //Recursion, I don't care, how nested is your menu that you run out of stack space here? Can a user really use that?
                findParents(children[i], data);
            }
        }

        function removeParents(data) {
            delete data.parent;
            var children = data.children;
            for (var i = 0; i < children.length; ++i) {
                //Recursion, I don't care, how nested is your menu that you run out of stack space here? Can a user really use that?
                removeParents(children[i]);
            }
        }

        function getMenuCacheInfo(parentCategoryId) {
            if (!menuCache.hasOwnProperty(parentCategoryId)) {
                menuCache[parentCategoryId] = {
                    expanded: false,
                    id: parentCategoryId
                };
            }
            return menuCache[parentCategoryId];
        }

        function buildMenu(parentBindings, menuCacheInfo, folder, autoHide) {
            if (autoHide === undefined) {
                autoHide = true;
            }

            if (!createdItems[menuCacheInfo.id]) {
                var parentModel = parentBindings.getModel('children');
                var list = null;
                parentModel.setData({
                }, function (created) {
                    list = created;
                });
                createdItems[menuCacheInfo.id] = true;

                var childItemsModel = list.getModel('childItems');

                childItemsModel.setData(folder.children, function (folderComponent, data) {
                    var id = data.menuItemId;
                    var menuCacheInfo = getMenuCacheInfo(id);

                    var listener = {
                        toggleMenuItem: function (evt) {
                            evt.preventDefault();

                            buildMenu(folderComponent, menuCacheInfo, data);
                            toggleMenu(menuCacheInfo, folderComponent.getToggle('children'));
                        }
                    };
                    if (editMode) {
                        editorSync.fireItemAdded(ajaxurl, data, function (editListener) { folderComponent.setListener(editListener); });
                    }
                    folderComponent.setListener(listener);

                    if (menuCacheInfo.expanded) {
                        buildMenu(folderComponent, menuCacheInfo, data, autoHide);
                    }
                }, function (row) {
                    if (!isFolder(row)) {
                        return "link";
                    }
                });
            }
        }

        function toggleMenu(menuCacheInfo, toggle, transitionTime) {
            if (transitionTime === undefined) {
                transitionTime = 200;
            }

            if (menuCacheInfo.expanded) {
                menuCacheInfo.expanded = false;
                toggle.off();
            }
            else {
                menuCacheInfo.expanded = true;
                toggle.on();
            }
        }
    }

    exports.TreeMenuController = TreeMenuController;
});

jsns.run([
    "htmlrest.controller",
    "edity.widgets.treemenu.controller"
], function (exports, module, controller, treemenu) {
    controller.create("treeMenu", treemenu.TreeMenuController);
});<|endoftext|>


<commit_before>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * The examples provided by Facebook are for non-commercial testing and
 * evaluation purposes only.
 *
 * Facebook reserves all rights not expressly granted.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
 * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  *
 *
 * @providesModule SwipeableQuickActionButton
 * @flow
 */
'use strict';

const Image = require('Image');
const React = require('React');
const StyleSheet = require('StyleSheet');
const Text = require('Text');
const TouchableHighlight = require('TouchableHighlight');
const View = require('View');

const {PropTypes} = React;

const SwipeableQuickActionButton = React.createClass({
  propTypes: {
    accessibilityLabel: PropTypes.string,
    imageSource: Image.propTypes.source.isRequired,
    imageStyle: Image.propTypes.style,
    onPress: PropTypes.func,
    style: View.propTypes.style,
    testID: PropTypes.string,
    text: PropTypes.string,
    textStyle: Text.propTypes.style,
  },

  render(): ?ReactElement {
    if (!this.props.imageSource && !this.props.text) {
      return null;
    }

    return (
      <TouchableHighlight
        onPress={this.props.onPress}
        testID={this.props.testID}
        underlayColor="transparent">
        <View style={[styles.button, this.props.style]}>
          <Image
            accessibilityLabel={this.props.accessibilityLabel}
            source={this.props.imageSource}
            style={[styles.image, this.props.imageStyle]}
          />
          <Text style={[styles.text, this.props.textStyle]}>
            {this.props.text}
          </Text>
        </View>
      </TouchableHighlight>
    );
  },
});

const styles = StyleSheet.create({
  button: {
    alignItems: 'center',
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    width: 76,
  },
  image: {
    height: 33,
    width: 33,
  },
  text: {
    color: '#ffffff',
    fontSize: 12,
    textAlign: 'center', // For Android to align properly
  },
});

module.exports = SwipeableQuickActionButton;
<commit_msg>Top align quick action buttons<commit_after>/**
 * Copyright (c) 2013-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 *
 * The examples provided by Facebook are for non-commercial testing and
 * evaluation purposes only.
 *
 * Facebook reserves all rights not expressly granted.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL
 * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  *
 *
 * @providesModule SwipeableQuickActionButton
 * @flow
 */
'use strict';

const Image = require('Image');
const React = require('React');
const StyleSheet = require('StyleSheet');
const Text = require('Text');
const TouchableHighlight = require('TouchableHighlight');
const View = require('View');

const {PropTypes} = React;

const SwipeableQuickActionButton = React.createClass({
  propTypes: {
    accessibilityLabel: PropTypes.string,
    imageSource: Image.propTypes.source.isRequired,
    imageStyle: Image.propTypes.style,
    onPress: PropTypes.func,
    style: View.propTypes.style,
    testID: PropTypes.string,
    text: PropTypes.string,
    textStyle: Text.propTypes.style,
  },

  render(): ?ReactElement {
    if (!this.props.imageSource && !this.props.text) {
      return null;
    }

    return (
      <TouchableHighlight
        onPress={this.props.onPress}
        testID={this.props.testID}
        underlayColor="transparent">
        <View style={[styles.button, this.props.style]}>
          <Image
            accessibilityLabel={this.props.accessibilityLabel}
            source={this.props.imageSource}
            style={[styles.image, this.props.imageStyle]}
          />
          <Text style={[styles.text, this.props.textStyle]}>
            {this.props.text}
          </Text>
        </View>
      </TouchableHighlight>
    );
  },
});

const styles = StyleSheet.create({
  button: {
    alignItems: 'center',
    flex: 1,
    flexDirection: 'column',
    width: 76,
  },
  image: {
    height: 33,
    width: 33,
  },
  text: {
    color: '#ffffff',
    fontSize: 12,
    textAlign: 'center', // For Android to align properly
  },
});

module.exports = SwipeableQuickActionButton;
<|endoftext|>