<commit_before>

//////////////////////////////////////////////////////////////////////////////
/**
 * @module geo
 */
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * Create a new instance of class sliderWidget
 *
 * @class
 * @returns {geo.sliderWidget}
 */
//////////////////////////////////////////////////////////////////////////////
geo.sliderWidget = function (arg) {
  'use strict';
  if (!(this instanceof geo.sliderWidget)) {
    return new geo.sliderWidget(arg);
  }
  geo.widget.call(this, arg);

  var m_this = this,
      m_xscale,
      m_yscale,
      m_plus,
      m_minus,
      m_track,
      m_nub,
      m_width = 20, // Approximate size of the widget in pixels
      m_height = 100,
      m_nubSize = 6,
      m_plusIcon,
      m_minusIcon;

  /* http://icomoon.io */
  /* CC BY 3.0 http://creativecommons.org/licenses/by/3.0/ */
  /* jshint -W101 */
  m_plusIcon = 'M512 81.92c-237.568 0-430.080 192.614-430.080 430.080 0 237.568 192.563 430.080 430.080 430.080s430.080-192.563 430.080-430.080c0-237.517-192.563-430.080-430.080-430.080zM564.326 564.326v206.182h-104.653v-206.182h-206.234v-104.653h206.182v-206.234h104.704v206.182h206.182v104.704h-206.182z';
  m_minusIcon = 'M512 81.92c-237.568 0-430.080 192.614-430.080 430.080 0 237.568 192.563 430.080 430.080 430.080s430.080-192.563 430.080-430.080c0-237.517-192.563-430.080-430.080-430.080zM770.56 459.674v104.704h-517.12v-104.704h517.12z';
  /* jshint +W101 */

  function put_icon(icon, base, cx, cy, size) {
    var g = base.append('g');

    // the scale factor
    var s = size / 1024;

    g.append('g')
      .append('g')
        .attr(
          'transform',
          'translate(' + cx + ',' + cy + ') scale(' + s + ') translate(-512,-512)'
      )
      .append('path')
        .attr('d', icon)
        .attr('class', 'geo-glyphicon');

    return g;
  }

  this._init = function () {
    var svg = m_this.layer().renderer().canvas(),
        x0 = 40,
        y0 = 40 + m_width,
        map = m_this.layer().map(),
        main = svg;

    // create d3 scales for positioning
    // TODO: make customizable and responsive
    m_xscale = d3.scale.linear().domain([-4, 4]).range([x0, x0 + m_width]);
    m_yscale = d3.scale.linear().domain([0, 1]).range([y0, y0 + m_height]);

    // Add a background
    var back = svg
      .append('rect')
        .attr('rx', 20)
        .attr('ry', 20)
        .style('fill', 'gray')
        .style('fill-opacity', 1)
        .attr('filter', 'url(#geo-blur)');

    svg = svg.append('g');

    m_plus = svg.append('g');
    m_plus.append('circle')
      .attr('cx', m_xscale(0))
      .attr('cy', m_yscale(0.0) - m_width + 2)
      .attr('r', m_width / 2)
      .style({
        'fill': 'white',
        'cursor': 'pointer'
      })
      .on('click', function () {
        var z = map.zoom();
        map.zoom(z + 1);
      })
      .on('mousedown', function () {
        d3.event.stopPropagation();
      });

    put_icon(
      m_plusIcon,
      m_plus,
      m_xscale(0),
      m_yscale(0) - m_width + 2,
      m_width + 5
    ).style('cursor', 'pointer')
      .style('pointer-events', 'none');

    m_minus = svg.append('g');
    m_minus.append('circle')
      .attr('cx', m_xscale(0))
      .attr('cy', m_yscale(1.0) + m_width - 2)
      .attr('r', m_width / 2)
      .style({
        'fill': 'white',
        'cursor': 'pointer'
      })
      .on('click', function () {
        var z = map.zoom();
        map.zoom(z - 1);
      })
      .on('mousedown', function () {
        d3.event.stopPropagation();
      });

    put_icon(
      m_minusIcon,
      m_minus,
      m_xscale(0),
      m_yscale(1) + m_width - 2,
      m_width + 5
    ).style('cursor', 'pointer')
      .style('pointer-events', 'none');

    m_track = svg.append('rect')
      .attr('x', m_xscale(0) - m_width / 10)
      .attr('y', m_yscale(0))
      .attr('rx', m_width / 10)
      .attr('ry', m_width / 10)
      .attr('width', m_width / 5)
      .attr('height', m_height)
      .style({
        'fill': 'white',
        'stroke': 'black',
        'cursor': 'pointer'
      });

    m_nub = svg.append('rect')
      .attr('x', m_xscale(-4))
      .attr('y', m_yscale(0.5) - m_nubSize / 2)
      .attr('rx', 3)
      .attr('ry', 3)
      .attr('width', m_width)
      .attr('height', m_nubSize)
      .style({
        'fill': 'black',
        'cursor': 'pointer'
      })
      .on('mousedown', function () {
        function respond() {
          var z = m_yscale.invert(d3.mouse(m_this.layer().node()[0])[1]),
              zrange = map.zoomRange(), evt = d3.event;
          z = (1 - z) * (zrange.max - zrange.min) + zrange.min;
          map.zoom(z);
          m_this._update();
          evt.stopPropagation();
        }
        d3.select(document).on('mousemove.geo.slider', function () {
          respond();
        });
        d3.select(document).on('mouseup.geo.slider', function () {
          respond(true);
          d3.select(document).on('.geo.slider', null);
        });
        d3.event.stopPropagation();
      });

    var bbox = svg.node().getBBox();
    back.attr('width', bbox.width + 20)
      .attr('height', bbox.height + 20)
      .attr('x', bbox.x - 10)
      .attr('y', bbox.y - 10)
      .style('opacity', 1e-6);
    main
      .on('mouseenter', function () {
        back.style('opacity', 1);
      })
      .on('mouseleave', function () {
        back.style('opacity', 1e-6);
      });

    svg.selectAll('*')
      .on('mouseover', function () {
        d3.select(this).attr('filter', 'url(#geo-highlight)');
      })
      .on('mouseout', function () {
        d3.select(this).attr('filter', null);
      });

    m_this.layer().geoOn(geo.event.zoom, function () {
      m_this._update();
    });

    m_this._update();
  };

  this._exit = function () {
    m_this.layer().renderer().canvas().remove();
    m_this.layer().geoOff(geo.event.zoom);
  };

  this._update = function (obj) {
    var map = m_this.layer().map(),
        zoomRange = map.zoomRange(),
        zoom = map.zoom(),
        zoomScale = d3.scale.linear();

    obj = obj || {};
    zoom = obj.value || zoom;
    zoomScale.domain([zoomRange.min, zoomRange.max])
      .range([1, 0])
      .clamp(true);

    m_nub.attr('y', m_yscale(zoomScale(zoom)) - m_nubSize / 2);
  };
};

inherit(geo.sliderWidget, geo.widget);

geo.registerWidget('d3', 'slider', geo.sliderWidget);
<commit_msg>Implemented clicking on the track of the zoom slider<commit_after>

//////////////////////////////////////////////////////////////////////////////
/**
 * @module geo
 */
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
/**
 * Create a new instance of class sliderWidget
 *
 * @class
 * @returns {geo.sliderWidget}
 */
//////////////////////////////////////////////////////////////////////////////
geo.sliderWidget = function (arg) {
  'use strict';
  if (!(this instanceof geo.sliderWidget)) {
    return new geo.sliderWidget(arg);
  }
  geo.widget.call(this, arg);

  var m_this = this,
      m_xscale,
      m_yscale,
      m_plus,
      m_minus,
      m_track,
      m_nub,
      m_width = 20, // Approximate size of the widget in pixels
      m_height = 100,
      m_nubSize = 6,
      m_plusIcon,
      m_minusIcon;

  /* http://icomoon.io */
  /* CC BY 3.0 http://creativecommons.org/licenses/by/3.0/ */
  /* jshint -W101 */
  m_plusIcon = 'M512 81.92c-237.568 0-430.080 192.614-430.080 430.080 0 237.568 192.563 430.080 430.080 430.080s430.080-192.563 430.080-430.080c0-237.517-192.563-430.080-430.080-430.080zM564.326 564.326v206.182h-104.653v-206.182h-206.234v-104.653h206.182v-206.234h104.704v206.182h206.182v104.704h-206.182z';
  m_minusIcon = 'M512 81.92c-237.568 0-430.080 192.614-430.080 430.080 0 237.568 192.563 430.080 430.080 430.080s430.080-192.563 430.080-430.080c0-237.517-192.563-430.080-430.080-430.080zM770.56 459.674v104.704h-517.12v-104.704h517.12z';
  /* jshint +W101 */

  function put_icon(icon, base, cx, cy, size) {
    var g = base.append('g');

    // the scale factor
    var s = size / 1024;

    g.append('g')
      .append('g')
        .attr(
          'transform',
          'translate(' + cx + ',' + cy + ') scale(' + s + ') translate(-512,-512)'
      )
      .append('path')
        .attr('d', icon)
        .attr('class', 'geo-glyphicon');

    return g;
  }

  this._init = function () {
    var svg = m_this.layer().renderer().canvas(),
        x0 = 40,
        y0 = 40 + m_width,
        map = m_this.layer().map(),
        main = svg;

    // create d3 scales for positioning
    // TODO: make customizable and responsive
    m_xscale = d3.scale.linear().domain([-4, 4]).range([x0, x0 + m_width]);
    m_yscale = d3.scale.linear().domain([0, 1]).range([y0, y0 + m_height]);

    // Add a background
    var back = svg
      .append('rect')
        .attr('rx', 20)
        .attr('ry', 20)
        .style('fill', 'gray')
        .style('fill-opacity', 1)
        .attr('filter', 'url(#geo-blur)');

    svg = svg.append('g');

    m_plus = svg.append('g');
    m_plus.append('circle')
      .attr('cx', m_xscale(0))
      .attr('cy', m_yscale(0.0) - m_width + 2)
      .attr('r', m_width / 2)
      .style({
        'fill': 'white',
        'cursor': 'pointer'
      })
      .on('click', function () {
        var z = map.zoom();
        map.zoom(z + 1);
      })
      .on('mousedown', function () {
        d3.event.stopPropagation();
      });

    put_icon(
      m_plusIcon,
      m_plus,
      m_xscale(0),
      m_yscale(0) - m_width + 2,
      m_width + 5
    ).style('cursor', 'pointer')
      .style('pointer-events', 'none');

    m_minus = svg.append('g');
    m_minus.append('circle')
      .attr('cx', m_xscale(0))
      .attr('cy', m_yscale(1.0) + m_width - 2)
      .attr('r', m_width / 2)
      .style({
        'fill': 'white',
        'cursor': 'pointer'
      })
      .on('click', function () {
        var z = map.zoom();
        map.zoom(z - 1);
      })
      .on('mousedown', function () {
        d3.event.stopPropagation();
      });

    put_icon(
      m_minusIcon,
      m_minus,
      m_xscale(0),
      m_yscale(1) + m_width - 2,
      m_width + 5
    ).style('cursor', 'pointer')
      .style('pointer-events', 'none');

    // Respond to a mouse event on the widget
    function respond(evt) {
      var z = m_yscale.invert(d3.mouse(m_this.layer().node()[0])[1]),
          zrange = map.zoomRange();
      z = (1 - z) * (zrange.max - zrange.min) + zrange.min;
      map.zoom(z);
      m_this._update();
      evt.stopPropagation();
    }

    m_track = svg.append('rect')
      .attr('x', m_xscale(0) - m_width / 10)
      .attr('y', m_yscale(0))
      .attr('rx', m_width / 10)
      .attr('ry', m_width / 10)
      .attr('width', m_width / 5)
      .attr('height', m_height)
      .style({
        'fill': 'white',
        'stroke': 'black',
        'cursor': 'pointer'
      })
      .on('click', function () {
        respond(d3.event);
      });

    m_nub = svg.append('rect')
      .attr('x', m_xscale(-4))
      .attr('y', m_yscale(0.5) - m_nubSize / 2)
      .attr('rx', 3)
      .attr('ry', 3)
      .attr('width', m_width)
      .attr('height', m_nubSize)
      .style({
        'fill': 'black',
        'cursor': 'pointer'
      })
      .on('mousedown', function () {
        d3.select(document).on('mousemove.geo.slider', function () {
          respond(d3.event);
        });
        d3.select(document).on('mouseup.geo.slider', function () {
          respond(d3.event);
          d3.select(document).on('.geo.slider', null);
        });
        d3.event.stopPropagation();
      });

    var bbox = svg.node().getBBox();
    back.attr('width', bbox.width + 20)
      .attr('height', bbox.height + 20)
      .attr('x', bbox.x - 10)
      .attr('y', bbox.y - 10)
      .style('opacity', 1e-6);
    main
      .on('mouseenter', function () {
        back.style('opacity', 1);
      })
      .on('mouseleave', function () {
        back.style('opacity', 1e-6);
      });

    svg.selectAll('*')
      .on('mouseover', function () {
        d3.select(this).attr('filter', 'url(#geo-highlight)');
      })
      .on('mouseout', function () {
        d3.select(this).attr('filter', null);
      });

    m_this.layer().geoOn(geo.event.zoom, function () {
      m_this._update();
    });

    m_this._update();
  };

  this._exit = function () {
    m_this.layer().renderer().canvas().remove();
    m_this.layer().geoOff(geo.event.zoom);
  };

  this._update = function (obj) {
    var map = m_this.layer().map(),
        zoomRange = map.zoomRange(),
        zoom = map.zoom(),
        zoomScale = d3.scale.linear();

    obj = obj || {};
    zoom = obj.value || zoom;
    zoomScale.domain([zoomRange.min, zoomRange.max])
      .range([1, 0])
      .clamp(true);

    m_nub.attr('y', m_yscale(zoomScale(zoom)) - m_nubSize / 2);
  };
};

