<commit_before>// Require any node modules to be used here
// Need to do this until able to modify webpack config in Angular CLI
var fs = require('fs');
var electron = require('electron');
var path = require('path');
var url = require('url');
var client;
// Add all 3rd party node_modules included in the Electron app to be able to be used
module.paths.push(path.resolve(electron.remote.app.getAppPath() + '/node_modules'));
// if LIVE_UPDATE env variable is true then use electron-connect
if (electron.remote.process.env.LIVE_UPDATE === "true") {
    client = require('electron-connect').client.create();
    client.on("reloadit", function() {
      electron.remote.getCurrentWindow().loadURL(url.format({
            pathname: 'index.html',
            protocol: 'file:',
            slashes: true
        }));
    });
}<commit_msg>Fixing bug with live-reload where after reload moving the app window causes an error.  Need to release all the callback listeners before reloading (#16)<commit_after>// Require any node modules to be used here
// Need to do this until able to modify webpack config in Angular CLI
var fs = require('fs');
var electron = require('electron');
var path = require('path');
var url = require('url');
var client;
// Add all 3rd party node_modules included in the Electron app to be able to be used
module.paths.push(path.resolve(electron.remote.app.getAppPath() + '/node_modules'));
// if LIVE_UPDATE env variable is true then use electron-connect
if (electron.remote.process.env.LIVE_UPDATE === "true") {
    client = require('electron-connect').client.create();
    client.on("reloadit", function() {
      electron.remote.getCurrentWindow().removeAllListeners();
      electron.remote.getCurrentWindow().loadURL(url.format({
            pathname: 'index.html',
            protocol: 'file:',
            slashes: true
        }));
    });
}<|endoftext|>


<commit_before>(function() {
    define(['engine/EventSet'], function(EventSet) {
        var Camera = function(screen) {
            this.screen = screen;
            this.x = 0;
            this.y = 0;
        };

        Camera.extend(EventSet);

        Camera.prototype.inViewPort = function(x, y, w, h) {
            return Boolean(this.screen.innerPoint(x, y) || this.screen.innerPoint(x + w, y) || this.screen.innerPoint(x, y + h) || this.screen.innerPoint(x + w, y + h));
        };

        Camera.prototype.update = function(x, y) {
            this.fire('update', x, y);
            if (x && y) {
                if (x !== this.x || y !== this.y) {
                    this.fire('change', x, y);
                }
                this.x = x;
                this.y = y;
            }

            return this;
        };

        return Camera;
    });
})();<commit_msg>Commented Camera<commit_after>/**
 * @file implements Camera class
 * @author CORSAIR <vladimir.corsair@gmail.com>
 *
 */
(function() {
    define(['engine/EventSet'], function(EventSet) {
        var Camera = function(screen) {
            this.screen = screen;
            this.x = 0;
            this.y = 0;
        };

        Camera.extend(EventSet);

        Camera.prototype.inViewPort = function(x, y, w, h) {
            return Boolean(this.screen.innerPoint(x, y) || this.screen.innerPoint(x + w, y) || this.screen.innerPoint(x, y + h) || this.screen.innerPoint(x + w, y + h));
        };

        Camera.prototype.update = function(x, y) {
            this.fire('update', x, y);
            if (x && y) {
                if (x !== this.x || y !== this.y) {
                    this.fire('change', x, y);
                }
                this.x = x;
                this.y = y;
            }

            return this;
        };

        return Camera;
    });
})();<|endoftext|>


<commit_before>var YieldTimers = require('../util/yieldtimers.js');

/**
 * A thread is a running stack context and all the metadata needed.
 * @param {?string} firstBlock First block to execute in the thread.
 * @constructor
 */
function Thread (firstBlock) {
    /**
     * ID of top block of the thread
     * @type {!string}
     */
    this.topBlock = firstBlock;

    /**
     * Stack for the thread. When the sequencer enters a control structure,
     * the block is pushed onto the stack so we know where to exit.
     * @type {Array.<string>}
     */
    this.stack = [];

    /**
     * Stack frames for the thread. Store metadata for the executing blocks.
     * @type {Array.<Object>}
     */
    this.stackFrames = [];

    /**
     * Status of the thread, one of three states (below)
     * @type {number}
     */
    this.status = 0; /* Thread.STATUS_RUNNING */

    /**
     * Execution-synced timeouts.
     * @type {number}
     */
    this.timeoutIds = [];
}

/**
 * Thread status for initialized or running thread.
 * Threads are in this state when the primitive is called for the first time.
 * @const
 */
Thread.STATUS_RUNNING = 0;

/**
 * Thread status for a yielded thread.
 * Threads are in this state when a primitive has yielded.
 * @const
 */
Thread.STATUS_YIELD = 1;

/**
 * Thread status for a finished/done thread.
 * Thread is moved to this state when the interpreter
 * can proceed with execution.
 * @const
 */
Thread.STATUS_DONE = 2;

/**
 * Push stack and update stack frames appropriately.
 * @param {string} blockId Block ID to push to stack.
 */
Thread.prototype.pushStack = function (blockId) {
    this.stack.push(blockId);
    // Push an empty stack frame, if we need one.
    // Might not, if we just popped the stack.
    if (this.stack.length > this.stackFrames.length) {
        this.stackFrames.push({
            reported: {}, // Collects reported input values.
            waitingReporter: null, // Name of waiting reporter.
            executionContext: {} // A context passed to block implementations.
        });
    }
};

/**
 * Pop last block on the stack and its stack frame.
 * @return {string} Block ID popped from the stack.
 */
Thread.prototype.popStack = function () {
    this.stackFrames.pop();
    return this.stack.pop();
};

/**
 * Get top stack item.
 * @return {?string} Block ID on top of stack.
 */
Thread.prototype.peekStack = function () {
    return this.stack[this.stack.length - 1];
};

/**
 * Get top stack frame.
 * @return {?Object} Last stack frame stored on this thread.
 */
Thread.prototype.peekStackFrame = function () {
    return this.stackFrames[this.stackFrames.length - 1];
};

/**
 * Push a reported value to the parent of the current stack frame.
 * @param {!Any} value Reported value to push.
 */
Thread.prototype.pushReportedValue = function (value) {
    var parentStackFrame = this.stackFrames[this.stackFrames.length - 2];
    if (parentStackFrame) {
        var waitingReporter = parentStackFrame.waitingReporter;
        parentStackFrame.reported[waitingReporter] = value;
        parentStackFrame.waitingReporter = null;
    }
};

/**
 * Yields the thread.
 */
Thread.prototype.yield = function () {
    this.status = Thread.STATUS_YIELD;
};

/**
 * Add an execution-synced timeouts for this thread.
 * See also: util/yieldtimers.js:timeout
 * @param {!Function} callback To be called when the timer is done.
 * @param {number} timeDelta Time to wait, in ms.
 */
Thread.prototype.addTimeout = function (callback, timeDelta) {
    var timeoutId = YieldTimers.timeout(callback, timeDelta);
    this.timeoutIds.push(timeoutId);
};

/**
 * Attempt to resolve all execution-synced timeouts on this thread.
 */
Thread.prototype.resolveTimeouts = function () {
    var newTimeouts = [];
    for (var i = 0; i < this.timeoutIds.length; i++) {
        var resolved = YieldTimers.resolve(this.timeoutIds[i]);
        if (!resolved) {
            newTimeouts.push(this.timeoutIds[i]);
        }
    }
    this.timeoutIds = newTimeouts;
};

module.exports = Thread;
<commit_msg>Refactor Thread.peekParentStackFrame<commit_after>var YieldTimers = require('../util/yieldtimers.js');

/**
 * A thread is a running stack context and all the metadata needed.
 * @param {?string} firstBlock First block to execute in the thread.
 * @constructor
 */
function Thread (firstBlock) {
    /**
     * ID of top block of the thread
     * @type {!string}
     */
    this.topBlock = firstBlock;

    /**
     * Stack for the thread. When the sequencer enters a control structure,
     * the block is pushed onto the stack so we know where to exit.
     * @type {Array.<string>}
     */
    this.stack = [];

    /**
     * Stack frames for the thread. Store metadata for the executing blocks.
     * @type {Array.<Object>}
     */
    this.stackFrames = [];

    /**
     * Status of the thread, one of three states (below)
     * @type {number}
     */
    this.status = 0; /* Thread.STATUS_RUNNING */

    /**
     * Execution-synced timeouts.
     * @type {number}
     */
    this.timeoutIds = [];
}

/**
 * Thread status for initialized or running thread.
 * Threads are in this state when the primitive is called for the first time.
 * @const
 */
Thread.STATUS_RUNNING = 0;

/**
 * Thread status for a yielded thread.
 * Threads are in this state when a primitive has yielded.
 * @const
 */
Thread.STATUS_YIELD = 1;

/**
 * Thread status for a finished/done thread.
 * Thread is moved to this state when the interpreter
 * can proceed with execution.
 * @const
 */
Thread.STATUS_DONE = 2;

/**
 * Push stack and update stack frames appropriately.
 * @param {string} blockId Block ID to push to stack.
 */
Thread.prototype.pushStack = function (blockId) {
    this.stack.push(blockId);
    // Push an empty stack frame, if we need one.
    // Might not, if we just popped the stack.
    if (this.stack.length > this.stackFrames.length) {
        this.stackFrames.push({
            reported: {}, // Collects reported input values.
            waitingReporter: null, // Name of waiting reporter.
            executionContext: {} // A context passed to block implementations.
        });
    }
};

/**
 * Pop last block on the stack and its stack frame.
 * @return {string} Block ID popped from the stack.
 */
Thread.prototype.popStack = function () {
    this.stackFrames.pop();
    return this.stack.pop();
};

/**
 * Get top stack item.
 * @return {?string} Block ID on top of stack.
 */
Thread.prototype.peekStack = function () {
    return this.stack[this.stack.length - 1];
};

/**
 * Get top stack frame.
 * @return {?Object} Last stack frame stored on this thread.
 */
Thread.prototype.peekStackFrame = function () {
    return this.stackFrames[this.stackFrames.length - 1];
};

/**
 * Get stack frame above the current top.
 * @return {?Object} Second to last stack frame stored on this thread.
 */
Thread.prototype.peekParentStackFrame = function () {
    return this.stackFrames[this.stackFrames.length - 2];
};

/**
 * Push a reported value to the parent of the current stack frame.
 * @param {!Any} value Reported value to push.
 */
Thread.prototype.pushReportedValue = function (value) {
    var parentStackFrame = this.peekParentStackFrame();
    if (parentStackFrame) {
        var waitingReporter = parentStackFrame.waitingReporter;
        parentStackFrame.reported[waitingReporter] = value;
        parentStackFrame.waitingReporter = null;
    }
};

/**
 * Yields the thread.
 */
Thread.prototype.yield = function () {
    this.status = Thread.STATUS_YIELD;
};

/**
 * Add an execution-synced timeouts for this thread.
 * See also: util/yieldtimers.js:timeout
 * @param {!Function} callback To be called when the timer is done.
 * @param {number} timeDelta Time to wait, in ms.
 */
Thread.prototype.addTimeout = function (callback, timeDelta) {
    var timeoutId = YieldTimers.timeout(callback, timeDelta);
    this.timeoutIds.push(timeoutId);
};

/**
 * Attempt to resolve all execution-synced timeouts on this thread.
 */
Thread.prototype.resolveTimeouts = function () {
    var newTimeouts = [];
    for (var i = 0; i < this.timeoutIds.length; i++) {
        var resolved = YieldTimers.resolve(this.timeoutIds[i]);
        if (!resolved) {
            newTimeouts.push(this.timeoutIds[i]);
        }
    }
    this.timeoutIds = newTimeouts;
};

module.exports = Thread;
<|endoftext|>


<commit_before>define(function () {
  'use strict';

  /**
   * A mixin, providing event emitting capabilities to a class. Events are simply string identifiers. When they are
   * emitted, zero or more parameters can be passed as arguments to the listening functions.
   * @exports bff/event-emitter
   * @mixin
   */
  var EventEmitter = {
    /**
     * Emit an event.
     * @arg {string} eventName - Identifier string for the event.
     * @arg {...any} [eventArguments] - Zero or more arguments that event listeners will be called with.
     * @returns {undefined}
     */
    emit: function emit(eventName) {
      if (RUNTIME_CHECKS && typeof eventName !== 'string') {
        throw '"eventName" argument must be a string';
      }

      if (!this.__private) { return; }
      if (!this.__private.listeners) { return; }

      var listenersForEvent = this.__private.listeners[eventName];
      if (!listenersForEvent) { return; }

      var length = listenersForEvent.length;
      for (var i = 0; i < length; ++i) {
        var listener = listenersForEvent[i];
        listener.call.apply(listener, arguments); // Call the listener without the first item in the "arguments" array
      }
    },

    /**
     * Add an event listener function that will be called whenever the given event is emitted. Trying to add the exact
     * same function twice till throw an error, as that is rarely ever the intention and a common source of errors.
     * @arg {string} eventName - Identifier string for the event that is to be listened to.
     * @arg {function} callback - The function that will be called when the event is emitted.
     * @returns {undefined}
     */
    addEventListener: function addEventListener(eventName, callback) {
      if (RUNTIME_CHECKS && typeof eventName !== 'string') {
        throw '"eventName" argument must be a string';
      }
      if (RUNTIME_CHECKS && typeof callback !== 'function') {
        throw '"callback" argument must be a function'; // Catch a common cause of errors
      }

      this.__private || Object.defineProperty(this, '__private', { writable: true, value: {}, });
      var listeners = this.__private.listeners || (this.__private.listeners = {});
      var listenersForEvent = listeners[eventName] || (listeners[eventName] = []);

      if (RUNTIME_CHECKS && listenersForEvent.indexOf(callback) !== -1) {
        throw 'This listener has already been added (event: ' + eventName + ')';
      }

      listenersForEvent.push(callback);
    },

    /**
     * Removes an event listener function. If the function was never a listener, do nothing.
     * @arg {string} eventName - Identifier string for the event in question.
     * @arg {function} [callback] - If not given, all event listeners to the provided eventName will be removed. If
     *     given, only the given callback will be removed from the given eventName.
     * @returns {undefined}
     */
    removeEventListener: function removeEventListener(eventName, callback) {
      if (RUNTIME_CHECKS && typeof eventName !== 'string') {
        throw '"eventName" argument must be a string';
      }
      if (RUNTIME_CHECKS && arguments.length === 2 && typeof callback !== 'function') {
        throw '"callback" argument must be a function'; // Catch a common cause of errors
      }

      if (!this.__private) { return; } // No listeners at all? We are done.
      if (!this.__private.listeners) { return; }

      var listenersForEvent = this.__private.listeners[eventName];
      if (!listenersForEvent) { return; } // No listeners for this event? We are done.

      if (callback) {
        var pos = listenersForEvent.indexOf(callback);
        if (pos === -1) { return; }
        listenersForEvent.splice(pos, 1);
      } else {
        listenersForEvent.length = 0;
      }
      listenersForEvent.length === 0 && (delete this.__private.listeners[eventName]);
    },

  };

  return EventEmitter;

});
<commit_msg>Minor refactor<commit_after>define(function () {
  'use strict';

  /**
   * A mixin, providing event emitting capabilities to a class. Events are simply string identifiers. When they are
   * emitted, zero or more parameters can be passed as arguments to the listening functions.
   * @exports bff/event-emitter
   * @mixin
   */
  var EventEmitter = {
    /**
     * Emit an event.
     * @arg {string} eventName - Identifier string for the event.
     * @arg {...any} [eventArguments] - Zero or more arguments that event listeners will be called with.
     * @returns {undefined}
     */
    emit: function emit(eventName) {
      if (RUNTIME_CHECKS && typeof eventName !== 'string') {
        throw '"eventName" argument must be a string';
      }

      if (!this.__private || !this.__private.listeners) { return; }

      var listenersForEvent = this.__private.listeners[eventName];
      if (!listenersForEvent) { return; }

      for (var i = 0, n = listenersForEvent.length; i < n; ++i) {
        var listener = listenersForEvent[i];
        listener.call.apply(listener, arguments); // Call the listener without the first item in the "arguments" array
      }
    },

    /**
     * Add an event listener function that will be called whenever the given event is emitted. Trying to add the exact
     * same function twice till throw an error, as that is rarely ever the intention and a common source of errors.
     * @arg {string} eventName - Identifier string for the event that is to be listened to.
     * @arg {function} callback - The function that will be called when the event is emitted.
     * @returns {undefined}
     */
    addEventListener: function addEventListener(eventName, callback) {
      if (RUNTIME_CHECKS && typeof eventName !== 'string') {
        throw '"eventName" argument must be a string';
      }
      if (RUNTIME_CHECKS && typeof callback !== 'function') {
        throw '"callback" argument must be a function'; // Catch a common cause of errors
      }

      this.__private || Object.defineProperty(this, '__private', { writable: true, value: {}, });
      var listeners = this.__private.listeners || (this.__private.listeners = {});
      var listenersForEvent = listeners[eventName] || (listeners[eventName] = []);

      if (RUNTIME_CHECKS && listenersForEvent.indexOf(callback) !== -1) {
        throw 'This listener has already been added (event: ' + eventName + ')';
      }

      listenersForEvent.push(callback);
    },

    /**
     * Removes an event listener function. If the function was never a listener, do nothing.
     * @arg {string} eventName - Identifier string for the event in question.
     * @arg {function} [callback] - If not given, all event listeners to the provided eventName will be removed. If
     *     given, only the given callback will be removed from the given eventName.
     * @returns {undefined}
     */
    removeEventListener: function removeEventListener(eventName, callback) {
      if (RUNTIME_CHECKS && typeof eventName !== 'string') {
        throw '"eventName" argument must be a string';
      }
      if (RUNTIME_CHECKS && arguments.length === 2 && typeof callback !== 'function') {
        throw '"callback" argument must be a function'; // Catch a common cause of errors
      }

      // No listeners at all? We are done.
      if (!this.__private || !this.__private.listeners) { return; }

      var listenersForEvent = this.__private.listeners[eventName];
      if (!listenersForEvent) { return; } // No listeners for this event? We are done.

      if (callback) {
        var pos = listenersForEvent.indexOf(callback);
        if (pos === -1) { return; }
        listenersForEvent.splice(pos, 1);
      } else {
        listenersForEvent.length = 0;
      }
      listenersForEvent.length === 0 && (delete this.__private.listeners[eventName]);
    },

  };

  return EventEmitter;

});
<|endoftext|>


<commit_before>define(["react"], function(React){
    return React.createClass({
        render: function(){
            var timerDiv = this.props.timed === "true" ?

 : "";
            var controllerButtons = this.props.showControllerSelection === "true" ?

Select rotation controller

                            <button id="discrete" className="btn btn-default">Discrete</button>
                            <button id="two-axis" className="btn btn-default">Two-Axis Valuator</button>
                            <button id="arcball" className="btn btn-default">Arcball</button>

 : "";
            return

                    <legend id="header-tasks"></legend>

                    {timerDiv}

Reference Orientation

Model to Rotate

Model to Rotate

                    <legend></legend>

Task Controls

                            <button id="save" className="btn btn-default">Submit Task</button>
                            <button id="reload" className="btn btn-default">Reset Orientation</button>
                            <button id="undo" className="btn btn-default">Undo Task Submission</button>

                        {controllerButtons}

        }
    });
});
<commit_msg>Reorganised buttons<commit_after>define(["react"], function(React){
    return React.createClass({
        render: function(){
            var timerDiv = this.props.timed === "true" ?

 : "";
            var controllerButtons = this.props.showControllerSelection === "true" ?

Select rotation controller

                            <button id="discrete" className="btn btn-default">Discrete</button>
                            <button id="two-axis" className="btn btn-default">Two-Axis Valuator</button>
                            <button id="arcball" className="btn btn-default">Arcball</button>

 : "";
            return

                    <legend id="header-tasks"></legend>

                    {timerDiv}

Reference Orientation

Model to Rotate

Model to Rotate

                            <button id="reload" style={{margin:"5px"}} className="btn btn-default">Reset Model Orientation</button>
                            <button id="undo" className="btn btn-default">Undo Task Submission</button>

                        {controllerButtons}

                            <button id="save" className="btn btn-default">Submit Task</button>

        }
    });
});
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * 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.
 */

foam.INTERFACE({
  package: 'foam.dao',
  name: 'Sink',

  methods: [
    {
      name: 'put',
      returns: '',
      args: [
        'sub',
        'obj'
      ],
      code: function() {}
    },
    {
      name: 'remove',
      returns: '',
      args: [
        'sub',
        'obj'
      ],
      code: function() {}
    },
    {
      name: 'eof',
      returns: '',
      args: [],
      code: function() {}
    },
    {
      name: 'reset',
      returns: '',
      args: [ 'sub' ],
      code: function() {}
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'ProxySink',
  implements: [ 'foam.dao.Sink' ],

  documentation: 'Proxy for Sink interface.',

  properties: [
    {
      class: 'Proxy',
      of: 'foam.dao.Sink',
      name: 'delegate'
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'AbstractSink',
  implements: [ 'foam.dao.Sink' ],

  documentation: 'Abstract base class for implementing Sink interface.',

  methods: [
    {
      name: 'put',
      code: function() {}
    },
    {
      name: 'remove',
      code: function() {}
    },
    {
      name: 'eof',
      code: function() {}
    },
    {
      name: 'reset',
      code: function() {}
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'PipeSink',
  extends: 'foam.dao.ProxySink',
  properties: [
    'dao'
  ],
  methods: [
    function reset(sub) {
      this.SUPER(sub);
      this.dao.select(this);
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'ResetListener',
  extends: 'foam.dao.ProxySink',
  documentation: 'Turns all sink events into a reset event.',
  methods: [
    function put(sub) {
      this.reset(sub);
    },
    function remove(sub) {
      this.reset(sub);
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'QuickSink',

  extends: 'foam.dao.AbstractSink',

  properties: [
    {
      class: 'Function',
      name: 'putFn'
    },
    {
      class: 'Function',
      name: 'removeFn'
    },
    {
      class: 'Function',
      name: 'eofFn'
    },
    {
      class: 'Function',
      name: 'resetFn'
    }
  ],

  methods: [
    function put() {
      return this.putFn && this.putFn.apply(this, arguments);
    },

    function remove() {
      return this.removeFn && this.removeFn.apply(this, arguments);
    },

    function eof() {
      return this.eofFn && this.eofFn.apply(this, arguments);
    },

    function reset() {
      return this.resetFn && this.resetFn.apply(this, arguments);
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'AnonymousSink',
  implements: [ 'foam.dao.Sink' ],

  properties: [ 'sink' ],

  methods: [
    function put(sub, obj) {
      var s = this.sink;
      s && s.put && s.put(sub, obj);
    },
    function remove(sub, obj) {
      var s = this.sink;
      s && s.remove && s.remove(sub, obj);
    },

    function eof() {
      var s = this.sink;
      s && s.eof && s.eof();
    },
    function reset(sub) {
      var s = this.sink;
      s && s.reset && s.reset(sub);
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'PredicatedSink',
  extends: 'foam.dao.ProxySink',

  properties: [
    {
      class: 'FObjectProperty',
      of: 'foam.mlang.predicate.Predicate',
      name: 'predicate'
    }
  ],

  methods: [
    {
      name: 'put',
      code: function put(sub, obj) {
        if ( this.predicate.f(obj) ) this.delegate.put(sub, obj);
      }
    },
    {
      name: 'remove',
      code: function remove(sub, obj) {
        if ( this.predicate.f(obj) ) this.delegate.remove(sub, obj);
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'LimitedSink',
  extends: 'foam.dao.ProxySink',

  properties: [
    {
      class: 'Int',
      name: 'limit'
    },
    {
      name: 'count',
      class: 'Int',
      value: 0
    }
  ],

  methods: [
    {
      name: 'put',
      code: function put(sub, obj) {
        if ( this.count++ >= this.limit ) {
          sub.detach();
        } else {
          this.delegate.put(sub, obj);
        }
      }
    },
    {
      name: 'remove',
      code: function remove(sub, obj) {
        if ( this.count++ >= this.limit ) {
          sub.detach();
        } else {
          this.delegate.remove(sub, obj);
        }
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'SkipSink',
  extends: 'foam.dao.ProxySink',

  properties: [
    {
      class: 'Int',
      name: 'skip'
    },
    {
      name: 'count',
      class: 'Int',
      value: 0
    }
  ],

  methods: [
    {
      name: 'put',
      code: function put(sub, obj) {
        if ( this.count < this.skip ) {
          this.count++;
          return;
        }

        this.delegate.put(sub, obj);
      }
    },
    {
      name: 'remove',
      code: function remove(sub, obj) {
        this.reset(sub);
      }
    },
    {
      name: 'reset',
      code: function(sub) {
        this.count = 0;
        this.delegate.reset(sub);
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'OrderedSink',
  extends: 'foam.dao.ProxySink',

  properties: [
    {
      class: 'FObjectProperty',
      of: 'foam.mlang.order.Comparator',
      name: 'comparator'
    },
    {
      class: 'List',
      name: 'array',
      factory: function() { return []; }
    }
  ],

  methods: [
    {
      name: 'put',
      code: function put(sub, obj) {
        this.array.push(obj);
      }
    },
    {
      name: 'eof',
      code: function eof() {
        var comparator = this.comparator;
        this.array.sort(function(o1, o2) {
          return comparator.compare(o1, o2);
        });

        for ( var i = 0 ; i < this.array.length ; i++ ) {
          this.delegate.put(this.array[i]);
        }
      }
    },

    function remove(sub, obj) {
      // TODO
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'DedupSink',
  extends: 'foam.dao.ProxySink',

  properties: [
    {
      /** @private */
      name: 'results_',
      hidden: true,
      factory: function() { return {}; }
    }
  ],

  methods: [
    {
      /** If the object to be put() has already been seen by this sink,
        ignore it */
      name: 'put',
      code: function put(sub, obj) {
        if ( ! this.results_[obj.id] ) {
          this.results_[obj.id] = true;
          return this.delegate.put(sub, obj);
        }
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'DescribeSink',
  documentation: 'Calls .describe() on every object.  Useful for debugging to quickly see what items are in a DAO.',
  implements: [ 'foam.dao.Sink' ],
  methods: [
    function put(_, o) {
      o.describe();
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'FnSink',
  documentation: 'Converts all sink events to call to a singular function.' +
    '  Useful for subscribing a listener method to a DAO',
  properties: [
    'fn'
  ],
  methods: [
    function put(s, obj) {
      this.fn(s, 'put', obj);
    },
    function remove(s, obj) {
      this.fn(s, 'remove', obj);
    },
    function reset(s) {
      this.fn(s, 'reset');
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'FramedSink',
  extends: 'foam.dao.ProxySink',
  documentation: 'A Sink that waits until the next frame to flush the calls to the sink.',
  properties: [
    { class: 'Array', name: 'calls' },
  ],
  methods: [
    {
      name: 'put',
      code: function() {
        this.calls.push(['put', arguments]);
        this.flushCalls();
      }
    },
    {
      name: 'remove',
      code: function() {
        this.calls.push(['remove', arguments]);
        this.flushCalls();
      }
    },
    {
      name: 'eof',
      code: function() {
        this.calls.push(['eof', arguments]);
        this.flushCalls();
      }
    },
    {
      name: 'reset',
      code: function() {
        this.calls = [['reset', arguments]];
        this.flushCalls();
      }
    }
  ],
  listeners: [
    {
      name: 'flushCalls',
      isFramed: true,
      code: function() {
        for (var i = 0, o; o = this.calls[i]; i++) {
          this.delegate[o[0]].apply(undefined, o[1]);
        }
        this.calls = [];
      }
    },
  ]
});
<commit_msg>Updating documentation<commit_after>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 *
 * 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.
 */

foam.INTERFACE({
  package: 'foam.dao',
  name: 'Sink',

  methods: [
    {
      name: 'put',
      returns: '',
      args: [
        'sub',
        'obj'
      ],
      code: function() {}
    },
    {
      name: 'remove',
      returns: '',
      args: [
        'sub',
        'obj'
      ],
      code: function() {}
    },
    {
      name: 'eof',
      returns: '',
      args: [],
      code: function() {}
    },
    {
      name: 'reset',
      returns: '',
      args: [ 'sub' ],
      code: function() {}
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'ProxySink',
  implements: [ 'foam.dao.Sink' ],

  documentation: 'Proxy for Sink interface.',

  properties: [
    {
      class: 'Proxy',
      of: 'foam.dao.Sink',
      name: 'delegate'
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'AbstractSink',
  implements: [ 'foam.dao.Sink' ],

  documentation: 'Abstract base class for implementing Sink interface.',

  methods: [
    {
      name: 'put',
      code: function() {}
    },
    {
      name: 'remove',
      code: function() {}
    },
    {
      name: 'eof',
      code: function() {}
    },
    {
      name: 'reset',
      code: function() {}
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'PipeSink',
  extends: 'foam.dao.ProxySink',
  properties: [
    'dao'
  ],
  methods: [
    function reset(sub) {
      this.SUPER(sub);
      this.dao.select(this);
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'ResetListener',
  extends: 'foam.dao.ProxySink',
  documentation: 'Turns all sink events into a reset event.',
  methods: [
    function put(sub) {
      this.reset(sub);
    },
    function remove(sub) {
      this.reset(sub);
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'QuickSink',

  extends: 'foam.dao.AbstractSink',

  properties: [
    {
      class: 'Function',
      name: 'putFn'
    },
    {
      class: 'Function',
      name: 'removeFn'
    },
    {
      class: 'Function',
      name: 'eofFn'
    },
    {
      class: 'Function',
      name: 'resetFn'
    }
  ],

  methods: [
    function put() {
      return this.putFn && this.putFn.apply(this, arguments);
    },

    function remove() {
      return this.removeFn && this.removeFn.apply(this, arguments);
    },

    function eof() {
      return this.eofFn && this.eofFn.apply(this, arguments);
    },

    function reset() {
      return this.resetFn && this.resetFn.apply(this, arguments);
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'AnonymousSink',
  implements: [ 'foam.dao.Sink' ],

  properties: [ 'sink' ],

  methods: [
    function put(sub, obj) {
      var s = this.sink;
      s && s.put && s.put(sub, obj);
    },
    function remove(sub, obj) {
      var s = this.sink;
      s && s.remove && s.remove(sub, obj);
    },

    function eof() {
      var s = this.sink;
      s && s.eof && s.eof();
    },
    function reset(sub) {
      var s = this.sink;
      s && s.reset && s.reset(sub);
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'PredicatedSink',
  extends: 'foam.dao.ProxySink',

  properties: [
    {
      class: 'FObjectProperty',
      of: 'foam.mlang.predicate.Predicate',
      name: 'predicate'
    }
  ],

  methods: [
    {
      name: 'put',
      code: function put(sub, obj) {
        if ( this.predicate.f(obj) ) this.delegate.put(sub, obj);
      }
    },
    {
      name: 'remove',
      code: function remove(sub, obj) {
        if ( this.predicate.f(obj) ) this.delegate.remove(sub, obj);
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'LimitedSink',
  extends: 'foam.dao.ProxySink',

  properties: [
    {
      class: 'Int',
      name: 'limit'
    },
    {
      name: 'count',
      class: 'Int',
      value: 0
    }
  ],

  methods: [
    {
      name: 'put',
      code: function put(sub, obj) {
        if ( this.count++ >= this.limit ) {
          sub.detach();
        } else {
          this.delegate.put(sub, obj);
        }
      }
    },
    {
      name: 'remove',
      code: function remove(sub, obj) {
        if ( this.count++ >= this.limit ) {
          sub.detach();
        } else {
          this.delegate.remove(sub, obj);
        }
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'SkipSink',
  extends: 'foam.dao.ProxySink',

  properties: [
    {
      class: 'Int',
      name: 'skip'
    },
    {
      name: 'count',
      class: 'Int',
      value: 0
    }
  ],

  methods: [
    {
      name: 'put',
      code: function put(sub, obj) {
        if ( this.count < this.skip ) {
          this.count++;
          return;
        }

        this.delegate.put(sub, obj);
      }
    },
    {
      name: 'remove',
      code: function remove(sub, obj) {
        this.reset(sub);
      }
    },
    {
      name: 'reset',
      code: function(sub) {
        this.count = 0;
        this.delegate.reset(sub);
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'OrderedSink',
  extends: 'foam.dao.ProxySink',

  properties: [
    {
      class: 'FObjectProperty',
      of: 'foam.mlang.order.Comparator',
      name: 'comparator'
    },
    {
      class: 'List',
      name: 'array',
      factory: function() { return []; }
    }
  ],

  methods: [
    {
      name: 'put',
      code: function put(sub, obj) {
        this.array.push(obj);
      }
    },
    {
      name: 'eof',
      code: function eof() {
        var comparator = this.comparator;
        this.array.sort(function(o1, o2) {
          return comparator.compare(o1, o2);
        });

        for ( var i = 0 ; i < this.array.length ; i++ ) {
          this.delegate.put(this.array[i]);
        }
      }
    },

    function remove(sub, obj) {
      // TODO
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'DedupSink',
  extends: 'foam.dao.ProxySink',

  properties: [
    {
      /** @private */
      name: 'results_',
      hidden: true,
      factory: function() { return {}; }
    }
  ],

  methods: [
    {
      /** If the object to be put() has already been seen by this sink,
        ignore it */
      name: 'put',
      code: function put(sub, obj) {
        if ( ! this.results_[obj.id] ) {
          this.results_[obj.id] = true;
          return this.delegate.put(sub, obj);
        }
      }
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'DescribeSink',
  documentation: 'Calls .describe() on every object.  Useful for debugging to quickly see what items are in a DAO.',
  implements: [ 'foam.dao.Sink' ],
  methods: [
    function put(_, o) {
      o.describe();
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'FnSink',
  documentation: 'Converts all sink events to call to a singular function.' +
    '  Useful for subscribing a listener method to a DAO',
  properties: [
    'fn'
  ],
  methods: [
    function put(s, obj) {
      this.fn(s, 'put', obj);
    },
    function remove(s, obj) {
      this.fn(s, 'remove', obj);
    },
    function reset(s) {
      this.fn(s, 'reset');
    }
  ]
});

foam.CLASS({
  package: 'foam.dao',
  name: 'FramedSink',
  extends: 'foam.dao.ProxySink',
  documentation: 'A proxy that waits until the next frame to flush the calls to the delegate.',
  properties: [
    { class: 'Array', name: 'calls' },
  ],
  methods: [
    {
      name: 'put',
      code: function() {
        this.calls.push(['put', arguments]);
        this.flushCalls();
      }
    },
    {
      name: 'remove',
      code: function() {
        this.calls.push(['remove', arguments]);
        this.flushCalls();
      }
    },
    {
      name: 'eof',
      code: function() {
        this.calls.push(['eof', arguments]);
        this.flushCalls();
      }
    },
    {
      name: 'reset',
      code: function() {
        this.calls = [['reset', arguments]];
        this.flushCalls();
      }
    }
  ],
  listeners: [
    {
      name: 'flushCalls',
      isFramed: true,
      code: function() {
        for (var i = 0, o; o = this.calls[i]; i++) {
          this.delegate[o[0]].apply(undefined, o[1]);
        }
        this.calls = [];
      }
    },
  ]
});
<|endoftext|>


<commit_before>
/**
 * Calculate the Earth Rotation Angle
 * @param  {number} days UT1 days since J2000.0
 * @return {number}      ERA (radians)
 */
export function era(days) {
  return 2 * Math.PI * ( 0.7790572732640 + 1.00273781191135448 * days ) % (2 * Math.PI);
}
<commit_msg>Fix operator precedence bug.<commit_after>
/**
 * Calculate the Earth Rotation Angle
 * @param  {number} days UT1 days since J2000.0
 * @return {number}      ERA (radians)
 */
export function era(days) {
  return 2 * Math.PI * ( ( 0.7790572732640 + 1.00273781191135448 * days ) % 1 );
}
<|endoftext|>


<commit_before>/*
---
script: moo.flot.stack.js
name: flot.stack
description: Original stack plugin ported to mootools
license: [ Re-release MIT license 2011, Originally released under the MIT license by IOLA, December 2007.]

authors:
  - @fat
  - Original stacker people

requires:
  - core/1.3: '*'
  - more
  - more/utilities/color
  - moo.flot

provides: [flot.series.stack]
...
*/

/*
Flot plugin for stacking data sets, i.e. putting them on top of each
other, for accumulative graphs. Note that the plugin assumes the data
is sorted on x. Also note that stacking a mix of positive and negative
values in most instances doesn't make sense (so it looks weird).

Two or more series are stacked when their "stack" attribute is set to
the same key (which can be any number or string or just "true"). To
specify the default stack, you can set

  series: {
    stack: null or true or key (number/string)
  }

or specify it for a specific series

  flot.plot( (placeholder element), [{ data: [ ... ], stack: true ])

The stacking order is determined by the order of the data series in
the array (later series end up on top of the previous).

Internally, the plugin modifies the datapoints in each series, adding
an offset to the y value. For line series, extra data points are
inserted through interpolation. For bar charts, the second y value is
also adjusted.
*/

(function (mooFlot) {
    var options = {
        series: {
            stack: null        // true or null - stack or no stack
        }
    };

    function init(plot) {
        function findMatchingSeries(s, allseries) {
            var res = null;
            for (var i = 0; i < allseries.length; ++i) {
                if (s == allseries[i])
                    break;

                if (allseries[i].stack == s.stack)
                    res = allseries[i];
            }

            return res;
        }

        function stackData(plot, s, datapoints) {
            if (s.stack == null || s.stack === false)
                return;

            var other = findMatchingSeries(s, plot.getData());
            if (!other)
                return;

            var ps = datapoints.pointsize,
                points = datapoints.points,
                otherps = other.datapoints.pointsize,
                otherpoints = other.datapoints.points,
                newpoints = [],
                px, py, intery, qx, qy, bottom,
                withlines = s.lines.show,
                horizontal = s.bars.horizontal,
                withbottom = ps > 2 && (horizontal ? datapoints.format[2].x : datapoints.format[2].y),
                withsteps = withlines && s.lines.steps,
                fromgap = true,
                keyOffset = horizontal ? 1 : 0,
                accumulateOffset = horizontal ? 0 : 1,
                i = 0, j = 0, l, m;

            while (true) {
                if (i >= points.length)
                    break;

                l = newpoints.length;

                if (points[i] == null) {
                    // copy gaps
                    for (m = 0; m < ps; ++m)
                        newpoints.push(points[i + m]);
                    i += ps;
                }
                else if (j >= otherpoints.length) {
                    // for lines, we can't use the rest of the points
                    if (!withlines) {
                        for (m = 0; m < ps; ++m)
                            newpoints.push(points[i + m]);
                    }
                    i += ps;
                }
                else if (otherpoints[j] == null) {
                    // oops, got a gap
                    for (m = 0; m < ps; ++m)
                        newpoints.push(null);
                    fromgap = true;
                    j += otherps;
                }
                else {
                    // cases where we actually got two points
                    px = points[i + keyOffset];
                    py = points[i + accumulateOffset];
                    qx = otherpoints[j + keyOffset];
                    qy = otherpoints[j + accumulateOffset];
                    bottom = 0;

                    if (px == qx) {
                        for (m = 0; m < ps; ++m)
                            newpoints.push(points[i + m]);

                        newpoints[l + accumulateOffset] += qy;
                        bottom = qy;

                        i += ps;
                        j += otherps;
                    }
                    else if (px > qx) {
                        // we got past point below, might need to
                        // insert interpolated extra point
                        if (withlines && i > 0 && points[i - ps] != null) {
                            intery = py + (points[i - ps + accumulateOffset] - py) * (qx - px) / (points[i - ps + keyOffset] - px);
                            newpoints.push(qx);
                            newpoints.push(intery + qy);
                            for (m = 2; m < ps; ++m)
                                newpoints.push(points[i + m]);
                            bottom = qy;
                        }

                        j += otherps;
                    }
                    else { // px < qx
                        if (fromgap && withlines) {
                            // if we come from a gap, we just skip this point
                            i += ps;
                            continue;
                        }

                        for (m = 0; m < ps; ++m)
                            newpoints.push(points[i + m]);

                        // we might be able to interpolate a point below,
                        // this can give us a better y
                        if (withlines && j > 0 && otherpoints[j - otherps] != null)
                            bottom = qy + (otherpoints[j - otherps + accumulateOffset] - qy) * (px - qx) / (otherpoints[j - otherps + keyOffset] - qx);

                        newpoints[l + accumulateOffset] += bottom;

                        i += ps;
                    }

                    fromgap = false;

                    if (l != newpoints.length && withbottom)
                        newpoints[l + 2] += bottom;
                }

                // maintain the line steps invariant
                if (withsteps && l != newpoints.length && l > 0
                    && newpoints[l] != null
                    && newpoints[l] != newpoints[l - ps]
                    && newpoints[l + 1] != newpoints[l - ps + 1]) {
                    for (m = 0; m < ps; ++m)
                        newpoints[l + ps + m] = newpoints[l + m];
                    newpoints[l + 1] = newpoints[l - ps + 1];
                }
            }

            datapoints.points = newpoints;
        }

        plot.hooks.processDatapoints.push(stackData);
    }

    mooFlot.plot.plugins.push({
        init: init,
        options: options,
        name: 'stack',
        version: '1.2'
    });
})(flot);<commit_msg>added last line to file<commit_after>/*
---
script: moo.flot.stack.js
name: flot.stack
description: Original stack plugin ported to mootools
license: [ Re-release MIT license 2011, Originally released under the MIT license by IOLA, December 2007.]

authors:
  - @fat
  - Original stacker people

requires:
  - core/1.3: '*'
  - more
  - more/utilities/color
  - moo.flot

provides: [flot.series.stack]
...
*/

/*
Flot plugin for stacking data sets, i.e. putting them on top of each
other, for accumulative graphs. Note that the plugin assumes the data
is sorted on x. Also note that stacking a mix of positive and negative
values in most instances doesn't make sense (so it looks weird).

Two or more series are stacked when their "stack" attribute is set to
the same key (which can be any number or string or just "true"). To
specify the default stack, you can set

  series: {
    stack: null or true or key (number/string)
  }

or specify it for a specific series

  flot.plot( (placeholder element), [{ data: [ ... ], stack: true ])

The stacking order is determined by the order of the data series in
the array (later series end up on top of the previous).

Internally, the plugin modifies the datapoints in each series, adding
an offset to the y value. For line series, extra data points are
inserted through interpolation. For bar charts, the second y value is
also adjusted.
*/

(function (mooFlot) {
    var options = {
        series: {
            stack: null        // true or null - stack or no stack
        }
    };

    function init(plot) {
        function findMatchingSeries(s, allseries) {
            var res = null;
            for (var i = 0; i < allseries.length; ++i) {
                if (s == allseries[i])
                    break;

                if (allseries[i].stack == s.stack)
                    res = allseries[i];
            }

            return res;
        }

        function stackData(plot, s, datapoints) {
            if (s.stack == null || s.stack === false)
                return;

            var other = findMatchingSeries(s, plot.getData());
            if (!other)
                return;

            var ps = datapoints.pointsize,
                points = datapoints.points,
                otherps = other.datapoints.pointsize,
                otherpoints = other.datapoints.points,
                newpoints = [],
                px, py, intery, qx, qy, bottom,
                withlines = s.lines.show,
                horizontal = s.bars.horizontal,
                withbottom = ps > 2 && (horizontal ? datapoints.format[2].x : datapoints.format[2].y),
                withsteps = withlines && s.lines.steps,
                fromgap = true,
                keyOffset = horizontal ? 1 : 0,
                accumulateOffset = horizontal ? 0 : 1,
                i = 0, j = 0, l, m;

            while (true) {
                if (i >= points.length)
                    break;

                l = newpoints.length;

                if (points[i] == null) {
                    // copy gaps
                    for (m = 0; m < ps; ++m)
                        newpoints.push(points[i + m]);
                    i += ps;
                }
                else if (j >= otherpoints.length) {
                    // for lines, we can't use the rest of the points
                    if (!withlines) {
                        for (m = 0; m < ps; ++m)
                            newpoints.push(points[i + m]);
                    }
                    i += ps;
                }
                else if (otherpoints[j] == null) {
                    // oops, got a gap
                    for (m = 0; m < ps; ++m)
                        newpoints.push(null);
                    fromgap = true;
                    j += otherps;
                }
                else {
                    // cases where we actually got two points
                    px = points[i + keyOffset];
                    py = points[i + accumulateOffset];
                    qx = otherpoints[j + keyOffset];
                    qy = otherpoints[j + accumulateOffset];
                    bottom = 0;

                    if (px == qx) {
                        for (m = 0; m < ps; ++m)
                            newpoints.push(points[i + m]);

                        newpoints[l + accumulateOffset] += qy;
                        bottom = qy;

                        i += ps;
                        j += otherps;
                    }
                    else if (px > qx) {
                        // we got past point below, might need to
                        // insert interpolated extra point
                        if (withlines && i > 0 && points[i - ps] != null) {
                            intery = py + (points[i - ps + accumulateOffset] - py) * (qx - px) / (points[i - ps + keyOffset] - px);
                            newpoints.push(qx);
                            newpoints.push(intery + qy);
                            for (m = 2; m < ps; ++m)
                                newpoints.push(points[i + m]);
                            bottom = qy;
                        }

                        j += otherps;
                    }
                    else { // px < qx
                        if (fromgap && withlines) {
                            // if we come from a gap, we just skip this point
                            i += ps;
                            continue;
                        }

                        for (m = 0; m < ps; ++m)
                            newpoints.push(points[i + m]);

                        // we might be able to interpolate a point below,
                        // this can give us a better y
                        if (withlines && j > 0 && otherpoints[j - otherps] != null)
                            bottom = qy + (otherpoints[j - otherps + accumulateOffset] - qy) * (px - qx) / (otherpoints[j - otherps + keyOffset] - qx);

                        newpoints[l + accumulateOffset] += bottom;

                        i += ps;
                    }

                    fromgap = false;

                    if (l != newpoints.length && withbottom)
                        newpoints[l + 2] += bottom;
                }

                // maintain the line steps invariant
                if (withsteps && l != newpoints.length && l > 0
                    && newpoints[l] != null
                    && newpoints[l] != newpoints[l - ps]
                    && newpoints[l + 1] != newpoints[l - ps + 1]) {
                    for (m = 0; m < ps; ++m)
                        newpoints[l + ps + m] = newpoints[l + m];
                    newpoints[l + 1] = newpoints[l - ps + 1];
                }
            }

            datapoints.points = newpoints;
        }

        plot.hooks.processDatapoints.push(stackData);
    }

    mooFlot.plot.plugins.push({
        init: init,
        options: options,
        name: 'stack',
        version: '1.2'
    });
})(flot);
<|endoftext|>


<commit_before>/*jslint -W079 */
/*jslint node: true */
'use strict';
var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;
var domain = require('domain');

var WebSocket = require('ws');
var Guid = require('guid');
var _ = {
  defaults: require('lodash.defaults')
};
var highland = require('highland');

var MessageStream = require('./messagestream');

function defaultExecuteHandler(messageStream, callback) {
  var errored = false;

  highland(messageStream)
    .stopOnError(function(err) {
      // TODO: this does not seem to halt the stream properly, and make
      // the callback being fired twice. We need to get rid of the ugly
      // errored variable check.
      errored = true;
      callback(err);
    })
    .map(function(message) {
      return message.result.data;
    })
    .sequence()
    .toArray(function(results) {
      if (!errored) {
        callback(null, results);
      }
    });
}

function GremlinClient(port, host, options) {
  this.port = port || 8182;
  this.host = host || 'localhost';

  this.options = _.defaults(options || {}, {
    language: 'gremlin-groovy',
    session: false,
    op: 'eval',
    processor: '',
    accept: 'application/json',
    executeHandler: defaultExecuteHandler //
  });

  this.useSession = this.options.session;

  if (this.useSession) {
    this.sessionId = Guid.create().value;
  }

  this.connected = false;
  this.queue = [];

  this.commands = {};

  // Open websocket connection
  this.ws = new WebSocket('ws://'+ this.host +':'+ this.port);

  this.ws.onopen = this.onConnectionOpen.bind(this);

  this.ws.onerror = function(e) {
    console.log('Error:', e);
  };

  this.ws.onmessage = this.handleMessage.bind(this);

  this.ws.onclose = this.handleDisconnection.bind(this);
}

inherits(GremlinClient, EventEmitter);

/**
 * Process all incoming raw message events sent by Gremlin Server, and dispatch
 * to the appropriate command.
 *
 * @param {MessageEvent} event
 */
GremlinClient.prototype.handleMessage = function(event) {
  var rawMessage = JSON.parse(event.data || event); // Node.js || Browser API
  var command = this.commands[rawMessage.requestId];
  var messageStream = command.messageStream;
  var statusCode = rawMessage.status.code;

  switch (statusCode) {
    case 200:
      messageStream.push(rawMessage);
      break;
    case 299:
      delete this.commands[rawMessage.requestId]; // TODO: optimize performance
      messageStream.push(null);
      break;
    default:
      messageStream.emit('error', new Error(rawMessage.status.message + ' (Error '+ statusCode +')'));
      break;
  }
};

/**
 * Handle the WebSocket onOpen event, flag the client as connected and
 * process command queue.
 */
GremlinClient.prototype.onConnectionOpen = function() {
  this.connected = true;
  this.emit('connect');

  this.executeQueue();
};

/**
 * @param {CloseEvent} event
 */
GremlinClient.prototype.handleDisconnection = function(event) {
  this.cancelPendingCommands({
    message: 'WebSocket closed',
    details: event
  });
};

/**
 * Process the current command queue, sending commands to Gremlin Server
 * (First In, First Out).
 */
GremlinClient.prototype.executeQueue = function() {
  var command;

  while (this.queue.length > 0) {
    command = this.queue.shift();
    this.sendMessage(command.message);
  }
};

/**
 * @param {Object} reason
 */
GremlinClient.prototype.cancelPendingCommands = function(reason) {
  var commands = this.commands;
  var command;
  var error = new Error(reason.message);
  error.details = reason.details;

  // Empty queue
  this.queue.length = 0;
  this.commands = {};

  Object.keys(commands).forEach(function(key) {
    command = commands[key];
    command.messageStream.emit('error', error);
  });
};

/**
 * For a given script string and optional bound parameters, build a command
 * object to be sent to Gremlin Server.
 *
 * @param {String|Function} script
 * @param {Object} bindings
 * @param {Object} message
 */
GremlinClient.prototype.buildCommand = function(script, bindings, message) {
  if (typeof script === 'function') {
    script = this.extractFunctionBody(script);
  }
  bindings = bindings || {};

  var messageStream = new MessageStream({ objectMode: true });
  var guid = Guid.create().value;
  var args = _.defaults(message && message.args || {}, {
    gremlin: script,
    bindings: bindings,
    accept: this.options.accept,
    language: this.options.language,
  });

  message = _.defaults(message || {}, {
    requestId: guid,
    processor: this.options.processor,
    op: this.options.op,
    args: args
  });

  var command = {
    message: message,
    messageStream: messageStream
  };

  if (this.useSession) {
    // Assume that people want to use the 'session' processor unless specified
    command.message.processor = this.options.processor || 'session';
    command.message.args.session = this.sessionId;
  }

  return command;
};

GremlinClient.prototype.sendMessage = function(message) {
  this.ws.send(JSON.stringify(message));
};

/**
 * Get the inner function body from a function.toString() representation
 *
 * @param {Function}
 * @return {String}
 */
GremlinClient.prototype.extractFunctionBody = function(fn) {
  var body = fn.toString();
  body = body.substring(body.indexOf('{') + 1, body.lastIndexOf('}'));

  return body;
};

/**
 * Asynchronously send a script to Gremlin Server for execution and fire
 * the provided callback when all results have been fetched.
 *
 * This method internally uses a stream to handle the potential concatenation
 * of results.
 *
 * Callback signature: (Error, Array<result>)
 *
 * @public
 * @param {String|Function} script
 * @param {Object} bindings
 * @param {Object} message
 * @param {Function} callback
 */
GremlinClient.prototype.execute = function(script, bindings, message, callback) {
  callback = arguments[arguments.length - 1]; //todo: improve?

  if (typeof message === 'function') {
    callback = message;
    message = {};
  }

  var messageStream = this.messageStream(script, bindings, message);

  // TO CHECK: errors handling could be improved
  // See https://groups.google.com/d/msg/nodejs/lJYT9hZxFu0/L59CFbqWGyYJ
  // for an example using domains
  var executeHandler = this.options.executeHandler;

  executeHandler(messageStream, callback);
};

/**
 * Execute the script and return a stream of distinct/single results.
 * This method reemits a distinct data event for each returned result, which
 * makes the stream behave as if `resultIterationBatchSize` was set to 1.
 *
 * If you do not wish this behavior, please use client.messageStream() instead.
 *
 * Even though this method uses Highland.js internally, it does not return
 * a high level Highland readable stream so we do not risk having to deal
 * with unexpected API breaking changes as Highland.js evolves.
 *
 * @return {ReadableStream} A Node.js Stream2
 */
GremlinClient.prototype.stream = function(script, bindings, message) {
  var messageStream = this.messageStream(script, bindings, message);
  var _ = highland; // override lo-dash locally

  // Create a local highland 'through' pipeline so we don't expose
  // a Highland stream to the end user, but a standard Node.js Stream2
  var through = _.pipeline(
    _.map(function(message) {
      return message.result.data;
    }),
    _.sequence()
  );

  var stream = messageStream.pipe(through);

  messageStream.on('error', function(e) {
    stream.emit('error', new Error(e));
  });

  return stream;
};

/**
 * Execute the script and return a stream of raw messages returned by Gremlin
 * Server.
 * This method does not reemit one distinct data event per result. It directly
 * emits the raw messages returned by Gremlin Server as they are received.
 *
 * Although public, this is a low level method intended to be used for
 * advanced usages.
 *
 * @public
 * @param {String|Function} script
 * @param {Object} bindings
 * @param {Object} message
 * @return {MessageStream}
 */
GremlinClient.prototype.messageStream = function(script, bindings, message) {
  var command = this.buildCommand(script, bindings, message);

  this.sendCommand(command); //todo improve for streams

  return command.messageStream;
};

/**
 * Send a command to Gremlin Server, or add it to queue if the connection
 * is not established.
 *
 * @param {Object} command
 */
GremlinClient.prototype.sendCommand = function(command) {
  this.commands[command.message.requestId] = command;

  if (this.connected) {
    this.sendMessage(command.message);
  } else {
    this.queue.push(command);
  }
};

module.exports = GremlinClient;
<commit_msg>Remove unused import<commit_after>/*jslint -W079 */
/*jslint node: true */
'use strict';
var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;

var WebSocket = require('ws');
var Guid = require('guid');
var _ = {
  defaults: require('lodash.defaults')
};
var highland = require('highland');

var MessageStream = require('./messagestream');

function defaultExecuteHandler(messageStream, callback) {
  var errored = false;

  highland(messageStream)
    .stopOnError(function(err) {
      // TODO: this does not seem to halt the stream properly, and make
      // the callback being fired twice. We need to get rid of the ugly
      // errored variable check.
      errored = true;
      callback(err);
    })
    .map(function(message) {
      return message.result.data;
    })
    .sequence()
    .toArray(function(results) {
      if (!errored) {
        callback(null, results);
      }
    });
}

function GremlinClient(port, host, options) {
  this.port = port || 8182;
  this.host = host || 'localhost';

  this.options = _.defaults(options || {}, {
    language: 'gremlin-groovy',
    session: false,
    op: 'eval',
    processor: '',
    accept: 'application/json',
    executeHandler: defaultExecuteHandler //
  });

  this.useSession = this.options.session;

  if (this.useSession) {
    this.sessionId = Guid.create().value;
  }

  this.connected = false;
  this.queue = [];

  this.commands = {};

  // Open websocket connection
  this.ws = new WebSocket('ws://'+ this.host +':'+ this.port);

  this.ws.onopen = this.onConnectionOpen.bind(this);

  this.ws.onerror = function(e) {
    console.log('Error:', e);
  };

  this.ws.onmessage = this.handleMessage.bind(this);

  this.ws.onclose = this.handleDisconnection.bind(this);
}

inherits(GremlinClient, EventEmitter);

/**
 * Process all incoming raw message events sent by Gremlin Server, and dispatch
 * to the appropriate command.
 *
 * @param {MessageEvent} event
 */
GremlinClient.prototype.handleMessage = function(event) {
  var rawMessage = JSON.parse(event.data || event); // Node.js || Browser API
  var command = this.commands[rawMessage.requestId];
  var messageStream = command.messageStream;
  var statusCode = rawMessage.status.code;

  switch (statusCode) {
    case 200:
      messageStream.push(rawMessage);
      break;
    case 299:
      delete this.commands[rawMessage.requestId]; // TODO: optimize performance
      messageStream.push(null);
      break;
    default:
      messageStream.emit('error', new Error(rawMessage.status.message + ' (Error '+ statusCode +')'));
      break;
  }
};

/**
 * Handle the WebSocket onOpen event, flag the client as connected and
 * process command queue.
 */
GremlinClient.prototype.onConnectionOpen = function() {
  this.connected = true;
  this.emit('connect');

  this.executeQueue();
};

/**
 * @param {CloseEvent} event
 */
GremlinClient.prototype.handleDisconnection = function(event) {
  this.cancelPendingCommands({
    message: 'WebSocket closed',
    details: event
  });
};

/**
 * Process the current command queue, sending commands to Gremlin Server
 * (First In, First Out).
 */
GremlinClient.prototype.executeQueue = function() {
  var command;

  while (this.queue.length > 0) {
    command = this.queue.shift();
    this.sendMessage(command.message);
  }
};

/**
 * @param {Object} reason
 */
GremlinClient.prototype.cancelPendingCommands = function(reason) {
  var commands = this.commands;
  var command;
  var error = new Error(reason.message);
  error.details = reason.details;

  // Empty queue
  this.queue.length = 0;
  this.commands = {};

  Object.keys(commands).forEach(function(key) {
    command = commands[key];
    command.messageStream.emit('error', error);
  });
};

/**
 * For a given script string and optional bound parameters, build a command
 * object to be sent to Gremlin Server.
 *
 * @param {String|Function} script
 * @param {Object} bindings
 * @param {Object} message
 */
GremlinClient.prototype.buildCommand = function(script, bindings, message) {
  if (typeof script === 'function') {
    script = this.extractFunctionBody(script);
  }
  bindings = bindings || {};

  var messageStream = new MessageStream({ objectMode: true });
  var guid = Guid.create().value;
  var args = _.defaults(message && message.args || {}, {
    gremlin: script,
    bindings: bindings,
    accept: this.options.accept,
    language: this.options.language,
  });

  message = _.defaults(message || {}, {
    requestId: guid,
    processor: this.options.processor,
    op: this.options.op,
    args: args
  });

  var command = {
    message: message,
    messageStream: messageStream
  };

  if (this.useSession) {
    // Assume that people want to use the 'session' processor unless specified
    command.message.processor = this.options.processor || 'session';
    command.message.args.session = this.sessionId;
  }

  return command;
};

GremlinClient.prototype.sendMessage = function(message) {
  this.ws.send(JSON.stringify(message));
};

/**
 * Get the inner function body from a function.toString() representation
 *
 * @param {Function}
 * @return {String}
 */
GremlinClient.prototype.extractFunctionBody = function(fn) {
  var body = fn.toString();
  body = body.substring(body.indexOf('{') + 1, body.lastIndexOf('}'));

  return body;
};

/**
 * Asynchronously send a script to Gremlin Server for execution and fire
 * the provided callback when all results have been fetched.
 *
 * This method internally uses a stream to handle the potential concatenation
 * of results.
 *
 * Callback signature: (Error, Array<result>)
 *
 * @public
 * @param {String|Function} script
 * @param {Object} bindings
 * @param {Object} message
 * @param {Function} callback
 */
GremlinClient.prototype.execute = function(script, bindings, message, callback) {
  callback = arguments[arguments.length - 1]; //todo: improve?

  if (typeof message === 'function') {
    callback = message;
    message = {};
  }

  var messageStream = this.messageStream(script, bindings, message);

  // TO CHECK: errors handling could be improved
  // See https://groups.google.com/d/msg/nodejs/lJYT9hZxFu0/L59CFbqWGyYJ
  // for an example using domains
  var executeHandler = this.options.executeHandler;

  executeHandler(messageStream, callback);
};

/**
 * Execute the script and return a stream of distinct/single results.
 * This method reemits a distinct data event for each returned result, which
 * makes the stream behave as if `resultIterationBatchSize` was set to 1.
 *
 * If you do not wish this behavior, please use client.messageStream() instead.
 *
 * Even though this method uses Highland.js internally, it does not return
 * a high level Highland readable stream so we do not risk having to deal
 * with unexpected API breaking changes as Highland.js evolves.
 *
 * @return {ReadableStream} A Node.js Stream2
 */
GremlinClient.prototype.stream = function(script, bindings, message) {
  var messageStream = this.messageStream(script, bindings, message);
  var _ = highland; // override lo-dash locally

  // Create a local highland 'through' pipeline so we don't expose
  // a Highland stream to the end user, but a standard Node.js Stream2
  var through = _.pipeline(
    _.map(function(message) {
      return message.result.data;
    }),
    _.sequence()
  );

  var stream = messageStream.pipe(through);

  messageStream.on('error', function(e) {
    stream.emit('error', new Error(e));
  });

  return stream;
};

/**
 * Execute the script and return a stream of raw messages returned by Gremlin
 * Server.
 * This method does not reemit one distinct data event per result. It directly
 * emits the raw messages returned by Gremlin Server as they are received.
 *
 * Although public, this is a low level method intended to be used for
 * advanced usages.
 *
 * @public
 * @param {String|Function} script
 * @param {Object} bindings
 * @param {Object} message
 * @return {MessageStream}
 */
GremlinClient.prototype.messageStream = function(script, bindings, message) {
  var command = this.buildCommand(script, bindings, message);

  this.sendCommand(command); //todo improve for streams

  return command.messageStream;
};

/**
 * Send a command to Gremlin Server, or add it to queue if the connection
 * is not established.
 *
 * @param {Object} command
 */
GremlinClient.prototype.sendCommand = function(command) {
  this.commands[command.message.requestId] = command;

  if (this.connected) {
    this.sendMessage(command.message);
  } else {
    this.queue.push(command);
  }
};

module.exports = GremlinClient;
<|endoftext|>


<commit_before>const debug = require('debug')('app:email');

const mandrill = require('mandrill-api/mandrill');
const { getVars, getTo } = require('./mandrill-utils');
const config = require('smart-config');
const emailConfig = config.get('email');
const mandrillClient = new mandrill.Mandrill(emailConfig.key);

const send = ({ email, to, cc, bcc, subject, message, template, vars }) => new Promise((resolve, reject) => {
  const mandrillMessage = {
    subject,
    to: getTo({ email, to, cc, bcc }),
    from_email: emailConfig.from,
    merge_vars: [{
      rcpt: email,
      vars: getVars(vars)
    }]
  };

  if (template) {
    return mandrillClient.messages.sendTemplate({
      template_name: template,
      template_content: [{}],
      message: mandrillMessage,
      async: false
    }, res => {
      debug('sent', res);
      resolve(res);
    }, err => {
      debug('error', err);
      reject(err);
    });
  }

  return mandrillClient.messages.send({
    message: { ...mandrillMessage, text: message },
    async: false
  }, res => {
    debug('sent', res);
    resolve(res);
  }, err => {
    debug('error', err);
    reject(err);
  });
});

module.exports = { send };
<commit_msg>Parse HTML in email message<commit_after>const debug = require('debug')('app:email');

const mandrill = require('mandrill-api/mandrill');
const { getVars, getTo } = require('./mandrill-utils');
const config = require('smart-config');
const emailConfig = config.get('email');
const mandrillClient = new mandrill.Mandrill(emailConfig.key);

const send = ({ email, to, cc, bcc, subject, message, template, vars }) => new Promise((resolve, reject) => {
  const mandrillMessage = {
    subject,
    to: getTo({ email, to, cc, bcc }),
    from_email: emailConfig.from,
    merge_vars: [{
      rcpt: email,
      vars: getVars(vars)
    }]
  };

  if (template) {
    return mandrillClient.messages.sendTemplate({
      template_name: template,
      template_content: [{}],
      message: mandrillMessage,
      async: false
    }, res => {
      debug('sent', res);
      resolve(res);
    }, err => {
      debug('error', err);
      reject(err);
    });
  }

  return mandrillClient.messages.send({
    message: { ...mandrillMessage, html: message },
    async: false
  }, res => {
    debug('sent', res);
    resolve(res);
  }, err => {
    debug('error', err);
    reject(err);
  });
});

module.exports = { send };
<|endoftext|>


<commit_before>import {isObject, isString, startsWith} from './util';
import {
  encodeUriQuery,
  encodeUriSegment,
  replaceUrlParamFromUrl,
  replaceQueryStringParamFromUrl,
  splitUrlByProtocolAndDomain
} from './url';
import {defaultGlobals, defaultHeaders} from './../defaults';

export class HttpError extends Error {
  constructor(statusCode = 500, {body, message = 'HttpError'}) {
    super(message);
    this.name = this.constructor.name;
    this.message = message;
    if (typeof Error.captureStackTrace === 'function') {
      Error.captureStackTrace(this, this.constructor);
    } else {
      this.stack = (new Error(message)).stack;
    }
    // Http
    this.statusCode = statusCode;
    this.status = statusCode;
    this.body = body;
  }
}

export const buildFetchUrl = (context, {url, urlParams, stripTrailingSlashes = true}) => {
  const [protocolAndDomain, remainderUrl] = splitUrlByProtocolAndDomain(url);
  // Replace urlParams with values from context
  let builtUrl = Object.keys(urlParams).reduce((wipUrl, urlParam) => {
    const urlParamInfo = urlParams[urlParam];
    const contextAsObject = !isObject(context) ? {id: context} : context;
    const value = contextAsObject[urlParam] || ''; // self.defaults[urlParam];
    if (value) {
      const encodedValue = urlParamInfo.isQueryParamValue ? encodeUriQuery(value, true) : encodeUriSegment(value);
      return replaceUrlParamFromUrl(wipUrl, urlParam, encodedValue);
    }
    return replaceUrlParamFromUrl(wipUrl, urlParam);
  }, remainderUrl);
  // Strip trailing slashes and set the url (unless this behavior is specifically disabled)
  if (stripTrailingSlashes) {
    builtUrl = builtUrl.replace(/\/+$/, '') || '/';
  }
  return protocolAndDomain + builtUrl;
};

export const buildFetchOpts = (context, {method, headers, credentials, query, body}) => {
  const opts = {
    headers: defaultHeaders
  };
  if (method) {
    opts.method = method;
  }
  if (headers) {
    opts.headers = {...opts.headers, ...headers};
  }
  if (credentials) {
    opts.credentials = credentials;
  }
  if (query) {
    opts.query = query;
  }
  const hasBody = /^(POST|PUT|PATCH)$/i.test(opts.method);
  if (hasBody) {
    if (body) {
      opts.body = body;
    } else if (context) {
      opts.body = JSON.stringify(context);
    }
  }
  return opts;
};

const fetch = (url, options = {}) => {
  // Support options.query
  const builtUrl = Object.keys(options.query || []).reduce((wipUrl, queryParam) => {
    const queryParamValue = isString(options.query[queryParam]) ? options.query[queryParam] : JSON.stringify(options.query[queryParam]);
    return replaceQueryStringParamFromUrl(wipUrl, queryParam, queryParamValue);
  }, url);
  return (options.Promise || defaultGlobals.Promise).resolve((defaultGlobals.fetch || fetch)(builtUrl, options))
    .then((res) => {
      if (!res.ok) {
        const contentType = res.headers.get('Content-Type');
        const isJson = startsWith(contentType, 'application/json');
        return res[isJson ? 'json' : 'text']().then((body) => {
          throw new HttpError(res.status, {body});
        });
      }
      return res;
    });
};

export default fetch;
<commit_msg>feat(fetch): add auto-stringification of body<commit_after>import {isObject, isString, startsWith} from './util';
import {
  encodeUriQuery,
  encodeUriSegment,
  replaceUrlParamFromUrl,
  replaceQueryStringParamFromUrl,
  splitUrlByProtocolAndDomain
} from './url';
import {defaultGlobals, defaultHeaders} from './../defaults';

export class HttpError extends Error {
  constructor(statusCode = 500, {body, message = 'HttpError'}) {
    super(message);
    this.name = this.constructor.name;
    this.message = message;
    if (typeof Error.captureStackTrace === 'function') {
      Error.captureStackTrace(this, this.constructor);
    } else {
      this.stack = (new Error(message)).stack;
    }
    // Http
    this.statusCode = statusCode;
    this.status = statusCode;
    this.body = body;
  }
}

export const buildFetchUrl = (context, {url, urlParams, stripTrailingSlashes = true}) => {
  const [protocolAndDomain, remainderUrl] = splitUrlByProtocolAndDomain(url);
  // Replace urlParams with values from context
  let builtUrl = Object.keys(urlParams).reduce((wipUrl, urlParam) => {
    const urlParamInfo = urlParams[urlParam];
    const contextAsObject = !isObject(context) ? {id: context} : context;
    const value = contextAsObject[urlParam] || ''; // self.defaults[urlParam];
    if (value) {
      const encodedValue = urlParamInfo.isQueryParamValue ? encodeUriQuery(value, true) : encodeUriSegment(value);
      return replaceUrlParamFromUrl(wipUrl, urlParam, encodedValue);
    }
    return replaceUrlParamFromUrl(wipUrl, urlParam);
  }, remainderUrl);
  // Strip trailing slashes and set the url (unless this behavior is specifically disabled)
  if (stripTrailingSlashes) {
    builtUrl = builtUrl.replace(/\/+$/, '') || '/';
  }
  return protocolAndDomain + builtUrl;
};

export const buildFetchOpts = (context, {method, headers, credentials, query, body}) => {
  const opts = {
    headers: defaultHeaders
  };
  if (method) {
    opts.method = method;
  }
  if (headers) {
    opts.headers = {...opts.headers, ...headers};
  }
  if (credentials) {
    opts.credentials = credentials;
  }
  if (query) {
    opts.query = query;
  }
  const hasBody = /^(POST|PUT|PATCH)$/i.test(opts.method);
  if (hasBody) {
    if (body) {
      opts.body = isString(body) ? body : JSON.stringify(body);
    } else if (context) {
      opts.body = isString(context) ? context : JSON.stringify(context);
    }
  }
  return opts;
};

const fetch = (url, options = {}) => {
  // Support options.query
  const builtUrl = Object.keys(options.query || []).reduce((wipUrl, queryParam) => {
    const queryParamValue = isString(options.query[queryParam]) ? options.query[queryParam] : JSON.stringify(options.query[queryParam]);
    return replaceQueryStringParamFromUrl(wipUrl, queryParam, queryParamValue);
  }, url);
  return (options.Promise || defaultGlobals.Promise).resolve((defaultGlobals.fetch || fetch)(builtUrl, options))
    .then((res) => {
      if (!res.ok) {
        const contentType = res.headers.get('Content-Type');
        const isJson = startsWith(contentType, 'application/json');
        return res[isJson ? 'json' : 'text']().then((body) => {
          throw new HttpError(res.status, {body});
        });
      }
      return res;
    });
};

export default fetch;
<|endoftext|>