<commit_before>var AWS = require('./core');
var domain = AWS.util.nodeRequire('domain');

/**
 * @!method on(eventName, callback)
 *   Registers an event listener callback for the event given by `eventName`.
 *   Parameters passed to the callback function depend on the individual event
 *   being triggered. See the event documentation for those parameters.
 *
 *   @param eventName [String] the event name to register the listener for
 *   @param callback [Function] the listener callback function
 *   @return [AWS.SequentialExecutor] the same object for chaining
 */
AWS.SequentialExecutor = AWS.util.inherit({

  constructor: function SequentialExecutor() {
    this.domain = domain && domain.active;
    this._events = {};
  },

  /**
   * @api private
   */
  listeners: function listeners(eventName) {
    return this._events[eventName] ? this._events[eventName].slice(0) : [];
  },

  on: function on(eventName, listener) {
    if (this._events[eventName]) {
      this._events[eventName].push(listener);
    } else {
      this._events[eventName] = [listener];
    }
    return this;
  },

  /**
   * @api private
   */
  onAsync: function onAsync(eventName, listener) {
    listener._isAsync = true;
    return this.on(eventName, listener);
  },

  removeListener: function removeListener(eventName, listener) {
    var listeners = this._events[eventName];
    if (listeners) {
      var length = listeners.length;
      var position = -1;
      for (var i = 0; i < length; ++i) {
        if (listeners[i] === listener) {
          position = i;
        }
      }
      if (position > -1) {
        listeners.splice(position, 1);
      }
    }
    return this;
  },

  removeAllListeners: function removeAllListeners(eventName) {
    if (eventName) {
      delete this._events[eventName];
    } else {
      this._events = {};
    }
    return this;
  },

  /**
   * @api private
   */
  emit: function emit(eventName, eventArgs, doneCallback) {
    if (!doneCallback) doneCallback = this.unhandledErrorCallback;
    var listeners = this.listeners(eventName);
    var count = listeners.length;
    this.callListeners(listeners, eventArgs, doneCallback);
    return count > 0;
  },

  /**
   * @api private
   */
  callListeners: function callListeners(listeners, args, doneCallback) {
    if (listeners.length === 0) {
      doneCallback.call(this);
      return;
    }

    var self = this, listener = listeners.shift();
    if (listener._isAsync) { // asynchronous listener
      var callNextListener = function(err) {
        if (err) {
          doneCallback.call(self, err);
        } else {
          self.callListeners(listeners, args, doneCallback);
        }
      };
      listener.apply(this, args.concat([callNextListener]));
    } else { // synchronous listener
      try {
        listener.apply(this, args);
        this.callListeners(listeners, args, doneCallback);
      } catch (err) {
        doneCallback.call(this, err);
      }
    }
  },

  /**
   * Adds or copies a set of listeners from another list of
   * listeners or SequentialExecutor object.
   *
   * @param listeners [map<String,Array<Function>>, AWS.SequentialExecutor]
   *   a list of events and callbacks, or an event emitter object
   *   containing listeners to add to this emitter object.
   * @return [AWS.SequentialExecutor] the emitter object, for chaining.
   * @example Adding listeners from a map of listeners
   *   emitter.addListeners({
   *     event1: [function() { ... }, function() { ... }],
   *     event2: [function() { ... }]
   *   });
   *   emitter.emit('event1'); // emitter has event1
   *   emitter.emit('event2'); // emitter has event2
   * @example Adding listeners from another emitter object
   *   var emitter1 = new AWS.SequentialExecutor();
   *   emitter1.on('event1', function() { ... });
   *   emitter1.on('event2', function() { ... });
   *   var emitter2 = new AWS.SequentialExecutor();
   *   emitter2.addListeners(emitter1);
   *   emitter2.emit('event1'); // emitter2 has event1
   *   emitter2.emit('event2'); // emitter2 has event2
   */
  addListeners: function addListeners(listeners) {
    var self = this;

    // extract listeners if parameter is an SequentialExecutor object
    if (listeners._events) listeners = listeners._events;

    AWS.util.each(listeners, function(event, callbacks) {
      if (typeof callbacks === 'function') callbacks = [callbacks];
      AWS.util.arrayEach(callbacks, function(callback) {
        self.on(event, callback);
      });
    });

    return self;
  },

  /**
   * Registers an event with {on} and saves the callback handle function
   * as a property on the emitter object using a given `name`.
   *
   * @param name [String] the property name to set on this object containing
   *   the callback function handle so that the listener can be removed in
   *   the future.
   * @param (see on)
   * @return (see on)
   * @example Adding a named listener DATA_CALLBACK
   *   var listener = function() { doSomething(); };
   *   emitter.addNamedListener('DATA_CALLBACK', 'data', listener);
   *
   *   // the following prints: true
   *   console.log(emitter.DATA_CALLBACK == listener);
   */
  addNamedListener: function addNamedListener(name, eventName, callback) {
    this[name] = callback;
    this.addListener(eventName, callback);
    return this;
  },

  /**
   * @api private
   */
  addNamedAsyncListener: function addNamedAsyncListener(name, eventName, callback) {
    callback._isAsync = true;
    return this.addNamedListener(name, eventName, callback);
  },

  /**
   * Helper method to add a set of named listeners using
   * {addNamedListener}. The callback contains a parameter
   * with a handle to the `addNamedListener` method.
   *
   * @callback callback function(add)
   *   The callback function is called immediately in order to provide
   *   the `add` function to the block. This simplifies the addition of
   *   a large group of named listeners.
   *   @param add [Function] the {addNamedListener} function to call
   *     when registering listeners.
   * @example Adding a set of named listeners
   *   emitter.addNamedListeners(function(add) {
   *     add('DATA_CALLBACK', 'data', function() { ... });
   *     add('OTHER', 'otherEvent', function() { ... });
   *     add('LAST', 'lastEvent', function() { ... });
   *   });
   *
   *   // these properties are now set:
   *   emitter.DATA_CALLBACK;
   *   emitter.OTHER;
   *   emitter.LAST;
   */
  addNamedListeners: function addNamedListeners(callback) {
    var self = this;
    callback(
      function() {
        self.addNamedListener.apply(self, arguments);
      },
      function() {
        self.addNamedAsyncListener.apply(self, arguments);
      }
    );
    return this;
  },

  /**
   * @api private
   */
  unhandledErrorCallback: function unhandledErrorCallback(err) {
    if (err) {
      if (domain && this.domain instanceof domain.Domain) {
        err.domainEmitter = this;
        err.domain = this.domain;
        err.domainThrown = false;
        this.domain.emit('error', err);
      } else {
        throw err;
      }
    }
  }
});

/**
 * {on} is the prefered method.
 * @api private
 */
AWS.SequentialExecutor.prototype.addListener = AWS.SequentialExecutor.prototype.on;

module.exports = AWS.SequentialExecutor;
<commit_msg>More refactoring on callListeners<commit_after>var AWS = require('./core');
var domain = AWS.util.nodeRequire('domain');

/**
 * @!method on(eventName, callback)
 *   Registers an event listener callback for the event given by `eventName`.
 *   Parameters passed to the callback function depend on the individual event
 *   being triggered. See the event documentation for those parameters.
 *
 *   @param eventName [String] the event name to register the listener for
 *   @param callback [Function] the listener callback function
 *   @return [AWS.SequentialExecutor] the same object for chaining
 */
AWS.SequentialExecutor = AWS.util.inherit({

  constructor: function SequentialExecutor() {
    this.domain = domain && domain.active;
    this._events = {};
  },

  /**
   * @api private
   */
  listeners: function listeners(eventName) {
    return this._events[eventName] ? this._events[eventName].slice(0) : [];
  },

  on: function on(eventName, listener) {
    if (this._events[eventName]) {
      this._events[eventName].push(listener);
    } else {
      this._events[eventName] = [listener];
    }
    return this;
  },

  /**
   * @api private
   */
  onAsync: function onAsync(eventName, listener) {
    listener._isAsync = true;
    return this.on(eventName, listener);
  },

  removeListener: function removeListener(eventName, listener) {
    var listeners = this._events[eventName];
    if (listeners) {
      var length = listeners.length;
      var position = -1;
      for (var i = 0; i < length; ++i) {
        if (listeners[i] === listener) {
          position = i;
        }
      }
      if (position > -1) {
        listeners.splice(position, 1);
      }
    }
    return this;
  },

  removeAllListeners: function removeAllListeners(eventName) {
    if (eventName) {
      delete this._events[eventName];
    } else {
      this._events = {};
    }
    return this;
  },

  /**
   * @api private
   */
  emit: function emit(eventName, eventArgs, doneCallback) {
    if (!doneCallback) doneCallback = this.unhandledErrorCallback;
    var listeners = this.listeners(eventName);
    var count = listeners.length;
    this.callListeners(listeners, eventArgs, doneCallback);
    return count > 0;
  },

  /**
   * @api private
   */
  callListeners: function callListeners(listeners, args, doneCallback) {
    if (listeners.length === 0) {
      doneCallback.call(this);
      return;
    }

    var self = this, listener = listeners.shift();
    if (listener._isAsync) { // asynchronous listener
      var callNextListener = function(err) {
        if (err) {
          doneCallback.call(self, err);
        } else {
          self.callListeners(listeners, args, doneCallback);
        }
      };
      listener.apply(self, args.concat([callNextListener]));
    } else { // synchronous listener
      try {
        listener.apply(self, args);
        self.callListeners(listeners, args, doneCallback);
      } catch (err) {
        doneCallback.call(self, err);
      }
    }
  },

  /**
   * Adds or copies a set of listeners from another list of
   * listeners or SequentialExecutor object.
   *
   * @param listeners [map<String,Array<Function>>, AWS.SequentialExecutor]
   *   a list of events and callbacks, or an event emitter object
   *   containing listeners to add to this emitter object.
   * @return [AWS.SequentialExecutor] the emitter object, for chaining.
   * @example Adding listeners from a map of listeners
   *   emitter.addListeners({
   *     event1: [function() { ... }, function() { ... }],
   *     event2: [function() { ... }]
   *   });
   *   emitter.emit('event1'); // emitter has event1
   *   emitter.emit('event2'); // emitter has event2
   * @example Adding listeners from another emitter object
   *   var emitter1 = new AWS.SequentialExecutor();
   *   emitter1.on('event1', function() { ... });
   *   emitter1.on('event2', function() { ... });
   *   var emitter2 = new AWS.SequentialExecutor();
   *   emitter2.addListeners(emitter1);
   *   emitter2.emit('event1'); // emitter2 has event1
   *   emitter2.emit('event2'); // emitter2 has event2
   */
  addListeners: function addListeners(listeners) {
    var self = this;

    // extract listeners if parameter is an SequentialExecutor object
    if (listeners._events) listeners = listeners._events;

    AWS.util.each(listeners, function(event, callbacks) {
      if (typeof callbacks === 'function') callbacks = [callbacks];
      AWS.util.arrayEach(callbacks, function(callback) {
        self.on(event, callback);
      });
    });

    return self;
  },

  /**
   * Registers an event with {on} and saves the callback handle function
   * as a property on the emitter object using a given `name`.
   *
   * @param name [String] the property name to set on this object containing
   *   the callback function handle so that the listener can be removed in
   *   the future.
   * @param (see on)
   * @return (see on)
   * @example Adding a named listener DATA_CALLBACK
   *   var listener = function() { doSomething(); };
   *   emitter.addNamedListener('DATA_CALLBACK', 'data', listener);
   *
   *   // the following prints: true
   *   console.log(emitter.DATA_CALLBACK == listener);
   */
  addNamedListener: function addNamedListener(name, eventName, callback) {
    this[name] = callback;
    this.addListener(eventName, callback);
    return this;
  },

  /**
   * @api private
   */
  addNamedAsyncListener: function addNamedAsyncListener(name, eventName, callback) {
    callback._isAsync = true;
    return this.addNamedListener(name, eventName, callback);
  },

  /**
   * Helper method to add a set of named listeners using
   * {addNamedListener}. The callback contains a parameter
   * with a handle to the `addNamedListener` method.
   *
   * @callback callback function(add)
   *   The callback function is called immediately in order to provide
   *   the `add` function to the block. This simplifies the addition of
   *   a large group of named listeners.
   *   @param add [Function] the {addNamedListener} function to call
   *     when registering listeners.
   * @example Adding a set of named listeners
   *   emitter.addNamedListeners(function(add) {
   *     add('DATA_CALLBACK', 'data', function() { ... });
   *     add('OTHER', 'otherEvent', function() { ... });
   *     add('LAST', 'lastEvent', function() { ... });
   *   });
   *
   *   // these properties are now set:
   *   emitter.DATA_CALLBACK;
   *   emitter.OTHER;
   *   emitter.LAST;
   */
  addNamedListeners: function addNamedListeners(callback) {
    var self = this;
    callback(
      function() {
        self.addNamedListener.apply(self, arguments);
      },
      function() {
        self.addNamedAsyncListener.apply(self, arguments);
      }
    );
    return this;
  },

  /**
   * @api private
   */
  unhandledErrorCallback: function unhandledErrorCallback(err) {
    if (err) {
      if (domain && this.domain instanceof domain.Domain) {
        err.domainEmitter = this;
        err.domain = this.domain;
        err.domainThrown = false;
        this.domain.emit('error', err);
      } else {
        throw err;
      }
    }
  }
});