inherit(geo.sliderWidget, geo.widget);

geo.registerWidget('d3', 'slider', geo.sliderWidget);
<|endoftext|>


<commit_before>!function() {
  var _undefined;

  var var1 = 'roperties';
  var var2 = 'ropertyDescriptors';
  var var3 = 'static';
  var var4 = 'onfiguration';
  var _properties = 'p' + var1;
  var _deepProperties = 'deepP' + var1;
  var _propertyDescriptors = 'p' + var2;
  var _staticProperties = var3 + 'P' + var1;
  var _staticDeepProperties = var3 + 'DeepP' + var1;
  var _staticPropertyDescriptors = var3 + 'P' + var2;
  var _configuration = 'c' + var4;
  var _deepConfiguration = 'deepC' + var4;
  var _deepProps = 'deepProps';
  var _deepStatics = 'deepStatics';
  var _deepConf = 'deepConf';
  var _initializers = 'initializers';
  var _methods = 'methods';
  var _composers = 'composers';
  var _compose = 'compose';
  var _object = 'object';
  var _length = 'length';
  var _Object = Object;
  var isArray = Array.isArray;
  var defineProperties = _Object.defineProperties;
  var objectKeys = _Object.keys;
  var3 = Array.prototype;
  var concat = var3.concat;
  var slice = var3.slice;

  var assign = _Object.assign || function(to) {
    var args = arguments, s = 1, from, keys, i;

    for (; s < args[_length];) {
      from = args[s++];
      if (from) {
        keys = objectKeys(from);
        for (i = 0; i < keys[_length]; i++) {
          to[keys[i]] = from[keys[i]];
        }
      }
    }

    return to;
  };

  function isFunction(obj) {
    return typeof obj == 'function';
  }

  function isObject(obj) {
    return obj && (typeof obj == _object || isFunction(obj));
  }

  function isPlainObject(value) {
    return value && typeof value == _object &&
      value.__proto__ == _Object.prototype;
  }

  /**
   * The 'src' argument plays the command role.
   * The returned values is always of the same type as the 'src'.
   * @param {Array|Object|*} dst Destination
   * @param {Array|Object|*} src Source
   * @returns {Array|Object|*} The `dst` argument
   */
  function mergeOne(dst, src) {
    if (src === _undefined) return dst;

    // According to specification arrays must be concatenated.
    // Also, the '.concat' creates a new array instance. Overrides the 'dst'.
    if (isArray(src)) return (isArray(dst) ? dst : []).concat(src);

    // Now deal with non plain 'src' object. 'src' overrides 'dst'
    // Note that functions are also assigned! We do not deep merge functions.
    if (!isPlainObject(src)) return src;

    // See if 'dst' is allowed to be mutated.
    // If not - it's overridden with a new plain object.
    var returnValue = isObject(dst) ? dst : {};

    var keys = objectKeys(src), i = 0, key, srcValue, dstValue, newDst;
    for (; i < keys[_length];) {
      key = keys[i++];

      srcValue = src[key];
      // Do not merge properties with the '_undefined' value.
      if (srcValue !== _undefined) {
        dstValue = returnValue[key];
        // Recursive calls to mergeOne() must allow only plain objects or arrays in dst
        newDst = isPlainObject(dstValue) || isArray(srcValue) ? dstValue : {};

        // deep merge each property. Recursion!
        returnValue[key] = mergeOne(newDst, srcValue);
      }
    }

    return returnValue;
  }

  function merge(dst) {
    return slice.call(arguments, 1).reduce(mergeOne, dst);
  }

  function extractFunctions() {
    var1 = concat.apply([], arguments).filter(isFunction);
    return var1[_length] == 0 ? _undefined : var1;
  }

  function pushUniqueFuncs(dst, src) {
    var i = 0, fn;
    for (; i < src[_length]; i) {
      fn = src[i++];
      if (isFunction(fn) && dst.indexOf(fn) < 0) {
        dst.push(fn);
      }
    }
  }

  function concatAssignFunctions(dstObject, srcArray, propName) {
    if (!isArray(srcArray)) {
      return;
    }

    pushUniqueFuncs(dstObject[propName] = dstObject[propName] || [], srcArray);
  }

  function combineProperties(dstObject, srcObject, propName, action) {
    if (!isObject(srcObject[propName])) {
      return;
    }
    if (!isObject(dstObject[propName])) {
      dstObject[propName] = {};
    }
    action(dstObject[propName], srcObject[propName]);
  }

  function deepMergeAssign(dstObject, srcObject, propName) {
    combineProperties(dstObject, srcObject, propName, merge);
  }

  function mergeAssign(dstObject, srcObject, propName) {
    combineProperties(dstObject, srcObject, propName, assign);
  }

  /**
   * Converts stampit extended descriptor to a standard one.
   * @param {Object|*} descr
   * methods
   * properties
   * props
   * refs
   * initializers
   * [init
   * deepProperties
   * deepProps
   * propertyDescriptors
   * staticProperties
   * statics
   * staticDeepProperties
   * deepStatics
   * staticPropertyDescriptors
   * configuration
   * conf
   * deepConfiguration
   * deepConf
   * composers
   * @returns {Descriptor} Standardised descriptor
   */
  function standardiseDescriptor(descr) {
    if (!isObject(descr)) return descr;
    var4 = {};

    var4[_methods] = descr[_methods] || _undefined;

    var1 = descr[_properties];
    var2 = descr.props;
    var3 = descr.refs;
    var4[_properties] = isObject(var1 || var2 || var3) ? assign({}, var3, var2, var1) : _undefined;

    var4[_initializers] = extractFunctions(descr.init, descr[_initializers]);

    var1 = descr[_deepProperties];
    var2 = descr[_deepProps];
    var4[_deepProperties] = isObject(var1 || var2) ? merge({}, var2, var1) : _undefined;

    var4[_propertyDescriptors] = descr[_propertyDescriptors];

    var1 = descr[_staticProperties];
    var2 = descr.statics;
    var4[_staticProperties] = isObject(var1 || var2) ? assign({}, var2, var1) : _undefined;

    var1 = descr[_staticDeepProperties];
    var2 = descr[_deepStatics];
    var4[_staticDeepProperties] = isObject(var1 || var2) ? merge({}, var2, var1) : _undefined;

    var4[_staticPropertyDescriptors] = descr[_staticPropertyDescriptors];

    var1 = descr[_configuration];
    var2 = descr.conf;
    var4[_configuration] = isObject(var1 || var2) ? assign({}, var2, var1) : _undefined;

    var1 = descr[_deepConfiguration];
    var2 = descr[_deepConf];
    var3 = isObject(var1 || var2) ? merge({}, var2, var1) : _undefined;

    var1 = extractFunctions(descr[_composers]);
    if (var1) {
      var3 = var3 || {};
      concatAssignFunctions(var3, var1, _composers);
    }

    var4[_deepConfiguration] = var3;

    return var4;
  }

  /**
   * Creates new factory instance.
   * @returns {Function} The new factory function.
   */
  function createFactory() {
    return function Stamp(options) {
      var i = Stamp[_compose] || {};
      // Next line was optimized for most JS VMs. Please, be careful here!
      var obj = _Object.create(i[_methods] || null);

      var inits = i[_initializers], args = slice.apply(arguments);
      var initializer, returnedValue;

      var tmp = i[_deepProperties];
      if (tmp) merge(obj, tmp);
      tmp = i[_properties];
      if (tmp) assign(obj, tmp);
      tmp = i[_propertyDescriptors];
      if (tmp) defineProperties(obj, tmp);

      if (!inits || inits[_length] == 0) return obj;

      if (options === _undefined) options = {};
      for (i = 0; i < inits[_length];) {
        initializer = inits[i++];
        if (isFunction(initializer)) {
          returnedValue = initializer.call(obj, options,
            {instance: obj, stamp: Stamp, args: args});
          obj = returnedValue === _undefined ? obj : returnedValue;
        }
      }

      return obj;
    };
  }

  /**
   * Returns a new stamp given a descriptor and a compose function implementation.
   * @param {Descriptor} [descriptor={}] The information about the object the stamp will be creating.
   * @returns {Stamp} The new stamp
   */
  function createStamp(descriptor) {
    var1 = createFactory();

    var2 = descriptor[_staticDeepProperties];
    if (var2) {
      merge(var1, var2);
    }
    var2 = descriptor[_staticProperties];
    if (var2) {
      assign(var1, var2);
    }
    var2 = descriptor[_staticPropertyDescriptors];
    if (var2) {
      defineProperties(var1, var2);
    }

    var2 = isFunction(var1[_compose]) ? var1[_compose] : compose;
    var1[_compose] = function() {
      return var2.apply(this, arguments);
    };
    assign(var1[_compose], descriptor);

    return var1;
  }

  /**
   * Mutates the dstDescriptor by merging the srcComposable data into it.
   * @param {Descriptor} dstDescriptor The descriptor object to merge into.
   * @param {Composable} [srcComposable] The composable
   * (either descriptor or stamp) to merge data form.
   * @returns {Descriptor} Returns the dstDescriptor argument.
   */
  function mergeComposable(dstDescriptor, srcComposable) {
    var4 = (srcComposable && srcComposable[_compose]) || srcComposable;
    if (!isObject(var4)) {
      return dstDescriptor;
    }

    mergeAssign(dstDescriptor, var4, _methods);
    mergeAssign(dstDescriptor, var4, _properties);
    deepMergeAssign(dstDescriptor, var4, _deepProperties);
    mergeAssign(dstDescriptor, var4, _propertyDescriptors);
    mergeAssign(dstDescriptor, var4, _staticProperties);
    deepMergeAssign(dstDescriptor, var4, _staticDeepProperties);
    mergeAssign(dstDescriptor, var4, _staticPropertyDescriptors);
    mergeAssign(dstDescriptor, var4, _configuration);
    deepMergeAssign(dstDescriptor, var4, _deepConfiguration);
    concatAssignFunctions(dstDescriptor, var4[_initializers], _initializers);

    return dstDescriptor;
  }

  /**
   * Given the list of composables (stamp descriptors and stamps) returns
   * a new stamp (composable factory function).
   * @typedef {Function} Compose
   * Parameters:  {...Composable} The list of composables.
   * @returns {Stamp} A new stamp (aka composable factory function)
   */
  function compose() {
    var descriptor = concat.apply([this], arguments)
    .filter(isObject)
    .reduce(mergeComposable, {});
    return createStamp(descriptor);
  }

  /**
   * The Stamp Descriptor
   * @typedef {Function|Object} Descriptor
   * @returns {Stamp} A new stamp based on this Stamp
   * @property {Object} [methods] Methods or other data used as object instances' prototype
   * @property {Array<Function>} [initializers] List of initializers called for each object instance
   * @property {Object} [properties] Shallow assigned properties of object instances
   * @property {Object} [deepProperties] Deeply merged properties of object instances
   * @property {Object} [staticProperties] Shallow assigned properties of Stamps
   * @property {Object} [staticDeepProperties] Deeply merged properties of Stamps
   * @property {Object} [configuration] Shallow assigned properties of Stamp arbitrary metadata
   * @property {Object} [deepConfiguration] Deeply merged properties of Stamp arbitrary metadata
   * @property {Object} [propertyDescriptors] ES5 Property Descriptors applied to object instances
   * @property {Object} [staticPropertyDescriptors] ES5 Property Descriptors applied to Stamps
   */

  /**
   * The Stamp factory function
   * @typedef {Function} Stamp
   * @returns {*} Instantiated object
   * @property {Descriptor} compose - The Stamp descriptor and composition function
   */

  /**
   * A composable object - stamp or descriptor
   * @typedef {Stamp|Descriptor} Composable
   */

  /**
   * Returns true if argument is a stamp.
   * @param {*} obj Any object
   * @returns {Boolean} True is the obj is a stamp
   */
  function isStamp(obj) {
    return isFunction(obj) && isFunction(obj[_compose]);
  }

  function createUtilityFunction(propName, action) {
    return function() {
      var4 = {};
      var3 = concat.apply([{}], arguments);
      var4[propName] = action.apply(_undefined, var3);
      var1 = this;

      return ((var1 && var1[_compose]) || _stampit).call(var1, var4);
    };
  }

  var allUtilities = {};

  allUtilities[_methods] = createUtilityFunction(_methods, assign);

  allUtilities[_properties] = allUtilities.refs = allUtilities.props =
    createUtilityFunction(_properties, assign);

  allUtilities[_initializers] = allUtilities.init =
    createUtilityFunction(_initializers, extractFunctions);

  allUtilities[_composers] = createUtilityFunction(_composers, extractFunctions);

  allUtilities[_deepProperties] = allUtilities[_deepProps] =
    createUtilityFunction(_deepProperties, merge);

  allUtilities[_staticProperties] = allUtilities.statics =
    createUtilityFunction(_staticProperties, assign);

  allUtilities[_staticDeepProperties] = allUtilities[_deepStatics] =
    createUtilityFunction(_staticDeepProperties, merge);

  allUtilities[_configuration] = allUtilities.conf =
    createUtilityFunction(_configuration, assign);

  allUtilities[_deepConfiguration] = allUtilities[_deepConf] =
    createUtilityFunction(_deepConfiguration, merge);

  allUtilities[_propertyDescriptors] = createUtilityFunction(_propertyDescriptors, assign);

  allUtilities[_staticPropertyDescriptors] = createUtilityFunction(_staticPropertyDescriptors, assign);

  /**
   * Infected compose
   * Parameters:  {...Composable} The list of composables.
   * @return {Stamp} The Stampit-flavoured stamp
   */
  var _stampit = function stampit() {
    var i = 0, tmp1, composables = [], uniqueComposers, tmp2 = arguments, tmp3;
    for (; i < tmp2[_length]; i) {
      tmp1 = tmp2[i++];
      if (isObject(tmp1)) {
        composables.push(isStamp(tmp1) ? tmp1 : standardiseDescriptor(tmp1));
      }
    }

    // Calling the standard pure compose function here.
    tmp1 = compose.apply(this || baseStampit, composables);

    tmp2 = tmp1[_compose][_deepConfiguration];
    tmp3 = tmp2 && tmp2[_composers];
    if (tmp3 && tmp3[_length] > 0) {
      pushUniqueFuncs(tmp2[_composers] = uniqueComposers = [], tmp3);

      if (isStamp(this)) {
        composables.unshift(this);
      }
      for (i = 0; i < uniqueComposers[_length]; i) {
        tmp3 = uniqueComposers[i++]({stamp: tmp1, composables: composables});
        tmp1 = isStamp(tmp3) ? tmp3 : tmp1;
      }
    }

    return tmp1;
  };

  // Setting up the shortcut functions
  assign(_stampit, allUtilities);

  var4 = {};
  allUtilities.create = function() {
    return this.apply(_undefined, arguments);
  };
  allUtilities[_compose] = _stampit;
  var4[_staticProperties] = allUtilities;

  /**
   * Infected stamp. Used as a storage of the infection metadata
   * @type {Function}
   * @return {Stamp}
   */
  var baseStampit = compose(var4);

  _stampit[_compose] = _stampit.bind(); // bind to undefined

  if (typeof _undefined != typeof module) module.exports = _stampit; else self.stampit = _stampit;
}();
<commit_msg>Further minification 9<commit_after>!function() {
  var _undefined;

  var var1 = 'roperties';
  var var2 = 'ropertyDescriptors';
  var var3 = 'static';
  var var4 = 'onfiguration';
  var _properties = 'p' + var1;
  var _deepProperties = 'deepP' + var1;
  var _propertyDescriptors = 'p' + var2;
  var _staticProperties = var3 + 'P' + var1;
  var _staticDeepProperties = var3 + 'DeepP' + var1;
  var _staticPropertyDescriptors = var3 + 'P' + var2;
  var _configuration = 'c' + var4;
  var _deepConfiguration = 'deepC' + var4;
  var _deepProps = 'deepProps';
  var _deepStatics = 'deepStatics';
  var _deepConf = 'deepConf';
  var _initializers = 'initializers';
  var _methods = 'methods';
  var _composers = 'composers';
  var _compose = 'compose';
  var _object = 'object';
  var _length = 'length';
  var _create = 'create';
  var _Object = Object;
  var isArray = Array.isArray;
  var defineProperties = _Object.defineProperties;
  var objectKeys = _Object.keys;
  var3 = Array.prototype;
  var concat = var3.concat;
  var slice = var3.slice;

  var assign = _Object.assign || function(to) {
    var args = arguments, s = 1, from, keys, i;

    for (; s < args[_length];) {
      from = args[s++];
      if (from) {
        keys = objectKeys(from);
        for (i = 0; i < keys[_length]; i++) {
          to[keys[i]] = from[keys[i]];
        }
      }
    }

    return to;
  };

  function isFunction(obj) {
    return typeof obj == 'function';
  }

  function isObject(obj) {
    return obj && (typeof obj == _object || isFunction(obj));
  }

  function isPlainObject(value) {
    return value && typeof value == _object &&
      value.__proto__ == _Object.prototype;
  }

  /**
   * The 'src' argument plays the command role.
   * The returned values is always of the same type as the 'src'.
   * @param {Array|Object|*} dst Destination
   * @param {Array|Object|*} src Source
   * @returns {Array|Object|*} The `dst` argument
   */
  function mergeOne(dst, src) {
    if (src === _undefined) return dst;

    // According to specification arrays must be concatenated.
    // Also, the '.concat' creates a new array instance. Overrides the 'dst'.
    if (isArray(src)) return (isArray(dst) ? dst : []).concat(src);

    // Now deal with non plain 'src' object. 'src' overrides 'dst'
    // Note that functions are also assigned! We do not deep merge functions.
    if (!isPlainObject(src)) return src;

    // See if 'dst' is allowed to be mutated.
    // If not - it's overridden with a new plain object.
    var returnValue = isObject(dst) ? dst : {};

    var keys = objectKeys(src), i = 0, key, srcValue, dstValue, newDst;
    for (; i < keys[_length];) {
      key = keys[i++];

      srcValue = src[key];
      // Do not merge properties with the '_undefined' value.
      if (srcValue !== _undefined) {
        dstValue = returnValue[key];
        // Recursive calls to mergeOne() must allow only plain objects or arrays in dst
        newDst = isPlainObject(dstValue) || isArray(srcValue) ? dstValue : {};

        // deep merge each property. Recursion!
        returnValue[key] = mergeOne(newDst, srcValue);
      }
    }

    return returnValue;
  }

  function merge(dst) {
    return slice.call(arguments, 1).reduce(mergeOne, dst);
  }

  function extractFunctions() {
    var1 = concat.apply([], arguments).filter(isFunction);
    return var1[_length] == 0 ? _undefined : var1;
  }

  function pushUniqueFuncs(dst, src) {
    var i = 0, fn;
    for (; i < src[_length]; i) {
      fn = src[i++];
      if (isFunction(fn) && dst.indexOf(fn) < 0) {
        dst.push(fn);
      }
    }
  }

  function concatAssignFunctions(dstObject, srcArray, propName) {
    if (isArray(srcArray)) {
      pushUniqueFuncs(dstObject[propName] = dstObject[propName] || [], srcArray);
    }
  }

  function combineProperties(dstObject, srcObject, propName, action) {
    if (!isObject(srcObject[propName])) {
      return;
    }
    if (!isObject(dstObject[propName])) {
      dstObject[propName] = {};
    }
    action(dstObject[propName], srcObject[propName]);
  }

  function deepMergeAssign(dstObject, srcObject, propName) {
    combineProperties(dstObject, srcObject, propName, merge);
  }

  function mergeAssign(dstObject, srcObject, propName) {
    combineProperties(dstObject, srcObject, propName, assign);
  }

  /**
   * Converts stampit extended descriptor to a standard one.
   * @param {Object|*} descr
   * methods
   * properties
   * props
   * refs
   * initializers
   * [init
   * deepProperties
   * deepProps
   * propertyDescriptors
   * staticProperties
   * statics
   * staticDeepProperties
   * deepStatics
   * staticPropertyDescriptors
   * configuration
   * conf
   * deepConfiguration
   * deepConf
   * composers
   * @returns {Descriptor} Standardised descriptor
   */
  function standardiseDescriptor(descr) {
    if (!isObject(descr)) return descr;
    var4 = {};

    var4[_methods] = descr[_methods] || _undefined;

    var1 = descr[_properties];
    var2 = descr.props;
    var3 = descr.refs;
    var4[_properties] = isObject(var1 || var2 || var3) ? assign({}, var3, var2, var1) : _undefined;

    var4[_initializers] = extractFunctions(descr.init, descr[_initializers]);

    var1 = descr[_deepProperties];
    var2 = descr[_deepProps];
    var4[_deepProperties] = isObject(var1 || var2) ? merge({}, var2, var1) : _undefined;

    var4[_propertyDescriptors] = descr[_propertyDescriptors];

    var1 = descr[_staticProperties];
    var2 = descr.statics;
    var4[_staticProperties] = isObject(var1 || var2) ? assign({}, var2, var1) : _undefined;

    var1 = descr[_staticDeepProperties];
    var2 = descr[_deepStatics];
    var4[_staticDeepProperties] = isObject(var1 || var2) ? merge({}, var2, var1) : _undefined;

    var4[_staticPropertyDescriptors] = descr[_staticPropertyDescriptors];

    var1 = descr[_configuration];
    var2 = descr.conf;
    var4[_configuration] = isObject(var1 || var2) ? assign({}, var2, var1) : _undefined;

    var1 = descr[_deepConfiguration];
    var2 = descr[_deepConf];
    var3 = isObject(var1 || var2) ? merge({}, var2, var1) : _undefined;

    var1 = extractFunctions(descr[_composers]);
    if (var1) {
      var3 = var3 || {};
      concatAssignFunctions(var3, var1, _composers);
    }

    var4[_deepConfiguration] = var3;

    return var4;
  }

  /**
   * Creates new factory instance.
   * @returns {Function} The new factory function.
   */
  function createFactory() {
    return function Stamp(options) {
      var i = Stamp[_compose] || {};
      // Next line was optimized for most JS VMs. Please, be careful here!
      var obj = _Object[_create](i[_methods] || null);

      var inits = i[_initializers], args = slice.apply(arguments);
      var initializer, returnedValue;

      var tmp = i[_deepProperties];
      if (tmp) merge(obj, tmp);
      tmp = i[_properties];
      if (tmp) assign(obj, tmp);
      tmp = i[_propertyDescriptors];
      if (tmp) defineProperties(obj, tmp);

      if (!inits || inits[_length] == 0) return obj;

      if (options === _undefined) options = {};
      for (i = 0; i < inits[_length];) {
        initializer = inits[i++];
        if (isFunction(initializer)) {
          returnedValue = initializer.call(obj, options,
            {instance: obj, stamp: Stamp, args: args});
          obj = returnedValue === _undefined ? obj : returnedValue;
        }
      }

      return obj;
    };
  }

  /**
   * Returns a new stamp given a descriptor and a compose function implementation.
   * @param {Descriptor} [descriptor={}] The information about the object the stamp will be creating.
   * @returns {Stamp} The new stamp
   */
  function createStamp(descriptor) {
    var1 = createFactory();

    var2 = descriptor[_staticDeepProperties];
    var2 && merge(var1, var2);

    var2 = descriptor[_staticProperties];
    var2 && assign(var1, var2);

    var2 = descriptor[_staticPropertyDescriptors];
    var2 && defineProperties(var1, var2);

    var2 = isFunction(var1[_compose]) ? var1[_compose] : compose;
    assign(var1[_compose] = function() {
      return var2.apply(this, arguments);
    }, descriptor);

    return var1;
  }

  /**
   * Mutates the dstDescriptor by merging the srcComposable data into it.
   * @param {Descriptor} dstDescriptor The descriptor object to merge into.
   * @param {Composable} [srcComposable] The composable
   * (either descriptor or stamp) to merge data form.
   * @returns {Descriptor} Returns the dstDescriptor argument.
   */
  function mergeComposable(dstDescriptor, srcComposable) {
    var4 = (srcComposable && srcComposable[_compose]) || srcComposable;
    if (isObject(var4)) {
      mergeAssign(dstDescriptor, var4, _methods);
      mergeAssign(dstDescriptor, var4, _properties);
      deepMergeAssign(dstDescriptor, var4, _deepProperties);
      mergeAssign(dstDescriptor, var4, _propertyDescriptors);
      mergeAssign(dstDescriptor, var4, _staticProperties);
      deepMergeAssign(dstDescriptor, var4, _staticDeepProperties);
      mergeAssign(dstDescriptor, var4, _staticPropertyDescriptors);
      mergeAssign(dstDescriptor, var4, _configuration);
      deepMergeAssign(dstDescriptor, var4, _deepConfiguration);
      concatAssignFunctions(dstDescriptor, var4[_initializers], _initializers);
    }

    return dstDescriptor;
  }

  /**
   * Given the list of composables (stamp descriptors and stamps) returns
   * a new stamp (composable factory function).
   * @typedef {Function} Compose
   * Parameters:  {...Composable} The list of composables.
   * @returns {Stamp} A new stamp (aka composable factory function)
   */
  function compose() {
    var descriptor = concat.apply([this], arguments)
    .filter(isObject)
    .reduce(mergeComposable, {});
    return createStamp(descriptor);
  }

  /**
   * The Stamp Descriptor
   * @typedef {Function|Object} Descriptor
   * @returns {Stamp} A new stamp based on this Stamp
   * @property {Object} [methods] Methods or other data used as object instances' prototype
   * @property {Array<Function>} [initializers] List of initializers called for each object instance
   * @property {Object} [properties] Shallow assigned properties of object instances
   * @property {Object} [deepProperties] Deeply merged properties of object instances
   * @property {Object} [staticProperties] Shallow assigned properties of Stamps
   * @property {Object} [staticDeepProperties] Deeply merged properties of Stamps
   * @property {Object} [configuration] Shallow assigned properties of Stamp arbitrary metadata
   * @property {Object} [deepConfiguration] Deeply merged properties of Stamp arbitrary metadata
   * @property {Object} [propertyDescriptors] ES5 Property Descriptors applied to object instances
   * @property {Object} [staticPropertyDescriptors] ES5 Property Descriptors applied to Stamps
   */

  /**
   * The Stamp factory function
   * @typedef {Function} Stamp
   * @returns {*} Instantiated object
   * @property {Descriptor} compose - The Stamp descriptor and composition function
   */

  /**
   * A composable object - stamp or descriptor
   * @typedef {Stamp|Descriptor} Composable
   */

  /**
   * Returns true if argument is a stamp.
   * @param {*} obj Any object
   * @returns {Boolean} True is the obj is a stamp
   */
  function isStamp(obj) {
    return isFunction(obj) && isFunction(obj[_compose]);
  }

  function createUtilityFunction(propName, action) {
    return function() {
      var4 = {};
      var3 = concat.apply([{}], arguments);
      var4[propName] = action.apply(_undefined, var3);
      var1 = this;

      return ((var1 && var1[_compose]) || _stampit).call(var1, var4);
    };
  }

  var allUtilities = {};

  allUtilities[_methods] = createUtilityFunction(_methods, assign);

  allUtilities[_properties] = allUtilities.refs = allUtilities.props =
    createUtilityFunction(_properties, assign);

  allUtilities[_initializers] = allUtilities.init =
    createUtilityFunction(_initializers, extractFunctions);

  allUtilities[_composers] = createUtilityFunction(_composers, extractFunctions);

  allUtilities[_deepProperties] = allUtilities[_deepProps] =
    createUtilityFunction(_deepProperties, merge);

  allUtilities[_staticProperties] = allUtilities.statics =
    createUtilityFunction(_staticProperties, assign);

  allUtilities[_staticDeepProperties] = allUtilities[_deepStatics] =
    createUtilityFunction(_staticDeepProperties, merge);

  allUtilities[_configuration] = allUtilities.conf =
    createUtilityFunction(_configuration, assign);

  allUtilities[_deepConfiguration] = allUtilities[_deepConf] =
    createUtilityFunction(_deepConfiguration, merge);

  allUtilities[_propertyDescriptors] = createUtilityFunction(_propertyDescriptors, assign);

  allUtilities[_staticPropertyDescriptors] = createUtilityFunction(_staticPropertyDescriptors, assign);

  /**
   * Infected compose
   * Parameters:  {...Composable} The list of composables.
   * @return {Stamp} The Stampit-flavoured stamp
   */
  var _stampit = assign(function stampit() {
    var i = 0, tmp1, composables = [], uniqueComposers, tmp2 = arguments, tmp3;
    for (; i < tmp2[_length]; i) {
      tmp1 = tmp2[i++];
      if (isObject(tmp1)) {
        composables.push(isStamp(tmp1) ? tmp1 : standardiseDescriptor(tmp1));
      }
    }

    // Calling the standard pure compose function here.
    tmp1 = compose.apply(this || baseStampit, composables);

    tmp2 = tmp1[_compose][_deepConfiguration];
    tmp3 = tmp2 && tmp2[_composers];
    if (tmp3 && tmp3[_length] > 0) {
      pushUniqueFuncs(tmp2[_composers] = uniqueComposers = [], tmp3);

      if (isStamp(this)) {
        composables.unshift(this);
      }
      for (i = 0; i < uniqueComposers[_length]; i) {
        tmp3 = uniqueComposers[i++]({stamp: tmp1, composables: composables});
        tmp1 = isStamp(tmp3) ? tmp3 : tmp1;
      }
    }

    return tmp1;
  }, allUtilities); // Setting up the shortcut functions

  var4 = {};
  allUtilities[_create] = function() {
    return this.apply(_undefined, arguments);
  };
  allUtilities[_compose] = _stampit;
  var4[_staticProperties] = allUtilities;

  /**
   * Infected stamp. Used as a storage of the infection metadata
   * @type {Function}
   * @return {Stamp}
   */
  var baseStampit = compose(var4);

  _stampit[_compose] = _stampit.bind(); // bind to undefined

  if (typeof _undefined != typeof module) module.exports = _stampit; else self.stampit = _stampit;
}();
<|endoftext|>


<commit_before>/*global namespace*/
(function () {
    var inspect = namespace.inspect;
    var equal = namespace.equal;

    var shim = namespace.shim;
    var bind = shim.bind;
    var forEach = shim.forEach;
    var filter = shim.filter;
    var map = shim.map;
    var trim = shim.trim;
    var reduce = shim.reduce;
    var getKeys = shim.getKeys;

    var utils = namespace.utils;
    var truncateStack = utils.truncateStack;
    var extend = utils.extend;
    var levenshteinDistance = utils.levenshteinDistance;

    function Assertion(subject, testDescription, flags, args) {
        this.subject = subject;
        this.testDescription = testDescription;
        this.flags = flags;
        this.args = args;
        this.errorMode = 'default';
    }

    Assertion.prototype.standardErrorMessage = function () {
        var argsString = map(this.args, function (arg) {
            return inspect(arg);
        }).join(', ');

        if (argsString.length > 0) {
            argsString = ' ' + argsString;
        }

        return 'expected ' +
            inspect(this.subject) +
            ' ' + this.testDescription +
            argsString;
    };

    Assertion.prototype.throwStandardError = function () {
        throw new Error(this.standardErrorMessage());
    };

    Assertion.prototype.assert = function (condition) {
        var not = !!this.flags.not;
        condition = !!condition;
        if (condition === not) {
            this.throwStandardError();
        }
    };

    function Unexpected(assertions) {
        this.assertions = assertions || {};
    }

    Unexpected.prototype.format = function (message, args) {
        args = map(args, function (arg) {
            return inspect(arg);
        });
        message = message.replace(/\{(\d+)\}/g, function (match, n) {
            return args[n] || match;
        });
        return message;
    };

    Unexpected.prototype.fail = function (message) {
        message = message || "explicit failure";
        var args = Array.prototype.slice.call(arguments, 1);
        throw new Error(this.format(message, args));
    };

    Unexpected.prototype.findAssertionSimilarTo = function (text) {
        var editDistrances = [];
        forEach(getKeys(this.assertions), function (assertion) {
            var distance = levenshteinDistance(text, assertion);
            editDistrances.push({
                assertion: assertion,
                distance: distance
            });
        });
        editDistrances.sort(function (x, y) {
            return x.distance - y.distance;
        });
        return map(editDistrances.slice(0, 5), function (editDistrance) {
            return editDistrance.assertion;
        });
    };

    Unexpected.prototype.addAssertion = function () {
        var assertions = this.assertions;
        var patterns = Array.prototype.slice.call(arguments, 0, -1);
        var handler = Array.prototype.slice.call(arguments, -1)[0];
        forEach(patterns, function (pattern) {
            ensureValidPattern(pattern);
            forEach(expandPattern(pattern), function (expandedPattern) {
                assertions[expandedPattern.text] = {
                    handler: handler,
                    flags: expandedPattern.flags
                };
            });
        });

        return this.expect; // for chaining
    };

    Unexpected.prototype.installPlugin = function (plugin) {
        if (typeof plugin !== 'function') {
            throw new Error('Expected first argument given to installPlugin to be a function');
        }

        plugin(this.expect);
    };

    function handleNestedExpects(e, assertion) {
        switch (assertion.errorMode) {
        case 'nested':
            e.message = assertion.standardErrorMessage() + '\n    ' + e.message.replace(/\n/g, '\n    ');
            break;
        case 'default':
            e.message = assertion.standardErrorMessage();
            break;
        case 'bubble':
            break;
        default:
            throw new Error("Unknown error mode: '" + assertion.errorMode + "'");
        }
    }

    function installExpectMethods(unexpected, expectFunction) {
        var expect = bind(expectFunction, unexpected);
        expect.fail = bind(unexpected.fail, unexpected);
        expect.addAssertion = bind(unexpected.addAssertion, unexpected);
        expect.clone = bind(unexpected.clone, unexpected);
        expect.toString = bind(unexpected.toString, unexpected);
        expect.assertions = unexpected.assertions;
        expect.installPlugin = bind(unexpected.installPlugin, unexpected);
        return expect;
    }

    function makeExpectFunction(unexpected) {
        var expect = installExpectMethods(unexpected, unexpected.expect);
        unexpected.expect = expect;
        return expect;
    }

    Unexpected.prototype.expect = function (subject, testDescriptionString) {
        var that = this;
        if (arguments.length < 2) {
            throw new Error('The expect functions requires at least two parameters.');
        }
        if (typeof testDescriptionString !== 'string') {
            throw new Error('The expect functions requires second parameter to be a string.');
        }
        var assertionRule = this.assertions[testDescriptionString];
        if (assertionRule) {
            var flags = reduce(assertionRule.flags, function (flags, flag) {
                flags[flag] = true;
                return flags;
            }, {});
            var args = Array.prototype.slice.call(arguments, 2);
            var nestingLevel = 0;
            var wrappedExpect = function () {
                nestingLevel += 1;
                try {
                    that.expect.apply(that, arguments);
                    nestingLevel -= 1;
                } catch (e) {
                    nestingLevel -= 1;
                    truncateStack(e, that.expect);
                    if (nestingLevel === 0) {
                        handleNestedExpects(e, assertion);
                    }
                    throw e;
                }
            };
            args.unshift(wrappedExpect, subject);
            var assertion = new Assertion(subject, testDescriptionString, flags, args.slice(2));
            var handler = assertionRule.handler;
            try {
                handler.apply(assertion, args);
            } catch (e) {
                truncateStack(e, this.expect);
                throw e;
            }
        } else {
            var similarAssertions = this.findAssertionSimilarTo(testDescriptionString);
            var message =
                'Unknown assertion "' + testDescriptionString + '", ' +
                'did you mean: "' + similarAssertions[0] + '"';
            var err = new Error(message);
            truncateStack(err, this.expect);
            throw err;
        }
    };

    Unexpected.prototype.toString = function () {
        return getKeys(this.assertions).sort().join('\n');
    };

    Unexpected.prototype.clone = function () {
        var unexpected = new Unexpected(extend({}, this.assertions));
        return makeExpectFunction(unexpected);
    };

    Unexpected.create = function () {
        var unexpected = new Unexpected();
        return makeExpectFunction(unexpected);
    };

    var expandPattern = (function () {
        function isFlag(token) {
            return token.slice(0, 1) === '[' && token.slice(-1) === ']';
        }
        function isAlternation(token) {
            return token.slice(0, 1) === '(' && token.slice(-1) === ')';
        }
        function removeEmptyStrings(texts) {
            return filter(texts, function (text) {
                return text !== '';
            });
        }
        function createPermutations(tokens, index) {
            if (index === tokens.length) {
                return [{ text: '', flags: []}];
            }

            var token = tokens[index];
            var tail = createPermutations(tokens, index + 1);
            if (isFlag(token)) {
                var flag = token.slice(1, -1);
                return map(tail, function (pattern) {
                    return {
                        text: flag + ' ' + pattern.text,
                        flags: [flag].concat(pattern.flags)
                    };
                }).concat(tail);
            } else if (isAlternation(token)) {
                var alternations = token.split(/\(|\)|\|/);
                alternations = removeEmptyStrings(alternations);
                return reduce(alternations, function (result, alternation) {
                    return result.concat(map(tail, function (pattern) {
                        return {
                            text: alternation + pattern.text,
                            flags: pattern.flags
                        };
                    }));
                }, []);
            } else {
                return map(tail, function (pattern) {
                    return {
                        text: token + pattern.text,
                        flags: pattern.flags
                    };
                });
            }
        }
        return function (pattern) {
            pattern = pattern.replace(/(\[[^\]]+\]) ?/g, '$1');
            var splitRegex = /\[[^\]]+\]|\([^\)]+\)/g;
            var tokens = [];
            var m;
            var lastIndex = 0;
            while ((m = splitRegex.exec(pattern))) {
                tokens.push(pattern.slice(lastIndex, m.index));
                tokens.push(pattern.slice(m.index, splitRegex.lastIndex));
                lastIndex = splitRegex.lastIndex;
            }
            tokens.push(pattern.slice(lastIndex));

            tokens = removeEmptyStrings(tokens);
            var permutations = createPermutations(tokens, 0);
            forEach(permutations, function (permutation) {
                permutation.text = trim(permutation.text);
                if (permutation.text === '') {
                    // This can only happen if the pattern only contains flags
                    throw new Error("Assertion patterns must not only contain flags");
                }
            });
            return permutations;
        };
    }());

    function ensureValidUseOfParenthesesOrBrackets(pattern) {
        var counts = {
            '[': 0,
            ']': 0,
            '(': 0,
            ')': 0
        };
        for (var i = 0; i < pattern.length; i += 1) {
            var c = pattern.charAt(i);
            if (c in counts) {
                counts[c] += 1;
            }
            if (c === ']' && counts['['] >= counts[']']) {
                if (counts['['] === counts[']'] + 1) {
                    throw new Error("Assertion patterns must not contain flags with brackets: '" + pattern + "'");
                }

                if (counts['('] !== counts[')']) {
                    throw new Error("Assertion patterns must not contain flags with parentheses: '" + pattern + "'");
                }

                if (pattern.charAt(i - 1) === '[') {
                    throw new Error("Assertion patterns must not contain empty flags: '" + pattern + "'");
                }
            } else if (c === ')' && counts['('] >= counts[')']) {
                if (counts['('] === counts[')'] + 1) {
                    throw new Error("Assertion patterns must not contain alternations with parentheses: '" + pattern + "'");
                }

                if (counts['['] !== counts[']']) {
                    throw new Error("Assertion patterns must not contain alternations with brackets: '" + pattern + "'");
                }
            }

            if ((c === ')' || c === '|') && counts['('] >= counts[')']) {
                if (pattern.charAt(i - 1) === '(' || pattern.charAt(i - 1) === '|') {
                    throw new Error("Assertion patterns must not contain empty alternations: '" + pattern + "'");
                }
            }
        }

        if (counts['['] !== counts[']']) {
            throw new Error("Assertion patterns must not contain unbalanced brackets: '" + pattern + "'");
        }

        if (counts['('] !== counts[')']) {
            throw new Error("Assertion patterns must not contain unbalanced parentheses: '" + pattern + "'");
        }
    }

    function ensureValidPattern(pattern) {
        if (typeof pattern !== 'string' || pattern === '') {
            throw new Error("Assertion patterns must be a non empty string");
        }
        if (pattern.match(/^\s|\s$/)) {
            throw new Error("Assertion patterns can't start or end with whitespace");
        }

        ensureValidUseOfParenthesesOrBrackets(pattern);
    }

    Assertion.prototype.inspect = inspect;
    Assertion.prototype.eql = equal; // Deprecated
    Assertion.prototype.equal = equal;

    namespace.expect = Unexpected.create();
}());
<commit_msg>Added this.obj back as deprecated<commit_after>/*global namespace*/
(function () {
    var inspect = namespace.inspect;
    var equal = namespace.equal;

    var shim = namespace.shim;
    var bind = shim.bind;
    var forEach = shim.forEach;
    var filter = shim.filter;
    var map = shim.map;
    var trim = shim.trim;
    var reduce = shim.reduce;
    var getKeys = shim.getKeys;

    var utils = namespace.utils;
    var truncateStack = utils.truncateStack;
    var extend = utils.extend;
    var levenshteinDistance = utils.levenshteinDistance;

    function Assertion(subject, testDescription, flags, args) {
        this.obj = subject; // deprecated
        this.subject = subject;
        this.testDescription = testDescription;
        this.flags = flags;
        this.args = args;
        this.errorMode = 'default';
    }

    Assertion.prototype.standardErrorMessage = function () {
        var argsString = map(this.args, function (arg) {
            return inspect(arg);
        }).join(', ');

        if (argsString.length > 0) {
            argsString = ' ' + argsString;
        }

        return 'expected ' +
            inspect(this.subject) +
            ' ' + this.testDescription +
            argsString;
    };

    Assertion.prototype.throwStandardError = function () {
        throw new Error(this.standardErrorMessage());
    };

    Assertion.prototype.assert = function (condition) {
        var not = !!this.flags.not;
        condition = !!condition;
        if (condition === not) {
            this.throwStandardError();
        }
    };

    function Unexpected(assertions) {
        this.assertions = assertions || {};
    }

    Unexpected.prototype.format = function (message, args) {
        args = map(args, function (arg) {
            return inspect(arg);
        });
        message = message.replace(/\{(\d+)\}/g, function (match, n) {
            return args[n] || match;
        });
        return message;
    };

    Unexpected.prototype.fail = function (message) {
        message = message || "explicit failure";
        var args = Array.prototype.slice.call(arguments, 1);
        throw new Error(this.format(message, args));
    };

    Unexpected.prototype.findAssertionSimilarTo = function (text) {
        var editDistrances = [];
        forEach(getKeys(this.assertions), function (assertion) {
            var distance = levenshteinDistance(text, assertion);
            editDistrances.push({
                assertion: assertion,
                distance: distance
            });
        });
        editDistrances.sort(function (x, y) {
            return x.distance - y.distance;
        });
        return map(editDistrances.slice(0, 5), function (editDistrance) {
            return editDistrance.assertion;
        });
    };

    Unexpected.prototype.addAssertion = function () {
        var assertions = this.assertions;
        var patterns = Array.prototype.slice.call(arguments, 0, -1);
        var handler = Array.prototype.slice.call(arguments, -1)[0];
        forEach(patterns, function (pattern) {
            ensureValidPattern(pattern);
            forEach(expandPattern(pattern), function (expandedPattern) {
                assertions[expandedPattern.text] = {
                    handler: handler,
                    flags: expandedPattern.flags
                };
            });
        });

        return this.expect; // for chaining
    };

    Unexpected.prototype.installPlugin = function (plugin) {
        if (typeof plugin !== 'function') {
            throw new Error('Expected first argument given to installPlugin to be a function');
        }

        plugin(this.expect);
    };

    function handleNestedExpects(e, assertion) {
        switch (assertion.errorMode) {
        case 'nested':
            e.message = assertion.standardErrorMessage() + '\n    ' + e.message.replace(/\n/g, '\n    ');
            break;
        case 'default':
            e.message = assertion.standardErrorMessage();
            break;
        case 'bubble':
            break;
        default:
            throw new Error("Unknown error mode: '" + assertion.errorMode + "'");
        }
    }

    function installExpectMethods(unexpected, expectFunction) {
        var expect = bind(expectFunction, unexpected);
        expect.fail = bind(unexpected.fail, unexpected);
        expect.addAssertion = bind(unexpected.addAssertion, unexpected);
        expect.clone = bind(unexpected.clone, unexpected);
        expect.toString = bind(unexpected.toString, unexpected);
        expect.assertions = unexpected.assertions;
        expect.installPlugin = bind(unexpected.installPlugin, unexpected);
        return expect;
    }

    function makeExpectFunction(unexpected) {
        var expect = installExpectMethods(unexpected, unexpected.expect);
        unexpected.expect = expect;
        return expect;
    }

    Unexpected.prototype.expect = function (subject, testDescriptionString) {
        var that = this;
        if (arguments.length < 2) {
            throw new Error('The expect functions requires at least two parameters.');
        }
        if (typeof testDescriptionString !== 'string') {
            throw new Error('The expect functions requires second parameter to be a string.');
        }
        var assertionRule = this.assertions[testDescriptionString];
        if (assertionRule) {
            var flags = reduce(assertionRule.flags, function (flags, flag) {
                flags[flag] = true;
                return flags;
            }, {});
            var args = Array.prototype.slice.call(arguments, 2);
            var nestingLevel = 0;
            var wrappedExpect = function () {
                nestingLevel += 1;
                try {
                    that.expect.apply(that, arguments);
                    nestingLevel -= 1;
                } catch (e) {
                    nestingLevel -= 1;
                    truncateStack(e, that.expect);
                    if (nestingLevel === 0) {
                        handleNestedExpects(e, assertion);
                    }
                    throw e;
                }
            };
            args.unshift(wrappedExpect, subject);
            var assertion = new Assertion(subject, testDescriptionString, flags, args.slice(2));
            var handler = assertionRule.handler;
            try {
                handler.apply(assertion, args);
            } catch (e) {
                truncateStack(e, this.expect);
                throw e;
            }
        } else {
            var similarAssertions = this.findAssertionSimilarTo(testDescriptionString);
            var message =
                'Unknown assertion "' + testDescriptionString + '", ' +
                'did you mean: "' + similarAssertions[0] + '"';
            var err = new Error(message);
            truncateStack(err, this.expect);
            throw err;
        }
    };

    Unexpected.prototype.toString = function () {
        return getKeys(this.assertions).sort().join('\n');
    };

    Unexpected.prototype.clone = function () {
        var unexpected = new Unexpected(extend({}, this.assertions));
        return makeExpectFunction(unexpected);
    };

    Unexpected.create = function () {
        var unexpected = new Unexpected();
        return makeExpectFunction(unexpected);
    };

    var expandPattern = (function () {
        function isFlag(token) {
            return token.slice(0, 1) === '[' && token.slice(-1) === ']';
        }
        function isAlternation(token) {
            return token.slice(0, 1) === '(' && token.slice(-1) === ')';
        }
        function removeEmptyStrings(texts) {
            return filter(texts, function (text) {
                return text !== '';
            });
        }
        function createPermutations(tokens, index) {
            if (index === tokens.length) {
                return [{ text: '', flags: []}];
            }

            var token = tokens[index];
            var tail = createPermutations(tokens, index + 1);
            if (isFlag(token)) {
                var flag = token.slice(1, -1);
                return map(tail, function (pattern) {
                    return {
                        text: flag + ' ' + pattern.text,
                        flags: [flag].concat(pattern.flags)
                    };
                }).concat(tail);
            } else if (isAlternation(token)) {
                var alternations = token.split(/\(|\)|\|/);
                alternations = removeEmptyStrings(alternations);
                return reduce(alternations, function (result, alternation) {
                    return result.concat(map(tail, function (pattern) {
                        return {
                            text: alternation + pattern.text,
                            flags: pattern.flags
                        };
                    }));
                }, []);
            } else {
                return map(tail, function (pattern) {
                    return {
                        text: token + pattern.text,
                        flags: pattern.flags
                    };
                });
            }
        }
        return function (pattern) {
            pattern = pattern.replace(/(\[[^\]]+\]) ?/g, '$1');
            var splitRegex = /\[[^\]]+\]|\([^\)]+\)/g;
            var tokens = [];
            var m;
            var lastIndex = 0;
            while ((m = splitRegex.exec(pattern))) {
                tokens.push(pattern.slice(lastIndex, m.index));
                tokens.push(pattern.slice(m.index, splitRegex.lastIndex));
                lastIndex = splitRegex.lastIndex;
            }
            tokens.push(pattern.slice(lastIndex));

            tokens = removeEmptyStrings(tokens);
            var permutations = createPermutations(tokens, 0);
            forEach(permutations, function (permutation) {
                permutation.text = trim(permutation.text);
                if (permutation.text === '') {
                    // This can only happen if the pattern only contains flags
                    throw new Error("Assertion patterns must not only contain flags");
                }
            });
            return permutations;
        };
    }());

    function ensureValidUseOfParenthesesOrBrackets(pattern) {
        var counts = {
            '[': 0,
            ']': 0,
            '(': 0,
            ')': 0
        };
        for (var i = 0; i < pattern.length; i += 1) {
            var c = pattern.charAt(i);
            if (c in counts) {
                counts[c] += 1;
            }
            if (c === ']' && counts['['] >= counts[']']) {
                if (counts['['] === counts[']'] + 1) {
                    throw new Error("Assertion patterns must not contain flags with brackets: '" + pattern + "'");
                }

                if (counts['('] !== counts[')']) {
                    throw new Error("Assertion patterns must not contain flags with parentheses: '" + pattern + "'");
                }

                if (pattern.charAt(i - 1) === '[') {
                    throw new Error("Assertion patterns must not contain empty flags: '" + pattern + "'");
                }
            } else if (c === ')' && counts['('] >= counts[')']) {
                if (counts['('] === counts[')'] + 1) {
                    throw new Error("Assertion patterns must not contain alternations with parentheses: '" + pattern + "'");
                }

                if (counts['['] !== counts[']']) {
                    throw new Error("Assertion patterns must not contain alternations with brackets: '" + pattern + "'");
                }
            }

            if ((c === ')' || c === '|') && counts['('] >= counts[')']) {
                if (pattern.charAt(i - 1) === '(' || pattern.charAt(i - 1) === '|') {
                    throw new Error("Assertion patterns must not contain empty alternations: '" + pattern + "'");
                }
            }
        }

        if (counts['['] !== counts[']']) {
            throw new Error("Assertion patterns must not contain unbalanced brackets: '" + pattern + "'");
        }

        if (counts['('] !== counts[')']) {
            throw new Error("Assertion patterns must not contain unbalanced parentheses: '" + pattern + "'");
        }
    }

    function ensureValidPattern(pattern) {
        if (typeof pattern !== 'string' || pattern === '') {
            throw new Error("Assertion patterns must be a non empty string");
        }
        if (pattern.match(/^\s|\s$/)) {
            throw new Error("Assertion patterns can't start or end with whitespace");
        }

        ensureValidUseOfParenthesesOrBrackets(pattern);
    }

    Assertion.prototype.inspect = inspect;
    Assertion.prototype.eql = equal; // Deprecated
    Assertion.prototype.equal = equal;

    namespace.expect = Unexpected.create();
}());
<|endoftext|>