/**
 * {on} is the prefered method.
 * @api private
 */
AWS.SequentialExecutor.prototype.addListener = AWS.SequentialExecutor.prototype.on;

module.exports = AWS.SequentialExecutor;
<|endoftext|>


<commit_before>/**
 * Yake can operate in three modes:
 * 	-	a jake/ruby mode where the yake bin is executed and loads a yakefile
 * 	-	where yake is part of a cli script (in js) and loads tasks from an array data sctructure
 * 	-	where yake is part of a cli script (in js) and loads tasks using the yake.task() and related functions
*/

//these are destinguished by an enumerated typeof - correspondingly
exports = {
	yakeCmd: 'yake_cmd',
	yakeFromArray: 'yakeFromArray',
	yakeTaskfile : 'yake_taskfile',
}<commit_msg>first<commit_after>/**
 * Yake can operate in three modes:
 * 	-	a jake/ruby mode where the yake bin is executed and loads a yakefile
 * 	-	where yake is part of a cli script (in js) and loads tasks from an array data sctructure
 * 	-	where yake is part of a cli script (in js) and loads tasks using the yake.task() and related functions
*/

//these are destinguished by an enumerated typeof - correspondingly
exports.MODE = {
	yakeCmd: 'yake_cmd',
	yakeFromArray: 'yakeFromArray',
	yakeTaskfile : 'yake_taskfile',
}<|endoftext|>


<commit_before>PLAYGROUND.Tween = function(manager, context) {

  if (!context) debugger;

  PLAYGROUND.Events.call(this);

  this.manager = manager;
  this.context = context;

  PLAYGROUND.Utils.extend(this, {

    actions: [],
    index: -1,
    prevEasing: "045",
    prevDuration: 0.5

  });

  this.current = false;

};

PLAYGROUND.Tween.prototype = {

  /*

    Add an action to the end of the list

    @param properties
    @param duration in miliseconds (optional, default is 0.5)
    @param easing (optional, default is 045)
    @returns `this` object so that calls can be chained.

  */

  add: function(properties, duration, easing) {

    if (typeof duration !== "undefined") this.prevDuration = duration;
    else duration = 0.5;

    if (easing) this.prevEasing = easing;
    else easing = "045";

    this.actions.push([properties, duration, easing]);

    return this;

  },

  /* Discard all other tweens associated with same context as ours */

  discard: function() {

    this.manager.discard(this.context, this);

    return this;

  },

  /* Alias for `add()` */

  to: function(properties, duration, easing) {

    return this.add(properties, duration, easing);

  },

  /* Enqueue a method call */

  call: function(methodName, context) {

    var action = ["call", methodName, context || this.context];

    for (var i = 2; i < arguments.length; i++) action.push(arguments[i]);

    this.actions.push(action);

    return this;

  },

  /* Mark the instance as being a repeated tween */

  loop: function() {

    this.looped = true;

    return this;

  },

  /* Add a repeat action for specified number of times */

  repeat: function(times) {

    this.actions.push(["repeat", times]);

    return this;

  },

  /* Add a wait action for specified number of miliseconds */

  wait: function(time) {

    this.actions.push(["wait", time]);

    return this;

  },

  /* Alias for `wait()` */

  delay: function(time) {

    this.actions.push(["wait", time]);

    return this;

  },

  /* Remove this tween from the manager */

  stop: function() {

    this.manager.remove(this);

    return this;

  },

  /* Inserts the tween into the manager if not already inside. */

  play: function() {

    this.manager.add(this);

    this.finished = false;

    return this;

  },

  /* Performs last step in the animation list. */

  end: function() {

    var lastAnimationIndex = 0;

    for (var i = this.index + 1; i < this.actions.length; i++) {
      if (typeof this.actions[i][0] === "object") lastAnimationIndex = i;
    }

    this.index = lastAnimationIndex - 1;
    this.next();
    this.delta = this.duration;
    this.step(0);

    return this;

  },

  /* TBD */

  forward: function() {

    this.delta = this.duration;
    this.step(0);

  },

  /* TBD */

  rewind: function() {

    this.delta = 0;
    this.step(0);

  },

  /*

    Perform one animation step

    Advances the index and, if the index reached the end of the
    `actions` array, either restarts it (for looped tweens) or terminates it.

    The function will set a string in `currentAction` indicating what it
    should be done next but it does not perform the action itself.

  */

  next: function() {

    this.delta = 0;

    this.index++;

    if (this.index >= this.actions.length) {

      if (this.looped) {

        this.trigger("loop", {
          tween: this
        });

        this.index = 0;

      } else {

        this.manager.remove(this);

        return;

      }
    }

    this.current = this.actions[this.index];

    if (this.current[0] === "call") {

      var args = this.current.slice(2);

      var methodName = this.current[1];
      var context = this.current[2];
      var method = context[methodName];

      method.apply(context, args);

    } else if (this.current[0] === "wait") {

      this.duration = this.current[1];
      this.currentAction = "wait";

    } else {

      /* calculate changes */

      var properties = this.current[0];

      /* keep keys as array for 0.0001% performance boost */

      this.keys = Object.keys(properties);

      this.change = [];
      this.before = [];
      this.types = [];

      for (i = 0; i < this.keys.length; i++) {

        var key = this.keys[i];
        var value = this.context[key];

        if (typeof properties[key] === "number") {

          this.before.push(value);
          this.change.push(properties[key] - value);
          this.types.push(0);

        } else if (typeof properties[key] === "string" && properties[key].indexOf("rad") > -1) {

          this.before.push(value);
          this.change.push(PLAYGROUND.Utils.circWrappedDistance(value, parseFloat(properties[key])));
          this.types.push(2);

        } else {

          var before = cq.color(value);

          this.before.push(before);

          var after = cq.color(properties[key]);

          var temp = [];

          for (var j = 0; j < 3; j++) {
            temp.push(after[j] - before[j]);
          }

          this.change.push(temp);

          this.types.push(1);

        }

      }

      this.currentAction = "animate";

      this.duration = this.current[1];
      this.easing = this.current[2];

    }

  },

  /* TBD */

  prev: function() {

  },

  /* Select an action if none is current then perform required steps. */

  step: function(delta) {

    this.delta += delta;

    if (!this.current) this.next();

    switch (this.currentAction) {

      case "animate":
        this.doAnimate(delta);
        break;

      case "wait":
        this.doWait(delta);
        break;

    }

  },

  doAnimate: function(delta) {

    this.progress = this.duration ? Math.min(1, this.delta / this.duration) : 1.0;

    var mod = PLAYGROUND.Utils.ease(this.progress, this.easing);

    for (var i = 0; i < this.keys.length; i++) {

      var key = this.keys[i];

      switch (this.types[i]) {

        /* number */

        case 0:

          this.context[key] = this.before[i] + this.change[i] * mod;

          break;

          /* color */

        case 1:

          var change = this.change[i];
          var before = this.before[i];
          var color = [];

          for (var j = 0; j < 3; j++) {
            color.push(before[j] + change[j] * mod | 0);
          }

          this.context[key] = "rgb(" + color.join(",") + ")";

          break;

          /* angle */

        case 2:

          this.context[key] = PLAYGROUND.Utils.circWrap(this.before[i] + this.change[i] * mod);

          break;
      }
    }

    if (this.progress >= 1) {

      this.next();

    }

    if (this.listeners["step"]) {

      this.trigger("step", {
        tween: this,
        dt: delta
      });

    }

  },

  /*

    Advances the animation if enough time has passed

    The function is called in response to `step()`; it will advance the
    index to next slot in the animation if

  */

  doWait: function(delta) {

    if (this.delta >= this.duration) this.next();

  },

  onremove: function() {

    this.trigger("finished", {
      tween: this
    });

    this.trigger("finish", {
      tween: this
    });

    this.finished = true;

  }

};

PLAYGROUND.Utils.extend(PLAYGROUND.Tween.prototype, PLAYGROUND.Events.prototype);

/*

  Manager for easing effects (transition between various states).

  If `app` is provided the manager becomes application's manager
  for tween effects. The constructor inserts a `tween()` function
  in application for simplicity.

  Properties:
  - delta:
  - defaultEasing:
  - tweens: the list of active animations

*/