<commit_before>// nodegit provides Treebuilder, which lets us mutate a
// not-yet-written tree. But you can't recursively put a Treebuilder
// inside a Treebuilder. That's where this class comes in.

const { TreeEntry, Treebuilder, Blob } = require('nodegit');
const { FILEMODE } = TreeEntry;

class MutableTree {
  constructor(repo, tree) {
    this.repo = repo;
    this.tree = tree;
    this.overlay = new Map();
  }
  entryByName(name) {
    if (this.overlay.has(name)) {
      return this.overlay.get(name);
    }
    let result;
    let entry;
    if (this.tree) {
      entry = safeEntryByName(this.tree, name);
    }
    if (entry) {
      result = new MutableEntryWrapper(entry);
    }
    this.overlay.set(name, result);
    return result;
  }

  // object is a Blob, MutableBlob, Tree, or MutableTree
  insert(filename, object, filemode) {
    let entry = new NewEntry(this.repo, object, filemode);
    this.overlay.set(filename, entry);
    return entry;
  }
  async insertPath(path, object, filemode) {
    let parts = path.split('/');
    let here = this;
    while (parts.length > 1) {
      let dirName = parts.shift();
      let entry = here.entryByName(dirName);
      if (!entry || !entry.isTree()) {
        entry = here.insert(dirName, new MutableTree(here.repo, null), FILEMODE.TREE);
      }
      here = await entry.getTree();
    }
    return this.insert(parts[0], object, filemode);
  }
  async write() {
    if (this.overlay.size === 0 && this.tree) {
      return this.tree;
    }
    let builder = await Treebuilder.create(this.repo, this.tree);
    for (let [filename, entry] of this.overlay.entries()) {
      await builder.insert(filename, await entry.write(), entry.filemode());
    }
    return builder.write();
  }
}

class MutableBlob {
  constructor(repo, buffer) {
    this.repo = repo;
    this.buffer = buffer;
  }
  async write() {
    return Blob.createFromBuffer(this.repo, this.buffer, this.buffer.length);
  }
}

class MutableEntryWrapper {
  constructor(repo, entry) {
    this.repo = repo;
    this.entry = entry;
    this._mutableTree = null;
  }
  filemode() {
    return this.entry.filemode();
  }
  isBlob() {
    return this.entry.isBlob();
  }
  isTree() {
    return this.entry.isTree();
  }
  async getBlob() {
    return this.entry.getBlob();
  }
  async getTree() {
    if (!this._mutableTree) {
      this._mutableTree = new MutableTree(this.repo, await this.entry.getTree());
    }
    return this._mutableTree;
  }
  async write() {
    if (this._mutableTree) {
      return this._mutableTree.write();
    } else {
      return this.entry.id();
    }
  }
}

class NewEntry {
  constructor(repo, object, filemode) {
    this.repo = repo;
    this._filemode = filemode;
    if (this.isTree() && !(object instanceof MutableTree)) {
      this._object = new MutableTree(repo, object);
    } else if (this.isBlob() && object instanceof Buffer) {
      this._object = new MutableBlob(repo, object);
    } else {
      this._object = object;
    }
  }
  filemode() {
    return this._filemode;
  }
  isBlob() {
    return this._filemode & FILEMODE.BLOB;
  }
  isTree() {
    return this._filemode & FILEMODE.TREE;
  }
  async getBlob() {
    return this._object;
  }
  async getTree() {
    return this._object;
  }
  async write() {
    if (this.isBlob()) {
      if (this._object instanceof MutableBlob) {
        return this._object.write();
      } else {
        return this._object.id();
      }
    } else {
      return this._object.write();
    }
  }
}