PLAYGROUND.TweenManager = function(app) {

  this.tweens = [];

  if (app) {
    this.app = app;
    this.app.tween = this.tween.bind(this);
  }

  this.delta = 0;

  this.app.on("step", this.step.bind(this));

};

PLAYGROUND.TweenManager.prototype = {

  defaultEasing: "128",

  /* TBD */

  circ: function(value) {

    return {
      type: "circ",
      value: value
    };

  },

  /*

    Marks the tween for removing.

    The tween is actually removed in `step()` function.

    @param object the object associated with the tween
    @param safe if the tween located using `object` is `safe` then it is not removed.

  */

  discard: function(object, safe) {

    for (var i = 0; i < this.tweens.length; i++) {

      var tween = this.tweens[i];

      if (tween.context === object && tween !== safe) this.remove(tween);

    }

  },

  /*

    Create a new tween.

    The tween is also added to internal list (you don't have to call
    `add()` yourself).

    @param context the object to associate with the new tween
    @returns a new PLAYGROUND.Tween object

  */

  tween: function(context) {

    var tween = new PLAYGROUND.Tween(this, context);

    this.add(tween);

    return tween;

  },

  /*

    Called each frame to update logic.

    The function updates all active tweens and removes the ones
    tagged as such.

  */

  step: function(delta) {

    this.delta += delta;

    for (var i = 0; i < this.tweens.length; i++) {

      var tween = this.tweens[i];

      if (!tween._remove) tween.step(delta);

      if (tween._remove) this.tweens.splice(i--, 1);

    }

  },

  /* Add a tween to internal list. */

  add: function(tween) {

    tween._remove = false;

    var index = this.tweens.indexOf(tween);

    if (index === -1) this.tweens.push(tween);

  },

  /* Marks a tween for removing during next step(). */

  remove: function(tween) {

    if (tween._remove) return;

    tween._remove = true;

    tween.onremove();

  }

};<commit_msg>Add "var" to for-loop<commit_after>PLAYGROUND.Tween = function(manager, context) {

  if (!context) debugger;

  PLAYGROUND.Events.call(this);

  this.manager = manager;
  this.context = context;

  PLAYGROUND.Utils.extend(this, {

    actions: [],
    index: -1,
    prevEasing: "045",
    prevDuration: 0.5

  });

  this.current = false;

};

PLAYGROUND.Tween.prototype = {

  /*

    Add an action to the end of the list

    @param properties
    @param duration in miliseconds (optional, default is 0.5)
    @param easing (optional, default is 045)
    @returns `this` object so that calls can be chained.

  */

  add: function(properties, duration, easing) {

    if (typeof duration !== "undefined") this.prevDuration = duration;
    else duration = 0.5;

    if (easing) this.prevEasing = easing;
    else easing = "045";

    this.actions.push([properties, duration, easing]);

    return this;

  },

  /* Discard all other tweens associated with same context as ours */

  discard: function() {

    this.manager.discard(this.context, this);

    return this;

  },

  /* Alias for `add()` */

  to: function(properties, duration, easing) {

    return this.add(properties, duration, easing);

  },

  /* Enqueue a method call */

  call: function(methodName, context) {

    var action = ["call", methodName, context || this.context];

    for (var i = 2; i < arguments.length; i++) action.push(arguments[i]);

    this.actions.push(action);

    return this;

  },

  /* Mark the instance as being a repeated tween */

  loop: function() {

    this.looped = true;

    return this;

  },

  /* Add a repeat action for specified number of times */

  repeat: function(times) {

    this.actions.push(["repeat", times]);

    return this;

  },

  /* Add a wait action for specified number of miliseconds */

  wait: function(time) {

    this.actions.push(["wait", time]);

    return this;

  },

  /* Alias for `wait()` */

  delay: function(time) {

    this.actions.push(["wait", time]);

    return this;

  },

  /* Remove this tween from the manager */

  stop: function() {

    this.manager.remove(this);

    return this;

  },

  /* Inserts the tween into the manager if not already inside. */

  play: function() {

    this.manager.add(this);

    this.finished = false;

    return this;

  },

  /* Performs last step in the animation list. */

  end: function() {

    var lastAnimationIndex = 0;

    for (var i = this.index + 1; i < this.actions.length; i++) {
      if (typeof this.actions[i][0] === "object") lastAnimationIndex = i;
    }

    this.index = lastAnimationIndex - 1;
    this.next();
    this.delta = this.duration;
    this.step(0);

    return this;

  },

  /* TBD */

  forward: function() {

    this.delta = this.duration;
    this.step(0);

  },

  /* TBD */

  rewind: function() {

    this.delta = 0;
    this.step(0);

  },

  /*

    Perform one animation step

    Advances the index and, if the index reached the end of the
    `actions` array, either restarts it (for looped tweens) or terminates it.

    The function will set a string in `currentAction` indicating what it
    should be done next but it does not perform the action itself.

  */

  next: function() {

    this.delta = 0;

    this.index++;

    if (this.index >= this.actions.length) {

      if (this.looped) {

        this.trigger("loop", {
          tween: this
        });

        this.index = 0;

      } else {

        this.manager.remove(this);

        return;

      }
    }

    this.current = this.actions[this.index];

    if (this.current[0] === "call") {

      var args = this.current.slice(2);

      var methodName = this.current[1];
      var context = this.current[2];
      var method = context[methodName];

      method.apply(context, args);

    } else if (this.current[0] === "wait") {

      this.duration = this.current[1];
      this.currentAction = "wait";

    } else {

      /* calculate changes */

      var properties = this.current[0];

      /* keep keys as array for 0.0001% performance boost */

      this.keys = Object.keys(properties);

      this.change = [];
      this.before = [];
      this.types = [];

      for (var i = 0; i < this.keys.length; i++) {

        var key = this.keys[i];
        var value = this.context[key];

        if (typeof properties[key] === "number") {

          this.before.push(value);
          this.change.push(properties[key] - value);
          this.types.push(0);

        } else if (typeof properties[key] === "string" && properties[key].indexOf("rad") > -1) {

          this.before.push(value);
          this.change.push(PLAYGROUND.Utils.circWrappedDistance(value, parseFloat(properties[key])));
          this.types.push(2);

        } else {

          var before = cq.color(value);

          this.before.push(before);

          var after = cq.color(properties[key]);

          var temp = [];

          for (var j = 0; j < 3; j++) {
            temp.push(after[j] - before[j]);
          }

          this.change.push(temp);

          this.types.push(1);

        }

      }

      this.currentAction = "animate";

      this.duration = this.current[1];
      this.easing = this.current[2];

    }

  },

  /* TBD */

  prev: function() {

  },

  /* Select an action if none is current then perform required steps. */

  step: function(delta) {

    this.delta += delta;

    if (!this.current) this.next();

    switch (this.currentAction) {

      case "animate":
        this.doAnimate(delta);
        break;

      case "wait":
        this.doWait(delta);
        break;

    }

  },

  doAnimate: function(delta) {

    this.progress = this.duration ? Math.min(1, this.delta / this.duration) : 1.0;

    var mod = PLAYGROUND.Utils.ease(this.progress, this.easing);

    for (var i = 0; i < this.keys.length; i++) {

      var key = this.keys[i];

      switch (this.types[i]) {

        /* number */

        case 0:

          this.context[key] = this.before[i] + this.change[i] * mod;

          break;

          /* color */

        case 1:

          var change = this.change[i];
          var before = this.before[i];
          var color = [];

          for (var j = 0; j < 3; j++) {
            color.push(before[j] + change[j] * mod | 0);
          }

          this.context[key] = "rgb(" + color.join(",") + ")";

          break;

          /* angle */

        case 2:

          this.context[key] = PLAYGROUND.Utils.circWrap(this.before[i] + this.change[i] * mod);

          break;
      }
    }

    if (this.progress >= 1) {

      this.next();

    }

    if (this.listeners["step"]) {

      this.trigger("step", {
        tween: this,
        dt: delta
      });

    }

  },

  /*

    Advances the animation if enough time has passed

    The function is called in response to `step()`; it will advance the
    index to next slot in the animation if

  */

  doWait: function(delta) {

    if (this.delta >= this.duration) this.next();

  },

  onremove: function() {

    this.trigger("finished", {
      tween: this
    });

    this.trigger("finish", {
      tween: this
    });

    this.finished = true;

  }

};

PLAYGROUND.Utils.extend(PLAYGROUND.Tween.prototype, PLAYGROUND.Events.prototype);

/*

  Manager for easing effects (transition between various states).

  If `app` is provided the manager becomes application's manager
  for tween effects. The constructor inserts a `tween()` function
  in application for simplicity.

  Properties:
  - delta:
  - defaultEasing:
  - tweens: the list of active animations

*/

PLAYGROUND.TweenManager = function(app) {

  this.tweens = [];

  if (app) {
    this.app = app;
    this.app.tween = this.tween.bind(this);
  }

  this.delta = 0;

  this.app.on("step", this.step.bind(this));

};

PLAYGROUND.TweenManager.prototype = {

  defaultEasing: "128",

  /* TBD */

  circ: function(value) {

    return {
      type: "circ",
      value: value
    };

  },

  /*

    Marks the tween for removing.

    The tween is actually removed in `step()` function.

    @param object the object associated with the tween
    @param safe if the tween located using `object` is `safe` then it is not removed.

  */

  discard: function(object, safe) {

    for (var i = 0; i < this.tweens.length; i++) {

      var tween = this.tweens[i];

      if (tween.context === object && tween !== safe) this.remove(tween);

    }

  },

  /*

    Create a new tween.

    The tween is also added to internal list (you don't have to call
    `add()` yourself).

    @param context the object to associate with the new tween
    @returns a new PLAYGROUND.Tween object

  */

  tween: function(context) {

    var tween = new PLAYGROUND.Tween(this, context);

    this.add(tween);

    return tween;

  },

  /*

    Called each frame to update logic.

    The function updates all active tweens and removes the ones
    tagged as such.

  */

  step: function(delta) {

    this.delta += delta;

    for (var i = 0; i < this.tweens.length; i++) {

      var tween = this.tweens[i];

      if (!tween._remove) tween.step(delta);

      if (tween._remove) this.tweens.splice(i--, 1);

    }

  },

  /* Add a tween to internal list. */

  add: function(tween) {

    tween._remove = false;

    var index = this.tweens.indexOf(tween);

    if (index === -1) this.tweens.push(tween);

  },

  /* Marks a tween for removing during next step(). */

  remove: function(tween) {

    if (tween._remove) return;

    tween._remove = true;

    tween.onremove();

  }

};
<|endoftext|>


<commit_before>/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
 * http://scratchdisk.com/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name Line
 *
 * @class The Line object represents..
 */
var Line = Base.extend(/** @lends Line# */{
    _class: 'Line',

    // DOCS: document Line class and constructor
    /**
     * Creates a Line object.
     *
     * @param {Point} point1
     * @param {Point} point2
     * @param {Boolean} [asVector=false]
     */
    initialize: function Line(arg0, arg1, arg2, arg3, arg4) {
        var asVector = false;
        if (arguments.length >= 4) {
            this._px = arg0;
            this._py = arg1;
            this._vx = arg2;
            this._vy = arg3;
            asVector = arg4;
        } else {
            this._px = arg0.x;
            this._py = arg0.y;
            this._vx = arg1.x;
            this._vy = arg1.y;
            asVector = arg2;
        }
        if (!asVector) {
            this._vx -= this._px;
            this._vy -= this._py;
        }
    },

    /**
     * The starting point of the line
     *
     * @name Line#point
     * @type Point
     */
    getPoint: function() {
        return new Point(this._px, this._py);
    },

    /**
     * The vector of the line
     *
     * @name Line#vector
     * @type Point
     */
    getVector: function() {
        return new Point(this._vx, this._vy);
    },

    /**
     * The length of the line
     *
     * @name Line#length
     * @type Number
     */
    getLength: function() {
        return this.getVector().getLength();
    },

    /**
     * @param {Line} line
     * @param {Boolean} [isInfinite=false]
     * @return {Point} the intersection point of the lines, {@code undefined}
     * if the two lines are colinear, or {@code null} if they don't intersect.
     */
    intersect: function(line, isInfinite) {
        return Line.intersect(
                this._px, this._py, this._vx, this._vy,
                line._px, line._py, line._vx, line._vy,
                true, isInfinite);
    },

    // DOCS: document Line#getSide(point)
    /**
     * @param {Point} point
     * @return {Number}
     */
    getSide: function(point) {
        return Line.getSide(
                this._px, this._py, this._vx, this._vy,
                point.x, point.y, true);
    },

    // DOCS: document Line#getDistance(point)
    /**
     * @param {Point} point
     * @return {Number}
     */
    getDistance: function(point) {
        return Math.abs(Line.getSignedDistance(
                this._px, this._py, this._vx, this._vy,
                point.x, point.y, true));
    },

    statics: /** @lends Line */{
        intersect: function(apx, apy, avx, avy, bpx, bpy, bvx, bvy, asVector,
                isInfinite) {
            // Convert 2nd points to vectors if they are not specified as such.
            if (!asVector) {
                avx -= apx;
                avy -= apy;
                bvx -= bpx;
                bvy -= bpy;
            }
            var cross = bvy * avx - bvx * avy;
            // Avoid divisions by 0, and errors when getting too close to 0
            if (!Numerical.isZero(cross)) {
                var dx = apx - bpx,
                    dy = apy - bpy,
                    ta = (bvx * dy - bvy * dx) / cross,
                    tb = (avx * dy - avy * dx) / cross;
                // Check the ranges of t parameters if the line is not allowed
                // to extend beyond the definition points.
                if ((isInfinite || 0 <= ta && ta <= 1)
                        && (isInfinite || 0 <= tb && tb <= 1))
                    return new Point(
                                apx + ta * avx,
                                apy + ta * avy);
            }
        },

        getSide: function(px, py, vx, vy, x, y, asVector) {
            if (!asVector) {
                vx -= px;
                vy -= py;
            }
            var v2x = x - px,
                v2y = y - py,
                ccw = v2x * vy - v2y * vx; // ccw = v2.cross(v1);
            if (ccw === 0) {
                ccw = v2x * vx + v2y * vy; // ccw = v2.dot(v1);
                if (ccw > 0) {
                    // ccw = v2.subtract(v1).dot(v1);
                    v2x -= vx;
                    v2y -= vy;
                    ccw = v2x * vx + v2y * vy;
                    if (ccw < 0)
                        ccw = 0;
                }
            }
            return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
        },

        getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
            if (!asVector) {
                vx -= px;
                vy -= py;
            }
            if (Numerical.isZero(vx))
                return x - px;
            var m = vy / vx, // slope
                b = py - m * px; // y offset
            // Distance to the linear equation
            return (y - (m * x) - b) / Math.sqrt(m * m + 1);
        }
    }
});
<commit_msg>Some code clean-up.<commit_after>/*
 * Paper.js - The Swiss Army Knife of Vector Graphics Scripting.
 * http://paperjs.org/
 *
 * Copyright (c) 2011 - 2014, Juerg Lehni & Jonathan Puckey
 * http://scratchdisk.com/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

/**
 * @name Line
 *
 * @class The Line object represents..
 */
var Line = Base.extend(/** @lends Line# */{
    _class: 'Line',

    // DOCS: document Line class and constructor
    /**
     * Creates a Line object.
     *
     * @param {Point} point1
     * @param {Point} point2
     * @param {Boolean} [asVector=false]
     */
    initialize: function Line(arg0, arg1, arg2, arg3, arg4) {
        var asVector = false;
        if (arguments.length >= 4) {
            this._px = arg0;
            this._py = arg1;
            this._vx = arg2;
            this._vy = arg3;
            asVector = arg4;
        } else {
            this._px = arg0.x;
            this._py = arg0.y;
            this._vx = arg1.x;
            this._vy = arg1.y;
            asVector = arg2;
        }
        if (!asVector) {
            this._vx -= this._px;
            this._vy -= this._py;
        }
    },

    /**
     * The starting point of the line
     *
     * @name Line#point
     * @type Point
     */
    getPoint: function() {
        return new Point(this._px, this._py);
    },

    /**
     * The vector of the line
     *
     * @name Line#vector
     * @type Point
     */
    getVector: function() {
        return new Point(this._vx, this._vy);
    },

    /**
     * The length of the line
     *
     * @name Line#length
     * @type Number
     */
    getLength: function() {
        return this.getVector().getLength();
    },

    /**
     * @param {Line} line
     * @param {Boolean} [isInfinite=false]
     * @return {Point} the intersection point of the lines, {@code undefined}
     * if the two lines are colinear, or {@code null} if they don't intersect.
     */
    intersect: function(line, isInfinite) {
        return Line.intersect(
                this._px, this._py, this._vx, this._vy,
                line._px, line._py, line._vx, line._vy,
                true, isInfinite);
    },

    // DOCS: document Line#getSide(point)
    /**
     * @param {Point} point
     * @return {Number}
     */
    getSide: function(point) {
        return Line.getSide(
                this._px, this._py, this._vx, this._vy,
                point.x, point.y, true);
    },

    // DOCS: document Line#getDistance(point)
    /**
     * @param {Point} point
     * @return {Number}
     */
    getDistance: function(point) {
        return Math.abs(Line.getSignedDistance(
                this._px, this._py, this._vx, this._vy,
                point.x, point.y, true));
    },

    statics: /** @lends Line */{
        intersect: function(apx, apy, avx, avy, bpx, bpy, bvx, bvy, asVector,
                isInfinite) {
            // Convert 2nd points to vectors if they are not specified as such.
            if (!asVector) {
                avx -= apx;
                avy -= apy;
                bvx -= bpx;
                bvy -= bpy;
            }
            var cross = avx * bvy - avy * bvx;
            // Avoid divisions by 0, and errors when getting too close to 0
            if (!Numerical.isZero(cross)) {
                var dx = apx - bpx,
                    dy = apy - bpy,
                    ta = (bvx * dy - bvy * dx) / cross,
                    tb = (avx * dy - avy * dx) / cross;
                // Check the ranges of t parameters if the line is not allowed
                // to extend beyond the definition points.
                if (isInfinite || 0 <= ta && ta <= 1 && 0 <= tb && tb <= 1)
                    return new Point(
                                apx + ta * avx,
                                apy + ta * avy);
            }
        },

        getSide: function(px, py, vx, vy, x, y, asVector) {
            if (!asVector) {
                vx -= px;
                vy -= py;
            }
            var v2x = x - px,
                v2y = y - py,
                ccw = v2x * vy - v2y * vx; // ccw = v2.cross(v1);
            if (ccw === 0) {
                ccw = v2x * vx + v2y * vy; // ccw = v2.dot(v1);
                if (ccw > 0) {
                    // ccw = v2.subtract(v1).dot(v1);
                    v2x -= vx;
                    v2y -= vy;
                    ccw = v2x * vx + v2y * vy;
                    if (ccw < 0)
                        ccw = 0;
                }
            }
            return ccw < 0 ? -1 : ccw > 0 ? 1 : 0;
        },

        getSignedDistance: function(px, py, vx, vy, x, y, asVector) {
            if (!asVector) {
                vx -= px;
                vy -= py;
            }
            if (Numerical.isZero(vx))
                return x - px;
            var m = vy / vx, // slope
                b = py - m * px; // y offset
            // Distance to the linear equation
            return (y - (m * x) - b) / Math.sqrt(m * m + 1);
        }
    }
});
<|endoftext|>


<commit_before>"use strict";

var Promise = require('bluebird');

var logger = require("../logging")("bus-command");
var util = require('util');
var filter = require('../filter');
var createCustomerOrProducerPromise = require('../factory');

const entityType = "command";
const entityExchangeName = entityType + ".exchange";

var producerClass = 'Sender';
var consumerClass = 'Receiver';

function CommandClass(entityName, rabbitPromise, consumerId, bus) {

    var producerPromise, consumerPromise;

    var fullPath = [entityType, entityName].join('.');

    var getProducerPromise = function(){
        if (!producerPromise) {
            var options = {
                exchange: entityExchangeName,
                routingKey: fullPath,
                messageType: fullPath
            };

            producerPromise = createCustomerOrProducerPromise(
                rabbitPromise,
                entityName,
                producerClass,
                options,
                entityType
            );
        }

        return producerPromise;
    };

    var getConsumerPromise = function(){
        if (!consumerPromise) {
            var options = {
                exchange: entityExchangeName,
                queue: {
                    name: [fullPath, consumerId].join('.'),
                    autoDelete: false
                },
                routingKey: fullPath,
                messageType: fullPath
            };

            consumerPromise = createCustomerOrProducerPromise(
                rabbitPromise,
                entityName,
                consumerClass,
                options,
                entityType
            );
        }

        return consumerPromise;
    };

    this.send = function(message, properties) {
        var properties = properties || {};
        var message = message || {};
        return getProducerPromise().then(function(producer){
            producer.send(message, properties);
            return producer;
        });
    };

    this.receive = function(callback) {
        return getConsumerPromise().then(function(consumer){
            consumer.receive(function(message, properties, actions, next){
                var commandResult = callback(message);
                Promise.resolve(commandResult).then(function(resp){
                    actions.ack();
                    var props = {};
                    if (properties.correlationId) {
                        props.correlationId = properties.correlationId;
                    }
                    bus.event([entityType, entityName, 'done'].join('.')).publish(resp, props);
                });
            });
            return consumer;
        });
    };

    logger.debug(entityType + ' ' + entityName + ' created');
}