module.exports = { MutableTree, MutableBlob };

function safeEntryByName(tree, name) {
  let entry = tree._entryByName(name);
  if (entry) {
    entry.parent = tree;
  }
  return entry;
}
<commit_msg>fix tree creation<commit_after>// nodegit provides Treebuilder, which lets us mutate a
// not-yet-written tree. But you can't recursively put a Treebuilder
// inside a Treebuilder. That's where this class comes in.

const { TreeEntry, Treebuilder, Blob } = require('nodegit');
const { FILEMODE } = TreeEntry;

class MutableTree {
  constructor(repo, tree) {
    this.repo = repo;
    this.tree = tree;
    this.overlay = new Map();
  }
  entryByName(name) {
    if (this.overlay.has(name)) {
      return this.overlay.get(name);
    }
    let result;
    let entry;
    if (this.tree) {
      entry = safeEntryByName(this.tree, name);
    }
    if (entry) {
      result = new MutableEntryWrapper(entry);
    }
    this.overlay.set(name, result);
    return result;
  }

  // object is a Blob, MutableBlob, Tree, or MutableTree
  insert(filename, object, filemode) {
    let entry = new NewEntry(this.repo, object, filemode);
    this.overlay.set(filename, entry);
    return entry;
  }
  async insertPath(path, object, filemode) {
    let parts = path.split('/');
    let here = this;
    while (parts.length > 1) {
      let dirName = parts.shift();
      let entry = here.entryByName(dirName);
      if (!entry || !entry.isTree()) {
        entry = here.insert(dirName, new MutableTree(here.repo, null), FILEMODE.TREE);
      }
      here = await entry.getTree();
    }
    return here.insert(parts[0], object, filemode);
  }
  async write() {
    if (this.overlay.size === 0 && this.tree) {
      return this.tree;
    }
    let builder = await Treebuilder.create(this.repo, this.tree);
    for (let [filename, entry] of this.overlay.entries()) {
      await builder.insert(filename, await entry.write(), entry.filemode());
    }
    return builder.write();
  }
}

class MutableBlob {
  constructor(repo, buffer) {
    this.repo = repo;
    this.buffer = buffer;
  }
  async write() {
    return Blob.createFromBuffer(this.repo, this.buffer, this.buffer.length);
  }
}