module.exports = function(commandName, rabbitPromis, consumerId, bus) {
    return new CommandClass(filter.string(commandName), rabbitPromis, consumerId, bus);
};

<commit_msg>add exceptions<commit_after>"use strict";

var Promise = require('bluebird');

var logger = require("../logging")("bus-command");
var util = require('util');
var filter = require('../filter');
var createCustomerOrProducerPromise = require('../factory');

const entityType = "command";
const entityExchangeName = entityType + ".exchange";

var producerClass = 'Sender';
var consumerClass = 'Receiver';

function CommandClass(entityName, rabbitPromise, consumerId, bus) {

    var producerPromise, consumerPromise;

    var fullPath = [entityType, entityName].join('.');

    var getProducerPromise = function(){
        if (!producerPromise) {
            var options = {
                exchange: entityExchangeName,
                routingKey: fullPath,
                messageType: fullPath
            };

            producerPromise = createCustomerOrProducerPromise(
                rabbitPromise,
                entityName,
                producerClass,
                options,
                entityType
            );
        }

        return producerPromise;
    };

    var getConsumerPromise = function(){
        if (!consumerPromise) {
            var options = {
                exchange: entityExchangeName,
                queue: {
                    name: [fullPath, consumerId].join('.'),
                    autoDelete: false
                },
                routingKey: fullPath,
                messageType: fullPath
            };

            consumerPromise = createCustomerOrProducerPromise(
                rabbitPromise,
                entityName,
                consumerClass,
                options,
                entityType
            );
        }

        return consumerPromise;
    };

    this.send = function(message, properties) {
        properties = properties || {};
        message = message || {};
        return getProducerPromise().then(function(producer){
            producer.send(message, properties);
            return producer;
        });
    };

    this.receive = function(callback) {
        return getConsumerPromise().then(function(consumer){
            consumer.receive(function(message, properties, actions, next){
                Promise.try(callback.bind(null, message)).then(function(resp){
                    var props = {};
                    if (properties.correlationId) {
                        props.correlationId = properties.correlationId;
                    }
                    bus.event([entityType, entityName, 'done'].join('.')).publish(resp, props);
                }).catch(function(error){
                    bus.exception(error).throw();
                }).finally(function(){
                    actions.ack();
                });
            });
            return consumer;
        });
    };

    logger.debug(entityType + ' ' + entityName + ' created');
}

module.exports = function(commandName, rabbitPromis, consumerId, bus) {
    return new CommandClass(filter.string(commandName), rabbitPromis, consumerId, bus);
};

<|endoftext|>


<commit_before>export const parseTime = function (seconds) {
  let hours = `${Math.floor(seconds / 3600)}`;
  let minutes = `${Math.floor(seconds % 3600 / 60)}`;
  let _seconds = `${Math.floor(seconds % 3600 % 60)}`;
  return `${padLeft(hours, 2)}:${padLeft(minutes, 2)}:${padLeft(_seconds, 2)}`;
};

export const padLeft = function (string, total) {
  if (typeof string !== 'string') {
    throw new Error('First parameter must be a string');
  }
  if (typeof total !== 'number') {
    throw new Error('Second parameter must be a integer');
  }
  return new Array(total - string.length + 1).join('0') + string;
};

export const replaceAndTrim = function (word) {
  return word.replace(/<br\s*[\/]?>/gi, '').replace(/\n/gi, '').trim();
};

export const getClearWordFromTranscript = function (word) {
  return replaceAndTrim(word).replace(/:$/, '');
};

export const COLORS = [
  '#78c361',
  '#9932cc',
  '#ff69b4',
  '#6495ed',
  '#ffd700',
  '#f6a7a1',
  '#7fb397',
  '#009999'
];

export const getRandomColor = function () {
  let letters = '012345'.split('');
  let color = '#';
  color += letters[Math.round(Math.random() * 5)];
  letters = '0123456789ABCDEF'.split('');
  for (let i = 0; i < 5; i++) {
    color += letters[Math.round(Math.random() * 15)];
  }
  return color;
};

export const getFileType = function (file) {
  if (file.type.indexOf('audio') > -1) {
    return 'audio';
  }
  else if (file.type.indexOf('video') > -1) {
    return 'video';
  }
  else return 'unknown';
};

export const dateToIso = function (date) {
  return new Date(date).toISOString();
};

export const sortByField = function (field) {
  var sortOrder = 1;
  if (field[0] === '-') {
    sortOrder = -1;
    field = field.substr(1);
  }
  return function (a, b) {
    var result = (a[field] < b[field]) ? -1 : (a[field] > b[field]) ? 1 : 0;
    return result * sortOrder;
  };
};
<commit_msg>fix first color<commit_after>export const parseTime = function (seconds) {
  let hours = `${Math.floor(seconds / 3600)}`;
  let minutes = `${Math.floor(seconds % 3600 / 60)}`;
  let _seconds = `${Math.floor(seconds % 3600 % 60)}`;
  return `${padLeft(hours, 2)}:${padLeft(minutes, 2)}:${padLeft(_seconds, 2)}`;
};

export const padLeft = function (string, total) {
  if (typeof string !== 'string') {
    throw new Error('First parameter must be a string');
  }
  if (typeof total !== 'number') {
    throw new Error('Second parameter must be a integer');
  }
  return new Array(total - string.length + 1).join('0') + string;
};

export const replaceAndTrim = function (word) {
  return word.replace(/<br\s*[\/]?>/gi, '').replace(/\n/gi, '').trim();
};

export const getClearWordFromTranscript = function (word) {
  return replaceAndTrim(word).replace(/:$/, '');
};

export const COLORS = [
  '#55a01a',
  '#9932cc',
  '#ff69b4',
  '#6495ed',
  '#ffd700',
  '#f6a7a1',
  '#7fb397',
  '#009999'
];

export const getRandomColor = function () {
  let letters = '012345'.split('');
  let color = '#';
  color += letters[Math.round(Math.random() * 5)];
  letters = '0123456789ABCDEF'.split('');
  for (let i = 0; i < 5; i++) {
    color += letters[Math.round(Math.random() * 15)];
  }
  return color;
};

export const getFileType = function (file) {
  if (file.type.indexOf('audio') > -1) {
    return 'audio';
  }
  else if (file.type.indexOf('video') > -1) {
    return 'video';
  }
  else return 'unknown';
};

export const dateToIso = function (date) {
  return new Date(date).toISOString();
};

export const sortByField = function (field) {
  var sortOrder = 1;
  if (field[0] === '-') {
    sortOrder = -1;
    field = field.substr(1);
  }
  return function (a, b) {
    var result = (a[field] < b[field]) ? -1 : (a[field] > b[field]) ? 1 : 0;
    return result * sortOrder;
  };
};
<|endoftext|>


<commit_before>/* @flow */
import React from 'react';
import { connect } from 'react-redux';
import { View, StyleSheet, KeyboardAvoidingView, Platform } from 'react-native';

import type { LocalizableText, PopRouteAction, NavigationState } from '../types';
import { ZulipStatusBar } from '../common';
import ModalNavBar from '../nav/ModalNavBar';

const styles = StyleSheet.create({
  screen: {
    flex: 1,
    flexDirection: 'column',
    alignItems: 'stretch',
  },
  screenWrapper: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'stretch',
  },
});

class Screen extends React.Component {

  props: {
    keyboardAvoiding: boolean,
    title: LocalizableText,
    nav: NavigationState,
    children: [],
    popRoute: PopRouteAction,
  };

  render() {
    const { keyboardAvoiding, title, nav, children, popRoute } = this.props;
    const WrapperView = keyboardAvoiding && Platform.OS === 'ios' ? KeyboardAvoidingView : View;

    return (
      <View style={styles.screen}>
        <ZulipStatusBar />
        <ModalNavBar title={title} popRoute={popRoute} nav={nav} />
        <WrapperView style={styles.screenWrapper} behavior="padding">
          {children}
        </WrapperView>
      </View>
    );
  }
}

export default connect((state) => ({
  orientation: state.app.orientation,
}))(Screen);
<commit_msg>Use ZulipStatusBar and background as per theme<commit_after>/* @flow */
import React from 'react';
import { connect } from 'react-redux';
import { View, StyleSheet, KeyboardAvoidingView, Platform } from 'react-native';

import type { LocalizableText, PopRouteAction, NavigationState } from '../types';
import { ZulipStatusBar } from '../common';
import ModalNavBar from '../nav/ModalNavBar';

const moreStyles = StyleSheet.create({
  screen: {
    flex: 1,
    flexDirection: 'column',
    alignItems: 'stretch',
  },
  screenWrapper: {
    flex: 1,
    flexDirection: 'column',
    justifyContent: 'center',
    alignItems: 'stretch',
  },
});

class Screen extends React.Component {

  props: {
    keyboardAvoiding: boolean,
    title: LocalizableText,
    nav: NavigationState,
    children: [],
    popRoute: PopRouteAction,
  };

  static contextTypes = {
    styles: () => null,
  };

  render() {
    const { keyboardAvoiding, title, nav, children, popRoute } = this.props;
    const WrapperView = keyboardAvoiding && Platform.OS === 'ios' ? KeyboardAvoidingView : View;
    const { styles } = this.context;
    const backgroundColor = StyleSheet.flatten(styles.background).backgroundColor;

    return (
      <View style={moreStyles.screen}>
        <ZulipStatusBar
          backgroundColor={backgroundColor}
        />
        <ModalNavBar title={title} popRoute={popRoute} nav={nav} />
        <WrapperView style={moreStyles.screenWrapper} behavior="padding">
          {children}
        </WrapperView>
      </View>
    );
  }
}

export default connect((state) => ({
  orientation: state.app.orientation,
}))(Screen);
<|endoftext|>


<commit_before>//! Corti - Replaces the browser's SpeechRecognition with a fake object.
//! version : 0.2.1
//! author  : Tal Ater @TalAter
//! license : MIT
//! https://github.com/TalAter/SpeechKITT/test/corti.js

(function (undefined) {
  "use strict";

  // Save a reference to the global object (window in the browser)
  var _root = this;

  // Holds the browser's implementation
  var _productionVersion = false;

  // Patch DOMException
  var DOMException = DOMException || TypeError;

  // Speech Recognition attributes
  var _maxAlternatives = 1;
  var _lang = '';
  var _continuous = false;
  var _interimResults = false;

  var newSpeechRecognition = function() {
    var _self = this;
    var _listeners = document.createElement('div');
    _self._started = false;
    _self.eventListenerTypes = ['start', 'end', 'result'];
    _self.maxAlternatives = 1;

    // Add listeners for events registered through attributes (e.g. recognition.onend = function) and not as proper listeners
    _self.eventListenerTypes.forEach(function(eventName) {
      _listeners.addEventListener(eventName, function () {
        if (typeof _self['on'+eventName] === 'function') {
          _self['on'+eventName].apply(_listeners, arguments);
        }
      }, false);
    });

    Object.defineProperty(this, 'maxAlternatives', {
      get: function() { return _maxAlternatives; },
      set: function(val) {
        if (typeof val === 'number') {
          _maxAlternatives = Math.floor(val);
        } else {
          _maxAlternatives = 0;
        }
      }
    });

    Object.defineProperty(this, 'lang', {
      get: function() { return _lang; },
      set: function(val) {
        if (val === undefined) {
          val = 'undefined';
        }
        _lang = val.toString();
      }
    });

    Object.defineProperty(this, 'continuous', {
      get: function() { return _continuous; },
      set: function(val) {
        _continuous = Boolean(val);
      }
    });

    Object.defineProperty(this, 'interimResults', {
      get: function() { return _interimResults; },
      set: function(val) {
        _interimResults = Boolean(val);
      }
    });

    this.start = function() {
      if (_self._started) {
        throw new DOMException('Failed to execute \'start\' on \'SpeechRecognition\': recognition has already started.');
      }
      _self._started = true;
      // Create and dispatch an event
      var event = document.createEvent('CustomEvent');
      event.initCustomEvent('start', false, false, null);
      _listeners.dispatchEvent(event);
    };

    this.abort = function() {
      if (!_self._started) {
        return;
      }
      _self._started = false;
      // Create and dispatch an event
      var event = document.createEvent('CustomEvent');
      event.initCustomEvent('end', false, false, null);
      _listeners.dispatchEvent(event);
    };

    this.stop = function() {
      return _self.abort();
    };

    this.isStarted = function() {
      return _self._started;
    };

    this.say = function(sentence) {
      // Create some speech alternatives
      var results = [];
      var commandIterator;
      var etcIterator;
      var itemFunction = function(index) {
        if (undefined === index) {
          throw new DOMException('Failed to execute \'item\' on \'SpeechRecognitionResult\': 1 argument required, but only 0 present.');
        }
        index = Number(index);
        if (isNaN(index)) {
          index = 0;
        }
        if (index >= this.length) {
          return null;
        } else {
          return this[index];
        }
      };
      for (commandIterator = 0; commandIterator<_maxAlternatives; commandIterator++) {
        var etc = '';
        for (etcIterator = 0; etcIterator<commandIterator; etcIterator++) {
          etc += ' and so on';
        }
        results.push(sentence+etc);
      }

      // Create the event
      var event = document.createEvent('CustomEvent');
      event.initCustomEvent('result', false, false, {'sentence': sentence});
      event.resultIndex = 0;
      event.results = {
        'item': itemFunction,
        0: {
          'item': itemFunction,
          'final': true
        }
      };
      for (commandIterator = 0; commandIterator<_maxAlternatives; commandIterator++) {
        event.results[0][commandIterator] = {
          'transcript': results[commandIterator],
          'confidence': Math.max(1-0.01*commandIterator, 0.001)
        };
      }
      Object.defineProperty(event.results, 'length', {
        get: function() { return 1; }
      });
      Object.defineProperty(event.results[0], 'length', {
        get: function() { return _maxAlternatives; }
      });
      event.interpretation = null;
      event.emma = null;
      _listeners.dispatchEvent(event);
    };

    this.addEventListener = function(event, callback) {
      _listeners.addEventListener(event, callback, false);
    };
  };

  // Expose functionality
  _root.Corti = {
    patch: function() {
      if (_productionVersion === false) {
        _productionVersion = _root.SpeechRecognition ||
          _root.webkitSpeechRecognition ||
          _root.mozSpeechRecognition ||
          _root.msSpeechRecognition ||
          _root.oSpeechRecognition;
      }
      _root.SpeechRecognition = newSpeechRecognition;
    },

    unpatch: function() {
      _root.SpeechRecognition = _productionVersion;
    }
  };

}).call(this);
<commit_msg>Fixed link to Corti page<commit_after>//! Corti - Replaces the browser's SpeechRecognition with a fake object.
//! version : 0.2.1
//! author  : Tal Ater @TalAter
//! license : MIT
//! https://github.com/TalAter/Corti

(function (undefined) {
  "use strict";

  // Save a reference to the global object (window in the browser)
  var _root = this;

  // Holds the browser's implementation
  var _productionVersion = false;

  // Patch DOMException
  var DOMException = DOMException || TypeError;

  // Speech Recognition attributes
  var _maxAlternatives = 1;
  var _lang = '';
  var _continuous = false;
  var _interimResults = false;

  var newSpeechRecognition = function() {
    var _self = this;
    var _listeners = document.createElement('div');
    _self._started = false;
    _self.eventListenerTypes = ['start', 'end', 'result'];
    _self.maxAlternatives = 1;

    // Add listeners for events registered through attributes (e.g. recognition.onend = function) and not as proper listeners
    _self.eventListenerTypes.forEach(function(eventName) {
      _listeners.addEventListener(eventName, function () {
        if (typeof _self['on'+eventName] === 'function') {
          _self['on'+eventName].apply(_listeners, arguments);
        }
      }, false);
    });

    Object.defineProperty(this, 'maxAlternatives', {
      get: function() { return _maxAlternatives; },
      set: function(val) {
        if (typeof val === 'number') {
          _maxAlternatives = Math.floor(val);
        } else {
          _maxAlternatives = 0;
        }
      }
    });

    Object.defineProperty(this, 'lang', {
      get: function() { return _lang; },
      set: function(val) {
        if (val === undefined) {
          val = 'undefined';
        }
        _lang = val.toString();
      }
    });

    Object.defineProperty(this, 'continuous', {
      get: function() { return _continuous; },
      set: function(val) {
        _continuous = Boolean(val);
      }
    });

    Object.defineProperty(this, 'interimResults', {
      get: function() { return _interimResults; },
      set: function(val) {
        _interimResults = Boolean(val);
      }
    });

    this.start = function() {
      if (_self._started) {
        throw new DOMException('Failed to execute \'start\' on \'SpeechRecognition\': recognition has already started.');
      }
      _self._started = true;
      // Create and dispatch an event
      var event = document.createEvent('CustomEvent');
      event.initCustomEvent('start', false, false, null);
      _listeners.dispatchEvent(event);
    };

    this.abort = function() {
      if (!_self._started) {
        return;
      }
      _self._started = false;
      // Create and dispatch an event
      var event = document.createEvent('CustomEvent');
      event.initCustomEvent('end', false, false, null);
      _listeners.dispatchEvent(event);
    };

    this.stop = function() {
      return _self.abort();
    };

    this.isStarted = function() {
      return _self._started;
    };

    this.say = function(sentence) {
      // Create some speech alternatives
      var results = [];
      var commandIterator;
      var etcIterator;
      var itemFunction = function(index) {
        if (undefined === index) {
          throw new DOMException('Failed to execute \'item\' on \'SpeechRecognitionResult\': 1 argument required, but only 0 present.');
        }
        index = Number(index);
        if (isNaN(index)) {
          index = 0;
        }
        if (index >= this.length) {
          return null;
        } else {
          return this[index];
        }
      };
      for (commandIterator = 0; commandIterator<_maxAlternatives; commandIterator++) {
        var etc = '';
        for (etcIterator = 0; etcIterator<commandIterator; etcIterator++) {
          etc += ' and so on';
        }
        results.push(sentence+etc);
      }

      // Create the event
      var event = document.createEvent('CustomEvent');
      event.initCustomEvent('result', false, false, {'sentence': sentence});
      event.resultIndex = 0;
      event.results = {
        'item': itemFunction,
        0: {
          'item': itemFunction,
          'final': true
        }
      };
      for (commandIterator = 0; commandIterator<_maxAlternatives; commandIterator++) {
        event.results[0][commandIterator] = {
          'transcript': results[commandIterator],
          'confidence': Math.max(1-0.01*commandIterator, 0.001)
        };
      }
      Object.defineProperty(event.results, 'length', {
        get: function() { return 1; }
      });
      Object.defineProperty(event.results[0], 'length', {
        get: function() { return _maxAlternatives; }
      });
      event.interpretation = null;
      event.emma = null;
      _listeners.dispatchEvent(event);
    };

    this.addEventListener = function(event, callback) {
      _listeners.addEventListener(event, callback, false);
    };
  };

  // Expose functionality
  _root.Corti = {
    patch: function() {
      if (_productionVersion === false) {
        _productionVersion = _root.SpeechRecognition ||
          _root.webkitSpeechRecognition ||
          _root.mozSpeechRecognition ||
          _root.msSpeechRecognition ||
          _root.oSpeechRecognition;
      }
      _root.SpeechRecognition = newSpeechRecognition;
    },

    unpatch: function() {
      _root.SpeechRecognition = _productionVersion;
    }
  };

}).call(this);
<|endoftext|>


<commit_before>// Copyright 2014 Volker Sorge
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Basic interface functionality for the Speech Rule Engine.
 *
 * @author volker.sorge@gmail.com (Volker Sorge)
 */
goog.provide('sre.System');

goog.require('sre.AuralRendering');
goog.require('sre.BaseUtil');
goog.require('sre.Debugger');
goog.require('sre.DomUtil');
goog.require('sre.DynamicCstr');
goog.require('sre.Engine');
goog.require('sre.Engine.Error');
goog.require('sre.Enrich');
goog.require('sre.HighlighterFactory');
goog.require('sre.L10n');
goog.require('sre.MathStore');
goog.require('sre.ProcessorFactory');
goog.require('sre.Semantic');
goog.require('sre.SpeechGeneratorFactory');
goog.require('sre.SpeechGeneratorUtil');
goog.require('sre.SpeechRuleEngine');
goog.require('sre.SpeechRuleStores');
goog.require('sre.SystemExternal');
goog.require('sre.Variables');
goog.require('sre.WalkerFactory');
goog.require('sre.WalkerUtil');

/**
 * @constructor
 */
sre.System = function() {

  /**
   * Version number.
   * @type {string}
   */
  this.version = sre.Variables.VERSION;

};
goog.addSingletonGetter(sre.System);

/**
 *  Setup Methods functionality.
 */
// These are all API interface functions. Therefore, avoid any usage of "this"
// in the code.
/**
 * Method to setup and intialize the speech rule engine. Currently the feature
 * parameter is ignored, however, this could be used to fine tune the setup.
 * @param {Object.<boolean|string>} feature An object describing some
 *     setup features.
 */