class MutableEntryWrapper {
  constructor(repo, entry) {
    this.repo = repo;
    this.entry = entry;
    this._mutableTree = null;
  }
  filemode() {
    return this.entry.filemode();
  }
  isBlob() {
    return this.entry.isBlob();
  }
  isTree() {
    return this.entry.isTree();
  }
  async getBlob() {
    return this.entry.getBlob();
  }
  async getTree() {
    if (!this._mutableTree) {
      this._mutableTree = new MutableTree(this.repo, await this.entry.getTree());
    }
    return this._mutableTree;
  }
  async write() {
    if (this._mutableTree) {
      return this._mutableTree.write();
    } else {
      return this.entry.id();
    }
  }
}

class NewEntry {
  constructor(repo, object, filemode) {
    this.repo = repo;
    this._filemode = filemode;
    if (this.isTree() && !(object instanceof MutableTree)) {
      this._object = new MutableTree(repo, object);
    } else if (this.isBlob() && object instanceof Buffer) {
      this._object = new MutableBlob(repo, object);
    } else {
      this._object = object;
    }
  }
  filemode() {
    return this._filemode;
  }
  isBlob() {
    return this._filemode & FILEMODE.BLOB;
  }
  isTree() {
    return this._filemode & FILEMODE.TREE;
  }
  async getBlob() {
    return this._object;
  }
  async getTree() {
    return this._object;
  }
  async write() {
    if (this.isBlob()) {
      if (this._object instanceof MutableBlob) {
        return this._object.write();
      } else {
        return this._object.id();
      }
    } else {
      return this._object.write();
    }
  }
}

module.exports = { MutableTree, MutableBlob };

function safeEntryByName(tree, name) {
  let entry = tree._entryByName(name);
  if (entry) {
    entry.parent = tree;
  }
  return entry;
}
<|endoftext|>


<commit_before>/**
 * Bencode library based on specs at http://en.wikipedia.org/wiki/Bencode
 */

var sprintf = require('sprintf').sprintf;

var bencode = function(value) {
  var value_type = typeof(value);

  switch (value_type) {
    case 'number': {
      return bencode_integer(value);
    }

    case 'string': {
      return bencode_string(value);
    }

    case 'object': {
      if (value instanceof Array) {
        return bencode_list(value);
      }
      else if (value instanceof Object) {
        return bencode_dictionary(value);
      }
      else {
        throw new Error('Invalid type')
      }
    }

    default: {
      throw new Error('Invalid type');
    }
  }
}

var bencode_integer = function(integer) {
  return sprintf('i%se', integer);
};

var bencode_string = function(string) {
  return sprintf('%s:%s', string.length, string);
};

var bencode_list = function(list) {
  var item;
  var encoded = [];

  encoded.push('l');
  for (var i = 0; i < list.length; i++) {
    item = list[i];
    encoded.push(bencode(item));
  }

  encoded.push('e');

  return encoded.join('');
};

var bencode_dictionary = function(dictionary) {
  var value, temp;
  var encoded = [];

  encoded.push('d');
  for (var key in dictionary) {
    if (dictionary.hasOwnProperty(key)) {
      value = dictionary[key];

      encoded.push(sprintf('%s%s', bencode_string(key), bencode(value)));
    }
  }

  // Sort the dictionary items by the key name in alphabetic order
  temp = encoded.splice(1);
  temp.sort(function(a, b) {
    var key_a, key_b;

    key_a  = a.substr(a.indexOf(':') + 1);
    key_b  = b.substr(b.indexOf(':') + 1);

    return key_a.localeCompare(key_b);
  });

  encoded = encoded.concat(temp);
  encoded.push('e');

  return encoded.join('');
};

var bdecode = function(string) {
  var match_object;
  var len, value;
  var bencoded_objects = [];

  if (!string) {
    return '';
  }

  if (typeof string !== 'string') {
    throw new Error('First argument must be a string');
  }

  match_object = string.match(/^(\d+):/);
  if (match_object) {
    len = parseInt(match_object[1], 10);
    value = string.substr(match_object[1].length + 1, len);

    if (value.length !== len) {
      throw new Error('Invalid bencoded string');
    }

    return [value, (value.length + match_object[1].length + 1)];
  }

  match_object = string.match(/^i(\d+)e/);
  if (match_object) {
    value = match_object[1];
    len = value.length;

    return [value, match_object[1].length + 2];
  }

  if (string[0] === 'l') {
    return bdecode_list(string);
  }
  else if (string[0] === 'd') {
    return bdecode_dictionary(string);
  }

  return null;
};

var bdecode_list = function(list) {
  var i, item, value;
  var list_array = [];

  if (list[0] !== 'l') {
    throw new Error('Bencoded list objects must start with \'l\'');
  }

  i = 1;
  while (i < list.length - 1) {
    item = list[i];
    if (item === 'e') {
      break;
    }

    value = bdecode(list.substr(i));
    if (!value) {
      break;
    }

    i = i + value[1];
    list_array.push(value[0]);
  }

  return [list_array, list.length];
};

var bdecode_dictionary = function(dictionary) {
  var i, item, key, value;
  var dictionary_object = {};

  if (dictionary[0] !== 'd') {
    throw new Error('Bencoded dictionary objects must start with \'d\'');
  }

  i = 1;
  while (i < dictionary.length - 1) {
    item = dictionary[i];
    if (item === 'e') {
      break;
    }

    value = bdecode(dictionary.substr(i));
    key = value[0];

    if (!value) {
      break;
    }

    i = i + value[1];

    value = bdecode(dictionary.substr(i));
    if (!value) {
      break;
    }

    i = i + value[1];

    dictionary_object[key] = value[0];
  }

  return [dictionary_object, dictionary.length];
};

exports.bencode = bencode;
exports.bencode_integer = bencode_integer;
exports.bencode_string = bencode_string;
exports.bencode_list = bencode_list;
exports.bencode_dictionary = bencode_dictionary;

exports.bdecode = bdecode;
exports.bdecode_list = bdecode_list;
exports.bdecode_dictionary = bdecode_dictionary;
<commit_msg>Fix a bug with accessing value array before checking if it has any members.<commit_after>/**
 * Bencode library based on specs at http://en.wikipedia.org/wiki/Bencode
 */

var sprintf = require('sprintf').sprintf;

var bencode = function(value) {
  var value_type = typeof(value);

  switch (value_type) {
    case 'number': {
      return bencode_integer(value);
    }

    case 'string': {
      return bencode_string(value);
    }

    case 'object': {
      if (value instanceof Array) {
        return bencode_list(value);
      }
      else if (value instanceof Object) {
        return bencode_dictionary(value);
      }
      else {
        throw new Error('Invalid type')
      }
    }

    default: {
      throw new Error('Invalid type');
    }
  }
}

var bencode_integer = function(integer) {
  return sprintf('i%se', integer);
};

var bencode_string = function(string) {
  return sprintf('%s:%s', string.length, string);
};

var bencode_list = function(list) {
  var item;
  var encoded = [];

  encoded.push('l');
  for (var i = 0; i < list.length; i++) {
    item = list[i];
    encoded.push(bencode(item));
  }

  encoded.push('e');

  return encoded.join('');
};

var bencode_dictionary = function(dictionary) {
  var value, temp;
  var encoded = [];

  encoded.push('d');
  for (var key in dictionary) {
    if (dictionary.hasOwnProperty(key)) {
      value = dictionary[key];

      encoded.push(sprintf('%s%s', bencode_string(key), bencode(value)));
    }
  }

  // Sort the dictionary items by the key name in alphabetic order
  temp = encoded.splice(1);
  temp.sort(function(a, b) {
    var key_a, key_b;

    key_a  = a.substr(a.indexOf(':') + 1);
    key_b  = b.substr(b.indexOf(':') + 1);

    return key_a.localeCompare(key_b);
  });

  encoded = encoded.concat(temp);
  encoded.push('e');

  return encoded.join('');
};

var bdecode = function(string) {
  var match_object;
  var len, value;
  var bencoded_objects = [];

  if (!string) {
    return '';
  }

  if (typeof string !== 'string') {
    throw new Error('First argument must be a string');
  }

  match_object = string.match(/^(\d+):/);
  if (match_object) {
    len = parseInt(match_object[1], 10);
    value = string.substr(match_object[1].length + 1, len);

    if (value.length !== len) {
      throw new Error('Invalid bencoded string');
    }

    return [value, (value.length + match_object[1].length + 1)];
  }

  match_object = string.match(/^i(\d+)e/);
  if (match_object) {
    value = match_object[1];
    len = value.length;

    return [value, match_object[1].length + 2];
  }

  if (string[0] === 'l') {
    return bdecode_list(string);
  }
  else if (string[0] === 'd') {
    return bdecode_dictionary(string);
  }

  return null;
};

var bdecode_list = function(list) {
  var i, item, value;
  var list_array = [];

  if (list[0] !== 'l') {
    throw new Error('Bencoded list objects must start with \'l\'');
  }

  i = 1;
  while (i < list.length - 1) {
    item = list[i];
    if (item === 'e') {
      break;
    }

    value = bdecode(list.substr(i));
    if (!value) {
      break;
    }

    i = i + value[1];
    list_array.push(value[0]);
  }

  return [list_array, list.length];
};

var bdecode_dictionary = function(dictionary) {
  var i, item, key, value;
  var dictionary_object = {};

  if (dictionary[0] !== 'd') {
    throw new Error('Bencoded dictionary objects must start with \'d\'');
  }

  i = 1;
  while (i < dictionary.length - 1) {
    item = dictionary[i];
    if (item === 'e') {
      break;
    }

    value = bdecode(dictionary.substr(i));

    if (!value) {
      break;
    }

    key = value[0];
    i = i + value[1];

    value = bdecode(dictionary.substr(i));
    if (!value) {
      break;
    }

    i = i + value[1];

    dictionary_object[key] = value[0];
  }

  return [dictionary_object, dictionary.length];
};

exports.bencode = bencode;
exports.bencode_integer = bencode_integer;
exports.bencode_string = bencode_string;
exports.bencode_list = bencode_list;
exports.bencode_dictionary = bencode_dictionary;

exports.bdecode = bdecode;
exports.bdecode_list = bdecode_list;
exports.bdecode_dictionary = bdecode_dictionary;
<|endoftext|>


<commit_before>// naive matrix implementation
class Matrix {
	constructor(w,h){
		// data should be stored in initial slots, attributes
		// should be cached to take less slots, arrays are expensive
		this.data = new Array(h);
		for(var i = 0; i < h; i++){
			this.data[i] = new Array(w);
		}
	}
	shape(){
		return [this.data.length, this.data[0].length];
	}

	set(x,y,v){
		this.data[x][y]=v;
	}

	at(x,y){
		return this.data[x][y];
	}

	add(other){
		var m = new Matrix(this.data.length, this.data[0].length);
		for(var i = 0; i < this.data.length;i++){
			for(var j = 0; j < this.data[0].length; j++){
				m.data[i][j] = this.data[i][j] + other.data[i][j];
			}
		}
		return m;
	}
	clone(){
		var [height, width] = this.shape();
		var m = new Matrix(height, width);
		for(var i = 0; i < height; i++){
			for(var j = 0; j < width; j++){
				m.data[i][j] = this.data[i][j];
			}
		}
		return m;
	}
	pow(n){
		// this is so naive I'm offended, not even squaring
		var m = this.clone();
		for(var i = 0; i < n; i++){
			var m = m.mul(this);
		}
		return m;
	}
	smul(scalar){
		var m = new Matrix(this.data.length, this.data[0].length);
		for(var i = 0; i < this.data.length; i++){
			for(var j = 0; j < this.data[0].length; j++){
				m.data[i][j] = this.data[i][j] * scalar;
			}
		}
	}
	mul(other){
		// this should definitely be at least Strassen
		// n[i][j] = Sum
		var m = new Matrix(this.data.length, this.data[0].length);
		for(var i = 0; i < this.data.length;i++){
			for(var j = 0; j < this.data[0].length; j++){
				m.data[i][j] = this.data[i][j] + other.data[i][j];
			}
		}
		return m;
	}