sre.System.prototype.setupEngine = function(feature) {
  var engine = sre.Engine.getInstance();
  var setIf = function(feat) {
    if (typeof feature[feat] !== 'undefined') {
      engine[feat] = !!feature[feat];
    }
  };
  var setMulti = function(feat) {
    engine[feat] = feature[feat] || engine[feat];
  };
  var binaryFeatures = ['strict', 'cache', 'semantics', 'structure', 'pprint'];
  var stringFeatures = ['markup', 'style', 'domain', 'speech', 'walker',
                        'locale', 'rate'];
  setMulti('mode');
  sre.System.prototype.configBlocks_(feature);
  binaryFeatures.forEach(setIf);
  stringFeatures.forEach(setMulti);
  if (feature.json) {
    sre.SystemExternal.jsonPath = sre.BaseUtil.makePath(feature.json);
  }
  if (feature.xpath) {
    sre.SystemExternal.WGXpath = feature.xpath;
  }
  engine.setupBrowsers();
  engine.ruleSets = feature.rules ? feature.rules :
      sre.SpeechRuleStores.availableSets();
  sre.SpeechRuleEngine.getInstance().parameterize(engine.ruleSets);
  engine.dynamicCstr = engine.parser.parse(
      engine.locale + '.' + engine.domain + '.' + engine.style);
  var comparator = engine.comparators[engine.domain];
  engine.comparator = comparator ? comparator() :
      new sre.DynamicCstr.DefaultComparator(
      engine.dynamicCstr,
      sre.DynamicProperties.create(
      [sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.LOCALE]],
      [sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.DOMAIN]],
      ['short', sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.STYLE]]));
  sre.L10n.setLocale();
};

/**
 * Reads configuration blocks and adds them to the feature vector.
 * @param {Object.<boolean|string>} feature An object describing some
 *     setup features.
 * @private
 */
sre.System.prototype.configBlocks_ = function(feature) {
  if (sre.Engine.getInstance().mode !== sre.Engine.Mode.HTTP) {
    return;
  }
  var scripts = document.documentElement.querySelectorAll(
      'script[type="text/x-sre-config"]');
  for (var i = 0, m = scripts.length; i < m; i++) {
    try {
      var inner = scripts[i].innerHTML;
      var config = JSON.parse(inner);
      for (var f in config) {
        feature[f] = config[f];
      }
    }
    catch (err) {
      sre.Debugger.getInstance().output('Illegal configuration ', inner);
    }
  }
};

/**
 * Setting engine to async mode once it is ready.
 */
sre.System.setAsync = function() {
  if (!sre.Engine.isReady()) {
    setTimeout(sre.System.setAsync, 500);
  }
  (sre.System.getInstance()).setupEngine({'mode': sre.Engine.Mode.ASYNC});
};

//
// Naming convention:
// Input is either an XML expression as a string or from a file.
//
// Output:
//  toSpeech: Aural rendering string.
//  toSemantic: XML of semantic tree.
//  toJson: Json version of the semantic tree.
//  toEnriched: Enriched MathML node.
//  toDescription: List of auditory descriptions.
//
// Output for the file version are strings.
//
//TODO: (sorge) Need an async versions of these.
/**
 * Main function to translate expressions into auditory descriptions.
 * @param {string} expr Processes a given XML expression for translation.
 * @return {string} The aural rendering of the expression.
 */
sre.System.prototype.toSpeech = function(expr) {
  return sre.System.getInstance().processString('speech', expr);
};

/**
 * @deprecated Use toSpeech().
 */
sre.System.prototype.processExpression = sre.System.prototype.toSpeech;

/**
 * Function to translate MathML string into Semantic Tree.
 * @param {string} expr Processes a given MathML expression for translation.
 * @return {Node} The semantic tree as Xml.
 */
sre.System.prototype.toSemantic = function(expr) {
  return sre.System.getInstance().processString('semantic', expr);
};

/**
 * Function to translate MathML string into JSON version of the Semantic Tree.
 * @param {string} expr Processes a given MathML expression for translation.
 * @return {JSONType} The semantic tree as Json.
 */
sre.System.prototype.toJson = function(expr) {
  return sre.System.getInstance().processString('json', expr);
};

/**
 * Main function to translate expressions into auditory descriptions.
 * @param {string} expr Processes a given Xml expression for translation.
 * @return {!Array.<sre.AuditoryDescription>} The auditory descriptions.
 */
sre.System.prototype.toDescription = function(expr) {
  return sre.System.getInstance().processString('description', expr);
};

/**
 * Function to translate MathML string into semantically enriched MathML.
 * @param {string} expr Processes a given MathML expression for translation.
 * @return {!Element} The enriched MathML node.
 */
sre.System.prototype.toEnriched = function(expr) {
  return sre.System.getInstance().processString('enriched', expr);
};

/**
 * Processes an input string with the given processor.
 * @param {string} processor The name of the processor to call.
 * @param {string} input The input string.
 * @return {T} The computed data structure.
 * @template T
 */
sre.System.prototype.processString = function(processor, input) {
  return sre.ProcessorFactory.process(processor, input);
};

/**
 * Reads an xml expression from a file and returns its aural rendering to a
 * file.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.fileToSpeech = function(input, opt_output) {
  sre.System.getInstance().processFile('speech', input, opt_output);
};

/**
 * @deprecated Use fileToSpeech().
 */
sre.System.prototype.processFile = sre.System.prototype.fileToSpeech;

/**
 * Reads an xml expression from a file and returns the XML for the semantic tree
 * to a file.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.fileToSemantic = function(input, opt_output) {
  sre.System.getInstance().processFile('semantic', input, opt_output);
};

/**
 * Function to translate MathML string into JSON version of the Semantic Tree to
 * a file.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.fileToJson = function(input, opt_output) {
  sre.System.getInstance().processFile('json', input, opt_output);
};

/**
 * Main function to translate expressions into auditory descriptions
 * a file.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.fileToDescription = function(input, opt_output) {
  sre.System.getInstance().processFile('description', input, opt_output);
};

/**
 * Function to translate MathML string into semantically enriched MathML in a
 * file.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.fileToEnriched = function(input, opt_output) {
  sre.System.getInstance().processFile('enriched', input, opt_output);
};

/**
 * Reads an xml expression from a file, processes with the given function and
 * returns the result either to a file or to stdout.
 * @param {string} processor The name of the processor to call.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.processFile = function(processor, input, opt_output) {
  if (!sre.Engine.isReady()) {
    setTimeout(goog.bind(function() {
      this.processFile(processor, input, opt_output);
    }, this), 100);
    return;
  }
  if (sre.Engine.getInstance().mode === sre.Engine.Mode.SYNC) {
    this.processFileSync_(processor, input, opt_output);
    return;
  }
  this.processFileAsync_(processor, input, opt_output);
};

/**
 * Reads an xml expression from a file. Throws exception if file does not exist.
 * @param {string} file The input filename.
 * @return {string} The input string read from file.
 * @private
 */
sre.System.prototype.inputFileSync_ = function(file) {
  try {
    var expr = sre.SystemExternal.fs.readFileSync(file, {encoding: 'utf8'});
  } catch (err) {
    throw new sre.Engine.Error('Can not open file: ' + file);
  }
  return expr;
};

/**
 * Reads an xml expression from a file, processes with the given function and
 * returns the result either to a file or to stdout in synchronous mode.
 * @param {string} processor The name of the processor.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 * @private
 */
sre.System.prototype.processFileSync_ = function(processor, input, opt_output) {
  var expr = sre.System.getInstance().inputFileSync_(input);
  var result = sre.ProcessorFactory.output(processor, expr);
  if (!opt_output) {
    console.info(result);
    return;
  }
  try {
    sre.SystemExternal.fs.writeFileSync(opt_output, result);
  } catch (err) {
    throw new sre.Engine.Error('Can not write to file: ' + opt_output);
  }
};

/**
 * Reads an xml expression from a file. Throws exception if file does not exist.
 * @param {string} file The input filename.
 * @param {function(string)} callback The callback to apply to the input.
 * @private
 */
sre.System.prototype.inputFileAsync_ = function(file, callback) {
  sre.SystemExternal.fs.readFile(
      file, {encoding: 'utf8'},
      goog.bind(function(err, data) {
        if (err) {
          throw new sre.Engine.Error('Can not open file: ' + file);
        }
        callback(data);
      }, this)
  );
};

/**
 * Reads an xml expression from a file, processes with the given function and
 * returns the result either to a file or to stdout in asynchronous mode.
 * @param {string} processor The name of the processor.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 * @private
 */
sre.System.prototype.processFileAsync_ = function(
    processor, input, opt_output) {
  sre.System.getInstance().inputFileAsync_(
      input,
      goog.bind(function(expr) {
        var result = sre.ProcessorFactory.output(processor, expr);
        if (!opt_output) {
          console.info(result);
          return;
        }
        sre.SystemExternal.fs.writeFile(opt_output, result, function(err) {
          if (err) {
            throw new sre.Engine.Error('Can not write to file: ' + opt_output);
          }
        });
      }, this));
};

// These are experimental and do not yet fit into the new processor setup.
/**
 * Walk a math expression provided by an external system.
 * @param {string} expr The string containing a MathML representation.
 * @return {string} The initial speech string for that expression.
 */
sre.System.prototype.walk = function(expr) {
  return sre.ProcessorFactory.output('walker', expr);
};

/**
 * Moves in the math expression that is currently being walked.
 * @param {sre.EventUtil.KeyCode|string} direction The direction of the move
 *     given either as string or keycode.
 * @return {?string} The speech string generated by the walk. Null if a boundary
 *     is hit.
 */
sre.System.prototype.move = function(direction) {
  return sre.ProcessorFactory.keypress('move', direction);
};
<commit_msg>Integrates external walking methods into processor framework.<commit_after>// Copyright 2014 Volker Sorge
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

/**
 * @fileoverview Basic interface functionality for the Speech Rule Engine.
 *
 * @author volker.sorge@gmail.com (Volker Sorge)
 */
goog.provide('sre.System');

goog.require('sre.AuralRendering');
goog.require('sre.BaseUtil');
goog.require('sre.Debugger');
goog.require('sre.DomUtil');
goog.require('sre.DynamicCstr');
goog.require('sre.Engine');
goog.require('sre.Engine.Error');
goog.require('sre.Enrich');
goog.require('sre.HighlighterFactory');
goog.require('sre.L10n');
goog.require('sre.MathStore');
goog.require('sre.ProcessorFactory');
goog.require('sre.Semantic');
goog.require('sre.SpeechGeneratorFactory');
goog.require('sre.SpeechGeneratorUtil');
goog.require('sre.SpeechRuleEngine');
goog.require('sre.SpeechRuleStores');
goog.require('sre.SystemExternal');
goog.require('sre.Variables');
goog.require('sre.WalkerFactory');
goog.require('sre.WalkerUtil');

/**
 * @constructor
 */
sre.System = function() {

  /**
   * Version number.
   * @type {string}
   */
  this.version = sre.Variables.VERSION;

};
goog.addSingletonGetter(sre.System);

/**
 *  Setup Methods functionality.
 */
// These are all API interface functions. Therefore, avoid any usage of "this"
// in the code.
/**
 * Method to setup and intialize the speech rule engine. Currently the feature
 * parameter is ignored, however, this could be used to fine tune the setup.
 * @param {Object.<boolean|string>} feature An object describing some
 *     setup features.
 */
sre.System.prototype.setupEngine = function(feature) {
  var engine = sre.Engine.getInstance();
  var setIf = function(feat) {
    if (typeof feature[feat] !== 'undefined') {
      engine[feat] = !!feature[feat];
    }
  };
  var setMulti = function(feat) {
    engine[feat] = feature[feat] || engine[feat];
  };
  var binaryFeatures = ['strict', 'cache', 'semantics', 'structure', 'pprint'];
  var stringFeatures = ['markup', 'style', 'domain', 'speech', 'walker',
                        'locale', 'rate'];
  setMulti('mode');
  sre.System.prototype.configBlocks_(feature);
  binaryFeatures.forEach(setIf);
  stringFeatures.forEach(setMulti);
  if (feature.json) {
    sre.SystemExternal.jsonPath = sre.BaseUtil.makePath(feature.json);
  }
  if (feature.xpath) {
    sre.SystemExternal.WGXpath = feature.xpath;
  }
  engine.setupBrowsers();
  engine.ruleSets = feature.rules ? feature.rules :
      sre.SpeechRuleStores.availableSets();
  sre.SpeechRuleEngine.getInstance().parameterize(engine.ruleSets);
  engine.dynamicCstr = engine.parser.parse(
      engine.locale + '.' + engine.domain + '.' + engine.style);
  var comparator = engine.comparators[engine.domain];
  engine.comparator = comparator ? comparator() :
      new sre.DynamicCstr.DefaultComparator(
      engine.dynamicCstr,
      sre.DynamicProperties.create(
      [sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.LOCALE]],
      [sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.DOMAIN]],
      ['short', sre.DynamicCstr.DEFAULT_VALUES[sre.DynamicCstr.Axis.STYLE]]));
  sre.L10n.setLocale();
};

/**
 * Reads configuration blocks and adds them to the feature vector.
 * @param {Object.<boolean|string>} feature An object describing some
 *     setup features.
 * @private
 */
sre.System.prototype.configBlocks_ = function(feature) {
  if (sre.Engine.getInstance().mode !== sre.Engine.Mode.HTTP) {
    return;
  }
  var scripts = document.documentElement.querySelectorAll(
      'script[type="text/x-sre-config"]');
  for (var i = 0, m = scripts.length; i < m; i++) {
    try {
      var inner = scripts[i].innerHTML;
      var config = JSON.parse(inner);
      for (var f in config) {
        feature[f] = config[f];
      }
    }
    catch (err) {
      sre.Debugger.getInstance().output('Illegal configuration ', inner);
    }
  }
};

/**
 * Setting engine to async mode once it is ready.
 */
sre.System.setAsync = function() {
  if (!sre.Engine.isReady()) {
    setTimeout(sre.System.setAsync, 500);
  }
  (sre.System.getInstance()).setupEngine({'mode': sre.Engine.Mode.ASYNC});
};

//
// Naming convention:
// Input is either an XML expression as a string or from a file.
//
// Output:
//  toSpeech: Aural rendering string.
//  toSemantic: XML of semantic tree.
//  toJson: Json version of the semantic tree.
//  toEnriched: Enriched MathML node.
//  toDescription: List of auditory descriptions.
//
// Output for the file version are strings.
//
//TODO: (sorge) Need an async versions of these.
/**
 * Main function to translate expressions into auditory descriptions.
 * @param {string} expr Processes a given XML expression for translation.
 * @return {string} The aural rendering of the expression.
 */
sre.System.prototype.toSpeech = function(expr) {
  return sre.System.getInstance().processString('speech', expr);
};

/**
 * @deprecated Use toSpeech().
 */
sre.System.prototype.processExpression = sre.System.prototype.toSpeech;

/**
 * Function to translate MathML string into Semantic Tree.
 * @param {string} expr Processes a given MathML expression for translation.
 * @return {Node} The semantic tree as Xml.
 */
sre.System.prototype.toSemantic = function(expr) {
  return sre.System.getInstance().processString('semantic', expr);
};

/**
 * Function to translate MathML string into JSON version of the Semantic Tree.
 * @param {string} expr Processes a given MathML expression for translation.
 * @return {JSONType} The semantic tree as Json.
 */
sre.System.prototype.toJson = function(expr) {
  return sre.System.getInstance().processString('json', expr);
};

/**
 * Main function to translate expressions into auditory descriptions.
 * @param {string} expr Processes a given Xml expression for translation.
 * @return {!Array.<sre.AuditoryDescription>} The auditory descriptions.
 */
sre.System.prototype.toDescription = function(expr) {
  return sre.System.getInstance().processString('description', expr);
};

/**
 * Function to translate MathML string into semantically enriched MathML.
 * @param {string} expr Processes a given MathML expression for translation.
 * @return {!Element} The enriched MathML node.
 */
sre.System.prototype.toEnriched = function(expr) {
  return sre.System.getInstance().processString('enriched', expr);
};

/**
 * Processes an input string with the given processor.
 * @param {string} processor The name of the processor to call.
 * @param {string} input The input string.
 * @return {T} The computed data structure.
 * @template T
 */
sre.System.prototype.processString = function(processor, input) {
  return sre.ProcessorFactory.process(processor, input);
};

/**
 * Reads an xml expression from a file and returns its aural rendering to a
 * file.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.fileToSpeech = function(input, opt_output) {
  sre.System.getInstance().processFile('speech', input, opt_output);
};

/**
 * @deprecated Use fileToSpeech().
 */
sre.System.prototype.processFile = sre.System.prototype.fileToSpeech;

/**
 * Reads an xml expression from a file and returns the XML for the semantic tree
 * to a file.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.fileToSemantic = function(input, opt_output) {
  sre.System.getInstance().processFile('semantic', input, opt_output);
};

/**
 * Function to translate MathML string into JSON version of the Semantic Tree to
 * a file.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.fileToJson = function(input, opt_output) {
  sre.System.getInstance().processFile('json', input, opt_output);
};

/**
 * Main function to translate expressions into auditory descriptions
 * a file.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.fileToDescription = function(input, opt_output) {
  sre.System.getInstance().processFile('description', input, opt_output);
};

/**
 * Function to translate MathML string into semantically enriched MathML in a
 * file.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.fileToEnriched = function(input, opt_output) {
  sre.System.getInstance().processFile('enriched', input, opt_output);
};

/**
 * Reads an xml expression from a file, processes with the given function and
 * returns the result either to a file or to stdout.
 * @param {string} processor The name of the processor to call.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 */
sre.System.prototype.processFile = function(processor, input, opt_output) {
  if (!sre.Engine.isReady()) {
    setTimeout(goog.bind(function() {
      this.processFile(processor, input, opt_output);
    }, this), 100);
    return;
  }
  if (sre.Engine.getInstance().mode === sre.Engine.Mode.SYNC) {
    this.processFileSync_(processor, input, opt_output);
    return;
  }
  this.processFileAsync_(processor, input, opt_output);
};

/**
 * Reads an xml expression from a file. Throws exception if file does not exist.
 * @param {string} file The input filename.
 * @return {string} The input string read from file.
 * @private
 */
sre.System.prototype.inputFileSync_ = function(file) {
  try {
    var expr = sre.SystemExternal.fs.readFileSync(file, {encoding: 'utf8'});
  } catch (err) {
    throw new sre.Engine.Error('Can not open file: ' + file);
  }
  return expr;
};

/**
 * Reads an xml expression from a file, processes with the given function and
 * returns the result either to a file or to stdout in synchronous mode.
 * @param {string} processor The name of the processor.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 * @private
 */
sre.System.prototype.processFileSync_ = function(processor, input, opt_output) {
  var expr = sre.System.getInstance().inputFileSync_(input);
  var result = sre.ProcessorFactory.output(processor, expr);
  if (!opt_output) {
    console.info(result);
    return;
  }
  try {
    sre.SystemExternal.fs.writeFileSync(opt_output, result);
  } catch (err) {
    throw new sre.Engine.Error('Can not write to file: ' + opt_output);
  }
};

/**
 * Reads an xml expression from a file. Throws exception if file does not exist.
 * @param {string} file The input filename.
 * @param {function(string)} callback The callback to apply to the input.
 * @private
 */
sre.System.prototype.inputFileAsync_ = function(file, callback) {
  sre.SystemExternal.fs.readFile(
      file, {encoding: 'utf8'},
      goog.bind(function(err, data) {
        if (err) {
          throw new sre.Engine.Error('Can not open file: ' + file);
        }
        callback(data);
      }, this)
  );
};

/**
 * Reads an xml expression from a file, processes with the given function and
 * returns the result either to a file or to stdout in asynchronous mode.
 * @param {string} processor The name of the processor.
 * @param {string} input The input filename.
 * @param {string=} opt_output The output filename if one is given.
 * @private
 */
sre.System.prototype.processFileAsync_ = function(
    processor, input, opt_output) {
  sre.System.getInstance().inputFileAsync_(
      input,
      goog.bind(function(expr) {
        var result = sre.ProcessorFactory.output(processor, expr);
        if (!opt_output) {
          console.info(result);
          return;
        }
        sre.SystemExternal.fs.writeFile(opt_output, result, function(err) {
          if (err) {
            throw new sre.Engine.Error('Can not write to file: ' + opt_output);
          }
        });
      }, this));
};

// These are still considered experimental.
/**
 * Walk a math expression provided by an external system.
 * @param {string} expr The string containing a MathML representation.
 * @return {string} The initial speech string for that expression.
 */
sre.System.prototype.walk = function(expr) {
  return sre.ProcessorFactory.output('walker', expr);
};

/**
 * Moves in the math expression that is currently being walked.
 * @param {sre.EventUtil.KeyCode|string} direction The direction of the move
 *     given either as string or keycode.
 * @return {?string} The speech string generated by the walk. Null if a boundary
 *     is hit.
 */
sre.System.prototype.move = function(direction) {
  return sre.ProcessorFactory.keypress('move', direction);
};
<|endoftext|>