	row(i){
		return this.data[i];
	}

	col(j){
		var column = new Array(this.data[0].length);
		for(var i = 0; i < this.data[0].length; i++){
			column[i] = this.data[i][j];
		}
		return column;
	}

	transpose(){
		var m = new Matrix(this.data.length, this.data[0].length);
		for(var i = 0; i < this.data.length; i++){
			for(var j = 0; j < this.data[0].length; j++){
				m.data[i][j] = this.data[j][i];
			}
		}
		return m;
	}

	sub(other){
		var m = new Matrix(this.data.length, this.data[0].length);
		for(var i = 0; i < this.data.length;i++){
			for(var j = 0; j < this.data[0].length; j++){
				var row = this.data[i];
				var col = other.col(j);
				var sum = 0;
				for(var i = 0; i < row.length; i++){
					sum += row[i] * col[j];
				}
				m.data[i][j] = sum;
			}
		}
		return m;
	}
	sum(){
		let [width, height] = this.shape();
		let sum = 0;
		for(let i = 0; i < width; i++){
			for(let j = 0; j < height; j++){
				sum += this.data[i][j];
			}
		}
		return num;
	}
	toString(){
		var rows = this.data.length;
		var str = '{';
		for (var i = 0; i < rows; i++) {
			str += "[" + this.row(i).toString() + "]";
			if (i < rows - 1) {
				str += ",";
			}
		}
		return str + '}';
	}
	toArray() {
		var rows = this.data.length;
		var arr = new Array(rows);
		for (var i = 0; i < rows; i++) {
			arr[i] = this.row(i);
		}
		return arr;
	}
	minor(row, col) {
		var rows = this.data.length;
		var cols = this.data[0].length;
		if (row > rows || col > cols || row < 0 || col < 0) {
			return;
		}

		var minorRow = 0;
		var minorCol = 0;
		var arr = new Array(rows - 1);

		for (var i = 0; i < rows; i++) {
			if (i == row) continue;
			minorCol = 0; //go back to first col upon reaching a new row
			arr[minorRow] = new Array(cols-1);
			var matrixRow = this.row(i);

			for (var j = 0; j < cols; j++) {
				if (j == col) continue;
				arr[minorRow][minorCol] = matrixRow[j];
				minorCol++;
			}

			minorRow++;
		}

		return Matrix.fromArray(arr);
	}
}

Matrix.eye = function(size){
	var m = new Matrix(size, size);
	for(var i = 0; i < size; i++){
		for(var j = 0; j < size; j++){
			if(i === j) m.data[i][j] = 1.0;
			else m.data[i][j] = 0.0;
		}
	}
	return m;
};
Matrix.zeros = function(size){
	var m = new Matrix(size, size);
	for(var i = 0; i < size; i++){
		for(var j = 0; j < size; j++){
			m.data[i][j] = 0.0;
		}
	}
	return m;
};

Matrix.fromArray = function(arr) {
	//TODO: check input is valid (non zero size array etc.)
	if (arr && arr[0]) {
		var rows = arr.length;
		var cols = arr[0].length;
		var m = new Matrix(rows, cols);
		for (var i = 0; i < rows; i++) {
			m.data[i] = arr[i];
		}
		return m;
	}
};

export default Matrix;<commit_msg>added setter and getter functions for matrix class<commit_after>// naive matrix implementation
class Matrix {
	constructor(w,h){
		// data should be stored in initial slots, attributes
		// should be cached to take less slots, arrays are expensive
		this.data = new Array(h);
		for(var i = 0; i < h; i++){
			this.data[i] = new Array(w);
		}
	}
	shape(){
		return [this.data.length, this.data[0].length];
	}

	set(x,y,v){
		this.data[x][y] = v;
	}

	setRow(i, val) {
		this.data[i] = val;
	}

	setCol(j, vals) {
		var height = this.shape()[0];
		for (var i = 0; i < height; i++) {
			this.data[i][j] = vals[i];
		}
	}

	getRow(x) {
		return this.data[x];
	}

	getCol(j) {
		var col = [];
		for (var i = 0; i < this.shape()[0]; i++) {
			col.push(this.data[i][j]);
		}

		return col;
	}

	at(x,y){
		return this.data[x][y];
	}

	add(other){
		var m = new Matrix(this.data.length, this.data[0].length);
		for(var i = 0; i < this.data.length;i++){
			for(var j = 0; j < this.data[0].length; j++){
				m.data[i][j] = this.data[i][j] + other.data[i][j];
			}
		}
		return m;
	}
	clone(){
		var [height, width] = this.shape();
		var m = new Matrix(height, width);
		for(var i = 0; i < height; i++){
			for(var j = 0; j < width; j++){
				m.data[i][j] = this.data[i][j];
			}
		}
		return m;
	}
	pow(n){
		// this is so naive I'm offended, not even squaring
		var m = this.clone();
		for(var i = 0; i < n; i++){
			var m = m.mul(this);
		}
		return m;
	}
	smul(scalar){
		var m = new Matrix(this.data.length, this.data[0].length);
		for(var i = 0; i < this.data.length; i++){
			for(var j = 0; j < this.data[0].length; j++){
				m.data[i][j] = this.data[i][j] * scalar;
			}
		}
	}
	mul(other){
		// this should definitely be at least Strassen
		// n[i][j] = Sum
		var m = new Matrix(this.data.length, this.data[0].length);
		for(var i = 0; i < this.data.length;i++){
			for(var j = 0; j < this.data[0].length; j++){
				m.data[i][j] = this.data[i][j] + other.data[i][j];
			}
		}
		return m;
	}

	row(i){
		return this.data[i];
	}

	col(j){
		var column = new Array(this.data[0].length);
		for(var i = 0; i < this.data[0].length; i++){
			column[i] = this.data[i][j];
		}
		return column;
	}

	transpose(){
		var m = new Matrix(this.data.length, this.data[0].length);
		for(var i = 0; i < this.data.length; i++){
			for(var j = 0; j < this.data[0].length; j++){
				m.data[i][j] = this.data[j][i];
			}
		}
		return m;
	}

	sub(other){
		var m = new Matrix(this.data.length, this.data[0].length);
		for(var i = 0; i < this.data.length;i++){
			for(var j = 0; j < this.data[0].length; j++){
				var row = this.data[i];
				var col = other.col(j);
				var sum = 0;
				for(var i = 0; i < row.length; i++){
					sum += row[i] * col[j];
				}
				m.data[i][j] = sum;
			}
		}
		return m;
	}
	sum(){
		let [width, height] = this.shape();
		let sum = 0;
		for(let i = 0; i < width; i++){
			for(let j = 0; j < height; j++){
				sum += this.data[i][j];
			}
		}
		return num;
	}
	toString(){
		var rows = this.data.length;
		var str = '{';
		for (var i = 0; i < rows; i++) {
			str += "[" + this.row(i).toString() + "]";
			if (i < rows - 1) {
				str += ",";
			}
		}
		return str + '}';
	}
	toArray() {
		var rows = this.data.length;
		var arr = new Array(rows);
		for (var i = 0; i < rows; i++) {
			arr[i] = this.row(i);
		}
		return arr;
	}
	minor(row, col) {
		var rows = this.data.length;
		var cols = this.data[0].length;
		if (row > rows || col > cols || row < 0 || col < 0) {
			return;
		}

		var minorRow = 0;
		var minorCol = 0;
		var arr = new Array(rows - 1);

		for (var i = 0; i < rows; i++) {
			if (i == row) continue;
			minorCol = 0; //go back to first col upon reaching a new row
			arr[minorRow] = new Array(cols-1);
			var matrixRow = this.row(i);

			for (var j = 0; j < cols; j++) {
				if (j == col) continue;
				arr[minorRow][minorCol] = matrixRow[j];
				minorCol++;
			}

			minorRow++;
		}

		return Matrix.fromArray(arr);
	}
}

Matrix.eye = function(size){
	var m = new Matrix(size, size);
	for(var i = 0; i < size; i++){
		for(var j = 0; j < size; j++){
			if(i === j) m.data[i][j] = 1.0;
			else m.data[i][j] = 0.0;
		}
	}
	return m;
};
Matrix.zeros = function(size){
	var m = new Matrix(size, size);
	for(var i = 0; i < size; i++){
		for(var j = 0; j < size; j++){
			m.data[i][j] = 0.0;
		}
	}
	return m;
};

Matrix.fromArray = function(arr) {
	//TODO: check input is valid (non zero size array etc.)
	if (arr && arr[0]) {
		var rows = arr.length;
		var cols = arr[0].length;
		var m = new Matrix(rows, cols);
		for (var i = 0; i < rows; i++) {
			m.data[i] = arr[i];
		}
		return m;
	}
};

export default Matrix;<|endoftext|>


<commit_before>'use strict';

const compute_first_verification_digit = require('./compute_first_verification_digit');
const compute_second_verification_digit = require('./compute_second_verification_digit');

module.exports = cpf => {
  const cpf_str = normalize_cpf(cpf);
  const digits = cpf_str.split('').map(digit => parseInt(digit, 10));

  return length_ok(digits) && not_all_equal(digits) && verification_digits_are_ok(digits);
};

function verification_digits_are_ok (digits) {
  const second_verification_digit = digits.pop();
  const first_verification_digit = digits.pop();

  return first_verification_digit_ok(first_verification_digit, digits) &&
         second_verification_digit_ok(second_verification_digit, digits.concat([first_verification_digit]));
}

function first_verification_digit_ok (verification_digit, first_nine_digits) {
  const calculated_digit = compute_first_verification_digit(first_nine_digits);

  return verification_digit === calculated_digit;
}

function second_verification_digit_ok (verification_digit, first_ten_digits) {
  const calculated_digit = compute_second_verification_digit(first_ten_digits);

  return verification_digit === calculated_digit;
}

function not_all_equal (digits) {
  const first = digits[0];

  const equal_to_first_count = digits.reduce((sum, current_digit) => {
    if (current_digit === first) {
      ++sum;
    }

    return sum;
  }, 0);

  return equal_to_first_count !== 11;
}

function length_ok (digits) {
  return digits.length === 11;
}

function normalize_cpf (cpf) {
  const raw_cpf_str = `${cpf}`;

  const not_digits = /[^0-9]/g;

  return raw_cpf_str.replace(not_digits, '');
}
<commit_msg>Alters cpf validation to use not_all_equal function<commit_after>'use strict';

const compute_first_verification_digit = require('./compute_first_verification_digit');
const compute_second_verification_digit = require('./compute_second_verification_digit');
const not_all_equal = require('./not_all_equal');

module.exports = cpf => {
  const cpf_str = normalize_cpf(cpf);
  const digits = cpf_str.split('').map(digit => parseInt(digit, 10));

  return length_ok(digits) && not_all_equal(digits) && verification_digits_are_ok(digits);
};

function verification_digits_are_ok (digits) {
  const second_verification_digit = digits.pop();
  const first_verification_digit = digits.pop();

  return first_verification_digit_ok(first_verification_digit, digits) &&
         second_verification_digit_ok(second_verification_digit, digits.concat([first_verification_digit]));
}

function first_verification_digit_ok (verification_digit, first_nine_digits) {
  const calculated_digit = compute_first_verification_digit(first_nine_digits);

  return verification_digit === calculated_digit;
}

function second_verification_digit_ok (verification_digit, first_ten_digits) {
  const calculated_digit = compute_second_verification_digit(first_ten_digits);

  return verification_digit === calculated_digit;
}

function length_ok (digits) {
  return digits.length === 11;
}

function normalize_cpf (cpf) {
  const raw_cpf_str = `${cpf}`;

  const not_digits = /[^0-9]/g;

  return raw_cpf_str.replace(not_digits, '');
}
<|endoftext|>