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

  angular.module("firebase")

    // The factory returns an object containing the value of the data at
    // the Firebase location provided, as well as several methods. It
    // takes one or two arguments:
    //
    //   * `ref`: A Firebase reference. Queries or limits may be applied.
    //   * `config`: An object containing any of the advanced config options explained in API docs
    .factory("$firebase", [ "$firebaseUtils", "$firebaseConfig",
      function ($firebaseUtils, $firebaseConfig) {
        function AngularFire(ref, config) {
          // make the new keyword optional
          if (!(this instanceof AngularFire)) {
            return new AngularFire(ref, config);
          }
          this._config = $firebaseConfig(config);
          this._ref = ref;
          this._arraySync = null;
          this._objectSync = null;
          this._assertValidConfig(ref, this._config);
        }

        AngularFire.prototype = {
          $ref: function () {
            return this._ref;
          },

          $push: function (data) {
            var def = $firebaseUtils.defer();
            var ref = this._ref.ref().push();
            var done = this._handle(def, ref);
            if (arguments.length > 0) {
              ref.set(data, done);
            }
            else {
              done();
            }
            return def.promise;
          },

          $set: function (key, data) {
            var ref = this._ref;
            var def = $firebaseUtils.defer();
            if (arguments.length > 1) {
              ref = ref.ref().child(key);
            }
            else {
              data = key;
            }
            if( angular.isFunction(ref.set) || !angular.isObject(data) ) {
              // this is not a query, just do a flat set
              ref.ref().set(data, this._handle(def, ref));
            }
            else {
              var dataCopy = angular.extend({}, data);
              // this is a query, so we will replace all the elements
              // of this query with the value provided, but not blow away
              // the entire Firebase path
              ref.once('value', function(snap) {
                snap.forEach(function(ss) {
                  if( !dataCopy.hasOwnProperty($firebaseUtils.getKey(ss)) ) {
                    dataCopy[$firebaseUtils.getKey(ss)] = null;
                  }
                });
                ref.ref().update(dataCopy, this._handle(def, ref));
              }, this);
            }
            return def.promise;
          },

          $remove: function (key) {
            var ref = this._ref, self = this;
            var def = $firebaseUtils.defer();
            if (arguments.length > 0) {
              ref = ref.ref().child(key);
            }
            if( angular.isFunction(ref.remove) ) {
              // self is not a query, just do a flat remove
              ref.remove(self._handle(def, ref));
            }
            else {
              // self is a query so let's only remove the
              // items in the query and not the entire path
              ref.once('value', function(snap) {
                var promises = [];
                snap.forEach(function(ss) {
                  var d = $firebaseUtils.defer();
                  promises.push(d.promise);
                  ss.ref().remove(self._handle(d));
                }, self);
                $firebaseUtils.allPromises(promises)
                  .then(function() {
                    def.resolve(ref);
                  },
                  function(err){
                    def.reject(err);
                  }
                );
              });
            }
            return def.promise;
          },

          $update: function (key, data) {
            var ref = this._ref.ref();
            var def = $firebaseUtils.defer();
            if (arguments.length > 1) {
              ref = ref.child(key);
            }
            else {
              data = key;
            }
            ref.update(data, this._handle(def, ref));
            return def.promise;
          },

          $transaction: function (key, valueFn, applyLocally) {
            var ref = this._ref.ref();
            if( angular.isFunction(key) ) {
              applyLocally = valueFn;
              valueFn = key;
            }
            else {
              ref = ref.child(key);
            }
            applyLocally = !!applyLocally;

            var def = $firebaseUtils.defer();
            ref.transaction(valueFn, function(err, committed, snap) {
               if( err ) {
                 def.reject(err);
               }
               else {
                 def.resolve(committed? snap : null);
               }
            }, applyLocally);
            return def.promise;
          },

          $asObject: function () {
            if (!this._objectSync || this._objectSync.isDestroyed) {
              this._objectSync = new SyncObject(this, this._config.objectFactory);
            }
            return this._objectSync.getObject();
          },

          $asArray: function () {
            if (!this._arraySync || this._arraySync.isDestroyed) {
              this._arraySync = new SyncArray(this, this._config.arrayFactory);
            }
            return this._arraySync.getArray();
          },

          _handle: function (def) {
            var args = Array.prototype.slice.call(arguments, 1);
            return function (err) {
              if (err) {
                def.reject(err);
              }
              else {
                def.resolve.apply(def, args);
              }
            };
          },

          _assertValidConfig: function (ref, cnf) {
            $firebaseUtils.assertValidRef(ref, 'Must pass a valid Firebase reference ' +
              'to $firebase (not a string or URL)');
            if (!angular.isFunction(cnf.arrayFactory)) {
              throw new Error('config.arrayFactory must be a valid function');
            }
            if (!angular.isFunction(cnf.objectFactory)) {
              throw new Error('config.objectFactory must be a valid function');
            }
          }
        };

        function SyncArray($inst, ArrayFactory) {
          function destroy(err) {
            self.isDestroyed = true;
            var ref = $inst.$ref();
            ref.off('child_added', created);
            ref.off('child_moved', moved);
            ref.off('child_changed', updated);
            ref.off('child_removed', removed);
            array = null;
            resolve(err||'destroyed');
          }

          function init() {
            var ref = $inst.$ref();

            // listen for changes at the Firebase instance
            ref.on('child_added', created, error);
            ref.on('child_moved', moved, error);
            ref.on('child_changed', updated, error);
            ref.on('child_removed', removed, error);

            // determine when initial load is completed
            ref.once('value', function() { resolve(null); }, resolve);
          }

          // call resolve(), do not call this directly
          function _resolveFn(err) {
            if( def ) {
              if( err ) { def.reject(err); }
              else { def.resolve(array); }
              def = null;
            }
          }

          function assertArray(arr) {
            if( !angular.isArray(arr) ) {
              var type = Object.prototype.toString.call(arr);
              throw new Error('arrayFactory must return a valid array that passes ' +
                'angular.isArray and Array.isArray, but received "' + type + '"');
            }
          }

          var def     = $firebaseUtils.defer();
          var array   = new ArrayFactory($inst, destroy, def.promise);
          var batch   = $firebaseUtils.batch();
          var created = batch(function(snap, prevChild) {
            var rec = array.$$added(snap, prevChild);
            if( rec ) {
              array.$$process('child_added', rec, prevChild);
            }
          });
          var updated = batch(function(snap) {
            var rec = array.$getRecord($firebaseUtils.getKey(snap));
            if( rec ) {
              var changed = array.$$updated(snap);
              if( changed ) {
                array.$$process('child_changed', rec);
              }
            }
          });
          var moved   = batch(function(snap, prevChild) {
            var rec = array.$getRecord($firebaseUtils.getKey(snap));
            if( rec ) {
              var confirmed = array.$$moved(snap, prevChild);
              if( confirmed ) {
                array.$$process('child_moved', rec, prevChild);
              }
            }
          });
          var removed = batch(function(snap) {
            var rec = array.$getRecord($firebaseUtils.getKey(snap));
            if( rec ) {
              var confirmed = array.$$removed(snap);
              if( confirmed ) {
                array.$$process('child_removed', rec);
              }
            }
          });
          var error   = batch(array.$$error, array);
          var resolve = batch(_resolveFn);

          var self = this;
          self.isDestroyed = false;
          self.getArray = function() { return array; };

          assertArray(array);
          init();
        }

        function SyncObject($inst, ObjectFactory) {
          function destroy(err) {
            self.isDestroyed = true;
            ref.off('value', applyUpdate);
            obj = null;
            resolve(err||'destroyed');
          }

          function init() {
            ref.on('value', applyUpdate, error);
            ref.once('value', function() { resolve(null); }, resolve);
          }

          // call resolve(); do not call this directly
          function _resolveFn(err) {
            if( def ) {
              if( err ) { def.reject(err); }
              else { def.resolve(obj); }
              def = null;
            }
          }

          var def = $firebaseUtils.defer();
          var obj = new ObjectFactory($inst, destroy, def.promise);
          var ref = $inst.$ref();
          var batch = $firebaseUtils.batch();
          var applyUpdate = batch(function(snap) {
            var changed = obj.$$updated(snap);
            if( changed ) {
              // notifies $watch listeners and
              // updates $scope if bound to a variable
              obj.$$notify();
            }
          });
          var error = batch(obj.$$error, obj);
          var resolve = batch(_resolveFn);

          var self = this;
          self.isDestroyed = false;
          self.getObject = function() { return obj; };
          init();
        }

        return AngularFire;
      }
    ]);
})();
<commit_msg>move static function assertArray() outside of closure so it's only created once.<commit_after>(function() {
  'use strict';

  angular.module("firebase")

    // The factory returns an object containing the value of the data at
    // the Firebase location provided, as well as several methods. It
    // takes one or two arguments:
    //
    //   * `ref`: A Firebase reference. Queries or limits may be applied.
    //   * `config`: An object containing any of the advanced config options explained in API docs
    .factory("$firebase", [ "$firebaseUtils", "$firebaseConfig",
      function ($firebaseUtils, $firebaseConfig) {
        function AngularFire(ref, config) {
          // make the new keyword optional
          if (!(this instanceof AngularFire)) {
            return new AngularFire(ref, config);
          }
          this._config = $firebaseConfig(config);
          this._ref = ref;
          this._arraySync = null;
          this._objectSync = null;
          this._assertValidConfig(ref, this._config);
        }

        AngularFire.prototype = {
          $ref: function () {
            return this._ref;
          },

          $push: function (data) {
            var def = $firebaseUtils.defer();
            var ref = this._ref.ref().push();
            var done = this._handle(def, ref);
            if (arguments.length > 0) {
              ref.set(data, done);
            }
            else {
              done();
            }
            return def.promise;
          },

          $set: function (key, data) {
            var ref = this._ref;
            var def = $firebaseUtils.defer();
            if (arguments.length > 1) {
              ref = ref.ref().child(key);
            }
            else {
              data = key;
            }
            if( angular.isFunction(ref.set) || !angular.isObject(data) ) {
              // this is not a query, just do a flat set
              ref.ref().set(data, this._handle(def, ref));
            }
            else {
              var dataCopy = angular.extend({}, data);
              // this is a query, so we will replace all the elements
              // of this query with the value provided, but not blow away
              // the entire Firebase path
              ref.once('value', function(snap) {
                snap.forEach(function(ss) {
                  if( !dataCopy.hasOwnProperty($firebaseUtils.getKey(ss)) ) {
                    dataCopy[$firebaseUtils.getKey(ss)] = null;
                  }
                });
                ref.ref().update(dataCopy, this._handle(def, ref));
              }, this);
            }
            return def.promise;
          },

          $remove: function (key) {
            var ref = this._ref, self = this;
            var def = $firebaseUtils.defer();
            if (arguments.length > 0) {
              ref = ref.ref().child(key);
            }
            if( angular.isFunction(ref.remove) ) {
              // self is not a query, just do a flat remove
              ref.remove(self._handle(def, ref));
            }
            else {
              // self is a query so let's only remove the
              // items in the query and not the entire path
              ref.once('value', function(snap) {
                var promises = [];
                snap.forEach(function(ss) {
                  var d = $firebaseUtils.defer();
                  promises.push(d.promise);
                  ss.ref().remove(self._handle(d));
                }, self);
                $firebaseUtils.allPromises(promises)
                  .then(function() {
                    def.resolve(ref);
                  },
                  function(err){
                    def.reject(err);
                  }
                );
              });
            }
            return def.promise;
          },

          $update: function (key, data) {
            var ref = this._ref.ref();
            var def = $firebaseUtils.defer();
            if (arguments.length > 1) {
              ref = ref.child(key);
            }
            else {
              data = key;
            }
            ref.update(data, this._handle(def, ref));
            return def.promise;
          },

          $transaction: function (key, valueFn, applyLocally) {
            var ref = this._ref.ref();
            if( angular.isFunction(key) ) {
              applyLocally = valueFn;
              valueFn = key;
            }
            else {
              ref = ref.child(key);
            }
            applyLocally = !!applyLocally;

            var def = $firebaseUtils.defer();
            ref.transaction(valueFn, function(err, committed, snap) {
               if( err ) {
                 def.reject(err);
               }
               else {
                 def.resolve(committed? snap : null);
               }
            }, applyLocally);
            return def.promise;
          },

          $asObject: function () {
            if (!this._objectSync || this._objectSync.isDestroyed) {
              this._objectSync = new SyncObject(this, this._config.objectFactory);
            }
            return this._objectSync.getObject();
          },

          $asArray: function () {
            if (!this._arraySync || this._arraySync.isDestroyed) {
              this._arraySync = new SyncArray(this, this._config.arrayFactory);
            }
            return this._arraySync.getArray();
          },

          _handle: function (def) {
            var args = Array.prototype.slice.call(arguments, 1);
            return function (err) {
              if (err) {
                def.reject(err);
              }
              else {
                def.resolve.apply(def, args);
              }
            };
          },

          _assertValidConfig: function (ref, cnf) {
            $firebaseUtils.assertValidRef(ref, 'Must pass a valid Firebase reference ' +
              'to $firebase (not a string or URL)');
            if (!angular.isFunction(cnf.arrayFactory)) {
              throw new Error('config.arrayFactory must be a valid function');
            }
            if (!angular.isFunction(cnf.objectFactory)) {
              throw new Error('config.objectFactory must be a valid function');
            }
          }
        };

        function SyncArray($inst, ArrayFactory) {
          function destroy(err) {
            self.isDestroyed = true;
            var ref = $inst.$ref();
            ref.off('child_added', created);
            ref.off('child_moved', moved);
            ref.off('child_changed', updated);
            ref.off('child_removed', removed);
            array = null;
            resolve(err||'destroyed');
          }

          function init() {
            var ref = $inst.$ref();

            // listen for changes at the Firebase instance
            ref.on('child_added', created, error);
            ref.on('child_moved', moved, error);
            ref.on('child_changed', updated, error);
            ref.on('child_removed', removed, error);

            // determine when initial load is completed
            ref.once('value', function() { resolve(null); }, resolve);
          }

          // call resolve(), do not call this directly
          function _resolveFn(err) {
            if( def ) {
              if( err ) { def.reject(err); }
              else { def.resolve(array); }
              def = null;
            }
          }

          var def     = $firebaseUtils.defer();
          var array   = new ArrayFactory($inst, destroy, def.promise);
          var batch   = $firebaseUtils.batch();
          var created = batch(function(snap, prevChild) {
            var rec = array.$$added(snap, prevChild);
            if( rec ) {
              array.$$process('child_added', rec, prevChild);
            }
          });
          var updated = batch(function(snap) {
            var rec = array.$getRecord($firebaseUtils.getKey(snap));
            if( rec ) {
              var changed = array.$$updated(snap);
              if( changed ) {
                array.$$process('child_changed', rec);
              }
            }
          });
          var moved   = batch(function(snap, prevChild) {
            var rec = array.$getRecord($firebaseUtils.getKey(snap));
            if( rec ) {
              var confirmed = array.$$moved(snap, prevChild);
              if( confirmed ) {
                array.$$process('child_moved', rec, prevChild);
              }
            }
          });
          var removed = batch(function(snap) {
            var rec = array.$getRecord($firebaseUtils.getKey(snap));
            if( rec ) {
              var confirmed = array.$$removed(snap);
              if( confirmed ) {
                array.$$process('child_removed', rec);
              }
            }
          });
          var error   = batch(array.$$error, array);
          var resolve = batch(_resolveFn);

          var self = this;
          self.isDestroyed = false;
          self.getArray = function() { return array; };

          assertArray(array);
          init();
        }

        function assertArray(arr) {
          if( !angular.isArray(arr) ) {
            var type = Object.prototype.toString.call(arr);
            throw new Error('arrayFactory must return a valid array that passes ' +
            'angular.isArray and Array.isArray, but received "' + type + '"');
          }
        }

        function SyncObject($inst, ObjectFactory) {
          function destroy(err) {
            self.isDestroyed = true;
            ref.off('value', applyUpdate);
            obj = null;
            resolve(err||'destroyed');
          }

          function init() {
            ref.on('value', applyUpdate, error);
            ref.once('value', function() { resolve(null); }, resolve);
          }

          // call resolve(); do not call this directly
          function _resolveFn(err) {
            if( def ) {
              if( err ) { def.reject(err); }
              else { def.resolve(obj); }
              def = null;
            }
          }

          var def = $firebaseUtils.defer();
          var obj = new ObjectFactory($inst, destroy, def.promise);
          var ref = $inst.$ref();
          var batch = $firebaseUtils.batch();
          var applyUpdate = batch(function(snap) {
            var changed = obj.$$updated(snap);
            if( changed ) {
              // notifies $watch listeners and
              // updates $scope if bound to a variable
              obj.$$notify();
            }
          });
          var error = batch(obj.$$error, obj);
          var resolve = batch(_resolveFn);

          var self = this;
          self.isDestroyed = false;
          self.getObject = function() { return obj; };
          init();
        }

        return AngularFire;
      }
    ]);
})();
<|endoftext|>


<commit_before>var ProximityManager = (function() {
    "use strict";

    function ProximityManager(w, h, div) {
	this._nodes = div;
	this._nodex = w / this._nodes;
	this._nodey = h / this._nodes;
	this._clear = [];
	this._map = new Array(this._nodes);
	for (var y = 0; y < this._nodes; y++) {
	    this._map[y] = new Array(this._nodes);
	    for (var x = 0; x < this._nodes; x++)
		this._map[y][x] = {elms:[], cache:[], cached:false}
	}
    };

    ProximityManager.prototype.addElement = function(elm) {
	var x = parseInt(elm.x / this._nodex);
	var y = parseInt(elm.y / this._nodey);
	if (x < 0 || x >= this._nodes || y < 0 || y >= this._nodes)
	    return (false);
	if (!this._map[y][x].elms.length)
	    this._clear.push(y * this._nodes + x);
	this._map[y][x].elms.push(elm);
	return (true);
    };

    ProximityManager.prototype.clear = function() {
	for (var i in this._clear) {
	    var n = this._clear[i];
	    var node = this._map[parseInt(n / this._nodes)][n % this._nodes];
	    node.elms = [];
	    node.cache = [];
	    node.cached = false;
	}
	this._clear = [];
    };

    ProximityManager.prototype.get = function(x, y) {
	if (x < 0 || y < 0 || y >= this._nodes || x >= this._nodes)
	    return (false);
	return this._map[y][x];
    };

    ProximityManager.prototype.query = function(x, y) {
	x = parseInt(x / this._nodex);
	y = parseInt(y / this._nodey);
	if (x < 0 || x >= this._nodes || y < 0 || y >= this._nodes)
	    return (false);
	var node = this._map[y][x]
	if (!node.cached) {
	    for (var j = -1; j <= 1; j++) {
		for (var i = -1; i <= 1; i++) {
		    if (x + i >= 0 && x + i < this._nodes && y + j >= 0 && y + j < this._nodes)
			node.cache = node.cache.concat(this._map[y + j][x + i].elms);
		}
	    }
	    node.cached = true;
	}
	return (node.cache);
    };

    return (ProximityManager);
})();

var Particle = (function() {
    "use strict";

    function Particle(px, py) {
	this.x = px;
	this.y = py;
	this.vx = 0;
	this.vy = 200;
	this.oldx = px;
	this.oldy = py;
    };

    Particle.prototype.resetVelocity = function(box) {
	this.vx = (this.x - this.oldx) / box._ts;
	this.vy = (this.y - this.oldy) / box._ts;
    }

    Particle.prototype.addVelocity = function(x, y) {
	this.vx += x;
	this.vy += y;
    }

    Particle.prototype.addPosition = function(x, y) {
	this.x += x;
	this.y += y;
    }

    return (Particle);
})();

function LoadBox_initFountain(box) {
    box._img = box._ctx.createImageData(box._canvas.width, box._canvas.height);
    box._manager = new ProximityManager(box._img.width, box._img.height, box._img.width / 20);
    box._list = [];
    box._color = box._params.color == undefined ? 0x0000FF : box._params.color;
    box._blobr = 10;
    if ((box._blob = !!box._params.blob)) {
	box._r = (box._color >> 16) & 0xFF;
	box._g = (box._color >> 8) & 0xFF;
	box._b = box._color & 0xFF;
    }

    // Timestep
    box._ts = 1.0 / 40;
    box._ts2 = box._ts * box._ts;

    // Simulation tweaks
    box._grav = box._params.gravity || 100;
    box._radius = box._params.radius || 20;
    box._theta = box._params.theta || 1;
    box._beta = box._params.beta || 0;
    box._stiff = box._params.stiffness || 200;
    box._stiff_n = box._params.stiffness2 || 40;
    box._density = box._params.density || 5;
    box._friction = box._params.friction || 0;

    // Spawn particles
    for (var j = 50; j < box._img.height; j += 3) {
	for (var i = -25; i <= 25; i += 10) {
	    box._list.push(new Particle(box._img.width / 2 + i, j + i % 5));
	}
    }

    function pow(x) { return (x * x); };

    function applyViscosity() {
	var neighbors;
	var rvx, rvy, vx, vy, vd, ix, iy;
	var r, q, u;

	for (var it in box._list) {
	    var i = box._list[it];
	    if (!(neighbors = box._manager.query(i.x, i.y)))
		continue;
	    for (var nit in neighbors) {
		var j = neighbors[nit];
		if (i == j)
		    continue;
		r = Math.sqrt(pow(j.x - i.x) + pow(j.y - i.y));
		if ((q = r / box._radius) < 1) {
		    rvx = (j.x - i.x) / r;
		    rvy = (j.y - i.y) / r;
		    vx = i.vx - j.vx;
		    vy = i.vy - j.vy;
		    vd = Math.sqrt(vx * vx + vy * vy);
		    if ((u = rvx * vx + rvy * vy) > 0) {
			iy = box._ts * (1 - q) * (box._theta * u + box._beta * u * u);
			ix = (iy * rvx) / 2.0;
			iy = (iy * rvy) / 2.0;
			i.addVelocity(-ix, -iy);
			j.addVelocity(ix, iy);
		    }
		}
	    }
	}
    };

    function doubleDensityRelaxation() {
	var neighbors;
	var phi, phi_n, press, press_n;
	var r, q, dxx, dxy, dx, dy;

	for (var it in box._list) {
	    var i = box._list[it];
	    if (!(neighbors = box._manager.query(i.x, i.y)))
		continue;
	    phi = phi_n = 0;
	    for (var nit in neighbors) {
		var j = neighbors[nit];
		if (i == j)
		    continue;
		r = Math.sqrt(pow(j.x - i.x) + pow(j.y - i.y));
		if ((q = r / box._radius) < 1) {
		    q = 1 - q;
		    phi += q * q;
		    phi_n += q * q * q;
		}
	    }
	    press = box._stiff * (phi - box._density);
	    press_n = box._stiff_n * phi_n;
	    dxx = dxy = 0;
	    for (var nit in neighbors) {
		var j = neighbors[nit];
		if (i == j)
		    continue;
		r = Math.sqrt(pow(j.x - i.x) + pow(j.y - i.y));
		if (r != 0 && (q = r / box._radius) < 1) {
		    dy = box._ts2 * (press * (1 - q) + press_n * pow(1 - q));
		    dx = dy * ((j.x - i.x) / r);
		    dy = dy * ((j.y - i.y) / r);
		    j.addPosition(dx, dy);
		    dxx -= dx;
		    dxy -= dy;
		}
	    }
	    i.addPosition(dxx, dxy);
	}
    };

    function resolveCollisions() {
	for (var it in box._list) {
	    var i = box._list[it];
	    if (i.y >= box._img.height - 5 || i.y < 0) {
		i.vy *= -1;
		i.y = i.y < 0 ? 0 : box._img.height - 5;
	    }
	    if (i.x >= box._img.width - 5 || i.x < 0) {
		i.vx *= -1;
		i.x = i.x < 0 ? 0 : box._img.width - 5;
	    }
	}
    };

    box.step = function() {
	if (box._blob)
	    box._ctx.clearRect(0, 0, box._img.width, box._img.height);
	box._manager.clear();
	// Set particles old position and reset proximity manager
	for (var i in box._list) {
	    var p = box._list[i];
	    box._manager.addElement(p);
	    if (!box._blob) {
		box._img.setPixel(parseInt(p.x), parseInt(p.y), 0xFFFFFF);
		box._img.data[(parseInt(p.y) * box._img.width + parseInt(p.x)) * 4 + 3] = 0;
	    }
	    p.oldx = p.x;
	    p.oldy = p.y;
	    p.vy += box._grav * box._ts;
	}
	applyViscosity();
	// Move particles
	for (var i in box._list) {
	    var p = box._list[i];
	    p.addPosition(p.vx * box._ts, p.vy * box._ts);
	}
	doubleDensityRelaxation();
	resolveCollisions();
	for (var i in box._list) {
	    var p = box._list[i];
	    // Update velocity
	    p.resetVelocity(box);
	    // Fountain effect
	    if (Math.abs(p.x - box._img.width / 2) < 10 && box._img.height - p.y < 75) {
		p.vy -= 10;
		p.vx /= 2;
	    }
	    // Display the particle
	    if (!box._blob) {
		box._img.setPixel(parseInt(p.x), parseInt(p.y), box._color);
		box._img.data[(parseInt(p.y) * box._img.width + parseInt(p.x)) * 4 + 3] = 255;
	    } else {
		var grd = box._ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, box._blobr);
		grd.addColorStop(0, "rgba(0, 0, 255, 0.5)");
		grd.addColorStop(1, "rgba(255, 255, 255, 0)");
		box._ctx.beginPath();
		box._ctx.arc(p.x, p.y, box._blobr, 0, 2 * Math.PI, false);
		box._ctx.fillStyle = grd;
		box._ctx.fill();
	    }
	}

	if (box._blob) {
	    box._img = box._ctx.getImageData(0, 0, box._img.width, box._img.height);
	    for (var i = box._img.width * box._img.height * 4 - 4; i >= 0; i -= 4) {
		if (box._img.data[i + 3] > 125 && box._img.data[i + 2] > 125) {
		    box._img.data[i + 0] = box._r;
		    box._img.data[i + 1] = box._g;
		    box._img.data[i + 2] = box._b;
		    box._img.data[i + 3] = 255;
		} else
		    box._img.data[i + 3] = 0;
	    }
	}
	box._ctx.putImageData(box._img, 0, 0);
    };
}
<commit_msg>add: collision management<commit_after>var ProximityManager = (function() {
    "use strict";

    function ProximityManager(w, h, div) {
	this._nodes = div;
	this._nodex = w / this._nodes;
	this._nodey = h / this._nodes;
	this._clear = [];
	this._map = new Array(this._nodes);
	for (var y = 0; y < this._nodes; y++) {
	    this._map[y] = new Array(this._nodes);
	    for (var x = 0; x < this._nodes; x++)
		this._map[y][x] = {elms:[], cache:[], cached:false}
	}
    };

    ProximityManager.prototype.addElement = function(elm) {
	var x = parseInt(elm.x / this._nodex);
	var y = parseInt(elm.y / this._nodey);
	if (x < 0 || x >= this._nodes || y < 0 || y >= this._nodes)
	    return (false);
	if (!this._map[y][x].elms.length)
	    this._clear.push(y * this._nodes + x);
	this._map[y][x].elms.push(elm);
	return (true);
    };

    ProximityManager.prototype.clear = function() {
	for (var i in this._clear) {
	    var n = this._clear[i];
	    var node = this._map[parseInt(n / this._nodes)][n % this._nodes];
	    node.elms = [];
	    node.cache = [];
	    node.cached = false;
	}
	this._clear = [];
    };

    ProximityManager.prototype.get = function(x, y) {
	if (x < 0 || y < 0 || y >= this._nodes || x >= this._nodes)
	    return (false);
	return this._map[y][x];
    };

    ProximityManager.prototype.query = function(x, y) {
	x = parseInt(x / this._nodex);
	y = parseInt(y / this._nodey);
	if (x < 0 || x >= this._nodes || y < 0 || y >= this._nodes)
	    return (false);
	var node = this._map[y][x]
	if (!node.cached) {
	    for (var j = -1; j <= 1; j++) {
		for (var i = -1; i <= 1; i++) {
		    if (x + i >= 0 && x + i < this._nodes && y + j >= 0 && y + j < this._nodes)
			node.cache = node.cache.concat(this._map[y + j][x + i].elms);
		}
	    }
	    node.cached = true;
	}
	return (node.cache);
    };

    return (ProximityManager);
})();

var Particle = (function() {
    "use strict";

    function Particle(px, py) {
	this.x = px;
	this.y = py;
	this.vx = 0;
	this.vy = 200;
	this.oldx = px;
	this.oldy = py;
    };

    Particle.prototype.resetVelocity = function(box) {
	this.vx = (this.x - this.oldx) / box._ts;
	this.vy = (this.y - this.oldy) / box._ts;
    }

    Particle.prototype.addVelocity = function(x, y) {
	this.vx += x;
	this.vy += y;
    }

    Particle.prototype.addPosition = function(x, y) {
	this.x += x;
	this.y += y;
    }

    Particle.prototype.testLineX = function(img) {
	var dir = this.x >= this.oldx ? 1 : -1;
	var step = (this.y - this.oldy) / Math.abs(this.x - this.oldx);
	while (img.data[(parseInt(this.x) + img.width * parseInt(this.y)) * 4 + 3]) {
	    this.x -= dir;
	    this.y -= step;
	}
    }

    Particle.prototype.testLineY = function(img) {
	var dir = this.y >= this.oldy ? 1 : -1;
	var step = (this.x - this.oldx) / Math.abs(this.y - this.oldy);
	while (img.data[(parseInt(this.x) + img.width * parseInt(this.y)) * 4 + 3]) {
	    this.x -= step;
	    this.y -= dir;
	}
    }

    Particle.prototype.collide = function(img) {
	if (Math.abs(this.x - this.oldx) > Math.abs(this.y - this.oldy))
	    this.y != this.oldy && this.testLineX(img);
	else
	    this.x != this.oldx && this.testLineY(img);
    }

    return (Particle);
})();

function LoadBox_initFountain(box) {
    box._img = box._ctx.createImageData(box._canvas.width, box._canvas.height);
    box._manager = new ProximityManager(box._img.width, box._img.height, box._img.width / 20);
    box._list = [];
    box._color = box._params.color == undefined ? 0x0000FF : box._params.color;
    box._blobr = 10;
    if ((box._blob = !!box._params.blob)) {
	box._r = (box._color >> 16) & 0xFF;
	box._g = (box._color >> 8) & 0xFF;
	box._b = box._color & 0xFF;
    }

    // Timestep
    box._ts = 1.0 / 40;
    box._ts2 = box._ts * box._ts;

    // Simulation tweaks
    box._grav = box._params.gravity || 100;
    box._radius = box._params.radius || 20;
    box._theta = box._params.theta || 1;
    box._beta = box._params.beta || 0;
    box._stiff = box._params.stiffness || 200;
    box._stiff_n = box._params.stiffness2 || 40;
    box._density = box._params.density || 5;
    box._friction = box._params.friction || 0;

    // Spawn particles
    for (var j = 100; j < box._img.height; j += 3) {
    	for (var i = -25; i <= 25; i += 10) {
    	    box._list.push(new Particle(box._img.width / 2 + i, j + i % 5));
    	}
    }

    for (var j = 0; j < 50; j++) {
	for (var i = 25; i < 175; i++)
	    box._img.setPixel(i, 50 + j, 0x000000);
    }

    function pow(x) { return (x * x); };

    function applyViscosity() {
	var neighbors;
	var rvx, rvy, vx, vy, vd, ix, iy;
	var r, q, u;

	for (var it in box._list) {
	    var i = box._list[it];
	    if (!(neighbors = box._manager.query(i.x, i.y)))
		continue;
	    for (var nit in neighbors) {
		var j = neighbors[nit];
		if (i == j)
		    continue;
		r = Math.sqrt(pow(j.x - i.x) + pow(j.y - i.y));
		if ((q = r / box._radius) < 1) {
		    rvx = (j.x - i.x) / r;
		    rvy = (j.y - i.y) / r;
		    vx = i.vx - j.vx;
		    vy = i.vy - j.vy;
		    vd = Math.sqrt(vx * vx + vy * vy);
		    if ((u = rvx * vx + rvy * vy) > 0) {
			iy = box._ts * (1 - q) * (box._theta * u + box._beta * u * u);
			ix = (iy * rvx) / 2.0;
			iy = (iy * rvy) / 2.0;
			i.addVelocity(-ix, -iy);
			j.addVelocity(ix, iy);
		    }
		}
	    }
	}
    };

    function doubleDensityRelaxation() {
	var neighbors;
	var phi, phi_n, press, press_n;
	var r, q, dxx, dxy, dx, dy;

	for (var it in box._list) {
	    var i = box._list[it];
	    if (!(neighbors = box._manager.query(i.x, i.y)))
		continue;
	    phi = phi_n = 0;
	    for (var nit in neighbors) {
		var j = neighbors[nit];
		if (i == j)
		    continue;
		r = Math.sqrt(pow(j.x - i.x) + pow(j.y - i.y));
		if ((q = r / box._radius) < 1) {
		    q = 1 - q;
		    phi += q * q;
		    phi_n += q * q * q;
		}
	    }
	    press = box._stiff * (phi - box._density);
	    press_n = box._stiff_n * phi_n;
	    dxx = dxy = 0;
	    for (var nit in neighbors) {
		var j = neighbors[nit];
		if (i == j)
		    continue;
		r = Math.sqrt(pow(j.x - i.x) + pow(j.y - i.y));
		if (r != 0 && (q = r / box._radius) < 1) {
		    dy = box._ts2 * (press * (1 - q) + press_n * pow(1 - q));
		    dx = dy * ((j.x - i.x) / r);
		    dy = dy * ((j.y - i.y) / r);
		    j.addPosition(dx, dy);
		    dxx -= dx;
		    dxy -= dy;
		}
	    }
	    i.addPosition(dxx, dxy);
	}
    };

    function resolveCollisions() {
	for (var it in box._list) {
	    var i = box._list[it];
	    if (i.y >= box._img.height - 5 || i.y < 0) {
		i.vy *= -1;
		i.y = i.y < 0 ? 0 : box._img.height - 5;
	    }
	    if (i.x >= box._img.width - 5 || i.x < 0) {
		i.vx *= -1;
		i.x = i.x < 0 ? 0 : box._img.width - 5;
	    }
	    i.collide(box._img);
	}
    };

    box.step = function() {
	if (box._blob)
	    box._ctx.clearRect(0, 0, box._img.width, box._img.height);
	box._manager.clear();
	// Set particles old position and reset proximity manager
	for (var i in box._list) {
	    var p = box._list[i];
	    box._manager.addElement(p);
	    if (!box._blob) {
		box._img.setPixel(parseInt(p.x), parseInt(p.y), 0xFFFFFF);
		box._img.data[(parseInt(p.y) * box._img.width + parseInt(p.x)) * 4 + 3] = 0;
	    }
	    p.oldx = p.x;
	    p.oldy = p.y;
	    p.vy += box._grav * box._ts;
	}
	applyViscosity();
	// Move particles
	for (var i in box._list) {
	    var p = box._list[i];
	    p.addPosition(p.vx * box._ts, p.vy * box._ts);
	}
	doubleDensityRelaxation();
	resolveCollisions();
	for (var i in box._list) {
	    var p = box._list[i];
	    // Update velocity
	    p.resetVelocity(box);
	    // Fountain effect
	    if (Math.abs(p.x - box._img.width / 2) < 10 && box._img.height - p.y < 75) {
		p.vy -= 10;
		p.vx /= 2;
	    }
	    // Display the particle
	    if (!box._blob) {
		box._img.setPixel(parseInt(p.x), parseInt(p.y), box._color);
		box._img.data[(parseInt(p.y) * box._img.width + parseInt(p.x)) * 4 + 3] = 255;
	    } else {
		var grd = box._ctx.createRadialGradient(p.x, p.y, 0, p.x, p.y, box._blobr);
		grd.addColorStop(0, "rgba(0, 0, 255, 0.5)");
		grd.addColorStop(1, "rgba(255, 255, 255, 0)");
		box._ctx.beginPath();
		box._ctx.arc(p.x, p.y, box._blobr, 0, 2 * Math.PI, false);
		box._ctx.fillStyle = grd;
		box._ctx.fill();
	    }
	}

	if (box._blob) {
	    box._img = box._ctx.getImageData(0, 0, box._img.width, box._img.height);
	    for (var i = box._img.width * box._img.height * 4 - 4; i >= 0; i -= 4) {
		if (box._img.data[i + 3] > 125 && box._img.data[i + 2] > 125) {
		    box._img.data[i + 0] = box._r;
		    box._img.data[i + 1] = box._g;
		    box._img.data[i + 2] = box._b;
		    box._img.data[i + 3] = 255;
		} else
		    box._img.data[i + 3] = 0;
	    }
	}
	box._ctx.putImageData(box._img, 0, 0);
    };
}
<|endoftext|>


<commit_before>import { create_svg_url, normalize_svg, generate_svg } from './svg';

import list from './utils/list';
import random_func from './utils/random';

import { cell_id, is_letter, alias_for } from './utils/index';
import { lazy, clamp, sequence, get_value } from './utils/index';

import by_unit from './utils/by-unit';
import by_charcode from './utils/by-charcode';
import calc from './utils/calc';
import expand from './utils/expand';
import Stack from './utils/stack';
import memo from './utils/memo';

import { shapes, create_shape_points } from './shapes';
import parse_value_group from './parser/parse-value-group';
import parse_shape_commands from './parser/parse-shape-commands';
import parse_svg from './parser/parse-svg';
import parse_svg_path from './parser/parse-svg-path';

import { uniform_time } from './uniform';

function get_exposed(random) {
  const { shuffle } = list(random);
  const { pick, rand, nrand, unique_id } = random_func(random);

  const Expose = {

    index({ count }) {
      return _ => count;
    },

    row({ y }) {
      return _ => y;
    },

    col({ x }) {
      return _ => x;
    },

    depth({ z }) {
      return _ => z;
    },

    size({ grid }) {
      return _ => grid.count;
    },

    ['size-row']({ grid }) {
      return _ => grid.y;
    },

    ['size-col']({ grid }) {
      return _ => grid.x;
    },

    ['size-depth']({ grid }) {
      return _ => grid.z;
    },

    id({ x, y, z }) {
      return _ => cell_id(x, y, z);
    },

    n({ extra }) {
      return n => extra ? (extra[0] + (Number(n) || 0)) : '@n';
    },

    nx({ extra }) {
      return n => extra ? (extra[1] + (Number(n) || 0)) : '@nx';
    },

    ny({ extra }) {
      return n => extra ? (extra[2] + (Number(n) || 0)) : '@ny';
    },

    N({ extra }) {
      return n => extra ? (extra[3] + (Number(n) || 0)) : '@N';
    },

    repeat: (
      make_sequence('')
    ),

    multiple: (
      make_sequence(',')
    ),

    ['multiple-with-space']: (
      make_sequence(' ')
    ),

    pick({ context }) {
      return expand((...args) => {
        return push_stack(context, 'last_pick', pick(args));
      });
    },

    ['pick-n']({ context, extra, position }) {
      let counter = 'pn-counter' + position;
      return expand((...args) => {
        if (!context[counter]) context[counter] = 0;
        context[counter] += 1;
        let max = args.length;
        let [idx = context[counter]] = extra || [];
        let pos = (idx - 1) % max;
        let value = args[pos];
        return push_stack(context, 'last_pick', value);
      });
    },

    ['pick-d']({ context, extra, position }) {
      let counter = 'pd-counter' + position;
      let values = 'pd-values' + position;
      return expand((...args) => {
        if (!context[counter]) context[counter] = 0;
        context[counter] += 1;
        if (!context[values]) {
          context[values] = shuffle(args);
        }
        let max = args.length;
        let [idx = context[counter]] = extra || [];
        let pos = (idx - 1) % max;
        let value = context[values][pos];
        return push_stack(context, 'last_pick', value);
      });
    },

    ['last-pick']({ context }) {
      return (n = 1) => {
        let stack = context.last_pick;
        return stack ? stack.last(n) : '';
      };
    },

    rand({ context }) {
      return (...args) => {
        let transform_type = args.every(is_letter)
          ? by_charcode
          : by_unit;
        let value = transform_type(rand).apply(null, args);
        return push_stack(context, 'last_rand', value);
      };
    },

    nrand({ context }) {
      return (...args) => {
        let transform_type = args.every(is_letter)
          ? by_charcode
          : by_unit;
        let value = transform_type(nrand).apply(null, args);
        return push_stack(context, 'last_rand', value);
      };
    },

    ['rand-int']({ context }) {
      return (...args) => {
        let transform_type = args.every(is_letter)
          ? by_charcode
          : by_unit;
        let rand_int = (...args) => Math.round(rand(...args))
        let value = transform_type(rand_int).apply(null, args)
        return push_stack(context, 'last_rand', value);
      }
    },

    ['nrand-int']({ context }) {
      return (...args) => {
        let transform_type = args.every(is_letter)
          ? by_charcode
          : by_unit;
        let nrand_int = (...args) => Math.round(nrand(...args))
        let value = transform_type(nrand_int).apply(null, args)
        return push_stack(context, 'last_rand', value);
      }
    },

    ['last-rand']({ context }) {
      return (n = 1) => {
        let stack = context.last_rand;
        return stack ? stack.last(n) : '';
      };
    },

    stripe() {
      return (...input) => {
        let colors = input.map(get_value);
        let max = colors.length;
        let default_count = 0;
        let custom_sizes = [];
        let prev;
        if (!max) {
          return '';
        }
        colors.forEach(step => {
          let [_, size] = parse_value_group(step);
          if (size !== undefined) custom_sizes.push(size);
          else default_count += 1;
        });
        let default_size = custom_sizes.length
          ? `(100% - ${custom_sizes.join(' - ')}) / ${default_count}`
          : `100% / ${max}`
        return colors.map((step, i) => {
          if (custom_sizes.length) {
            let [color, size] = parse_value_group(step);
            let prefix = prev ? (prev + ' + ') : '';
            prev = prefix + (size !== undefined ? size : default_size);
            return `${color} 0 calc(${ prev })`
          }
          return `${step} 0 ${100 / max * (i + 1)}%`
        })
        .join(',');
      }
    },

    reflect() {
      return (...input) => {
        return [
          ...input,
          ...input.slice(0, -1).reverse()
        ].join(',');
      }
    },

    calc() {
      return value => calc(get_value(value));
    },

    hex() {
      return value => parseInt(get_value(value)).toString(16);
    },

    svg: lazy((...args) => {
      let value = args.map(input => get_value(input()).trim()).join(',');
      if (!value.startsWith('<')) {
        let parsed = parse_svg(value);
        value = generate_svg(parsed);
      }
      let svg = normalize_svg(value);
      return create_svg_url(svg);
    }),

    ['svg-filter']: lazy((...args) => {
      let value = args.map(input => get_value(input()).trim()).join(',');
      let id = unique_id('filter-');
      if (!value.startsWith('<')) {
        let parsed = parse_svg(value, {
          type: 'block',
          name: 'filter'
        });
        value = generate_svg(parsed);
      }
      let svg = normalize_svg(value).replace(
        /<filter([\s>])/,
        `<filter id="${ id }"$1`
      );
      return create_svg_url(svg, id);
    }),

    var() {
      return value => `var(${ get_value(value) })`;
    },

    t() {
      return value => `var(--${ uniform_time.name })`;
    },

    point({ count, context, extra, position, grid }) {
      let key = 'offset-points' + position;
      return commands => {
        let [idx = count, _, __, max = grid.count] = extra || [];
        if (!context[key]) {
          let config = parse_shape_commands(commands);
          config.points = max;
          context[key] = create_shape_points(config, {min: 1, max: 65536});
        }
        return context[key][idx - 1];
      };
    },

    Point({ count, context, extra, position, grid }) {
      let key = 'offset-points' + position;
      return commands => {
        let [idx = count, _, __, max = grid.count] = extra || [];
        if (!context[key]) {
          let config = parse_shape_commands(commands);
          config.points = max;
          config.absolute = true;
          context[key] = create_shape_points(config, {min: 1, max: 65536});
        }
        return context[key][idx - 1];
      };
    },

    shape() {
      return memo('shape-function', (type = '', ...args) => {
        type = String(type).trim();
        let points = [];
        if (type.length) {
          if (typeof shapes[type] === 'function') {
            points = shapes[type](args);
          } else {
            let commands = type;
            let rest = args.join(',');
            if (rest.length) {
              commands = type + ',' + rest;
            }
            let config = parse_shape_commands(commands);
            points = create_shape_points(config, {min: 3, max: 3600});
          }
        }
        return `polygon(${points.join(',')})`;
      });
    },

    doodle() {
      return value => value;
    },

    shaders() {
      return value => value;
    },

    canvas() {
      return value => value;
    },

    path() {
      return value => value;
    },

    invert() {
      return commands => {
        let parsed = parse_svg_path(commands);
        if (!parsed.valid) return commands;
        return parsed.commands.map(({ name, value }) => {
          switch (name) {
            case 'v': return 'h' + value.join(' ');
            case 'V': return 'H' + value.join(' ');
            case 'h': return 'v' + value.join(' ');
            case 'H': return 'V' + value.join(' ');
            default:  return name + value.join(' ');
          }
        }).join(' ');
      };
    },

    flipH() {
      return commands => {
        let parsed = parse_svg_path(commands);
        if (!parsed.valid) return commands;
        return parsed.commands.map(({ name, value }) => {
          switch (name) {
            case 'h':
            case 'H': return name + value.map(flip_value).join(' ');
            default:  return name + value.join(' ');
          }
        }).join(' ');
      };
    },

    flipV() {
      return commands => {
        let parsed = parse_svg_path(commands);
        if (!parsed.valid) return commands;
        return parsed.commands.map(({ name, value }) => {
          switch (name) {
            case 'v':
            case 'V': return name + value.map(flip_value).join(' ');
            default:  return name + value.join(' ');
          }
        }).join(' ');
      };
    },

    flip(...args) {
      let flipH = Expose.flipH(...args);
      let flipV = Expose.flipV(...args);
      return commands => {
        return flipV(flipH(commands));
      }
    },

  };

  function make_sequence(c) {
    return lazy((n, ...actions) => {
      if (!actions || !n) return '';
      let count = get_value(n());
      let evaluated = calc(count);
      if (evaluated === 0) {
        evaluated = count;
      }
      return sequence(
        evaluated,
        (...args) => {
          return actions.map(action => {
            return get_value(action(...args))
          }).join(',');
        }
      ).join(c);
    });
  }

  function push_stack(context, name, value) {
    if (!context[name]) context[name] = new Stack();
    context[name].push(value);
    return value;
  }

  function flip_value(num) {
    return -1 * num;
  }

  return alias_for(Expose, {
    'm': 'multiple',
    'M': 'multiple-with-space',

    'r':    'rand',
    'rn':   'nrand',
    'ri':   'rand-int',
    'rni':  'nrand-int',
    'lr':   'last-rand',

    'p':  'pick',
    'pn': 'pick-n',
    'pd': 'pick-d',
    'lp': 'last-pick',

    'rep': 'repeat',

    'i': 'index',
    'x': 'col',
    'y': 'row',
    'z': 'depth',

    'I': 'size',
    'X': 'size-col',
    'Y': 'size-row',
    'Z': 'size-depth',

    'flipv': 'flipV',
    'fliph': 'flipH',

    // legacy names, keep them before 1.0
    'nr': 'rn',
    'nri': 'nri',
    'ms': 'multiple-with-space',
    's':  'size',
    'sx': 'size-col',
    'sy': 'size-row',
    'sz': 'size-depth',
    'size-x': 'size-col',
    'size-y': 'size-row',
    'size-z': 'size-depth',
    'multi': 'multiple',
    'pick-by-turn': 'pick-n',
    'max-row': 'size-row',
    'max-col': 'size-col',
    'offset': 'point',
    'Offset': 'Point',

    // error prone
    'stripes': 'stripe',
    'strip':   'stripe',
  });
}

export default get_exposed;
<commit_msg>Add `@reverse` function for svg path<commit_after>import { create_svg_url, normalize_svg, generate_svg } from './svg';

import list from './utils/list';
import random_func from './utils/random';

import { cell_id, is_letter, alias_for } from './utils/index';
import { lazy, clamp, sequence, get_value } from './utils/index';

import by_unit from './utils/by-unit';
import by_charcode from './utils/by-charcode';
import calc from './utils/calc';
import expand from './utils/expand';
import Stack from './utils/stack';
import memo from './utils/memo';

import { shapes, create_shape_points } from './shapes';
import parse_value_group from './parser/parse-value-group';
import parse_shape_commands from './parser/parse-shape-commands';
import parse_svg from './parser/parse-svg';
import parse_svg_path from './parser/parse-svg-path';

import { uniform_time } from './uniform';

function get_exposed(random) {
  const { shuffle } = list(random);
  const { pick, rand, nrand, unique_id } = random_func(random);

  const Expose = {

    index({ count }) {
      return _ => count;
    },

    row({ y }) {
      return _ => y;
    },

    col({ x }) {
      return _ => x;
    },

    depth({ z }) {
      return _ => z;
    },

    size({ grid }) {
      return _ => grid.count;
    },

    ['size-row']({ grid }) {
      return _ => grid.y;
    },

    ['size-col']({ grid }) {
      return _ => grid.x;
    },

    ['size-depth']({ grid }) {
      return _ => grid.z;
    },

    id({ x, y, z }) {
      return _ => cell_id(x, y, z);
    },

    n({ extra }) {
      return n => extra ? (extra[0] + (Number(n) || 0)) : '@n';
    },

    nx({ extra }) {
      return n => extra ? (extra[1] + (Number(n) || 0)) : '@nx';
    },

    ny({ extra }) {
      return n => extra ? (extra[2] + (Number(n) || 0)) : '@ny';
    },

    N({ extra }) {
      return n => extra ? (extra[3] + (Number(n) || 0)) : '@N';
    },

    repeat: (
      make_sequence('')
    ),

    multiple: (
      make_sequence(',')
    ),

    ['multiple-with-space']: (
      make_sequence(' ')
    ),

    pick({ context }) {
      return expand((...args) => {
        return push_stack(context, 'last_pick', pick(args));
      });
    },

    ['pick-n']({ context, extra, position }) {
      let counter = 'pn-counter' + position;
      return expand((...args) => {
        if (!context[counter]) context[counter] = 0;
        context[counter] += 1;
        let max = args.length;
        let [idx = context[counter]] = extra || [];
        let pos = (idx - 1) % max;
        let value = args[pos];
        return push_stack(context, 'last_pick', value);
      });
    },

    ['pick-d']({ context, extra, position }) {
      let counter = 'pd-counter' + position;
      let values = 'pd-values' + position;
      return expand((...args) => {
        if (!context[counter]) context[counter] = 0;
        context[counter] += 1;
        if (!context[values]) {
          context[values] = shuffle(args);
        }
        let max = args.length;
        let [idx = context[counter]] = extra || [];
        let pos = (idx - 1) % max;
        let value = context[values][pos];
        return push_stack(context, 'last_pick', value);
      });
    },

    ['last-pick']({ context }) {
      return (n = 1) => {
        let stack = context.last_pick;
        return stack ? stack.last(n) : '';
      };
    },

    rand({ context }) {
      return (...args) => {
        let transform_type = args.every(is_letter)
          ? by_charcode
          : by_unit;
        let value = transform_type(rand).apply(null, args);
        return push_stack(context, 'last_rand', value);
      };
    },

    nrand({ context }) {
      return (...args) => {
        let transform_type = args.every(is_letter)
          ? by_charcode
          : by_unit;
        let value = transform_type(nrand).apply(null, args);
        return push_stack(context, 'last_rand', value);
      };
    },

    ['rand-int']({ context }) {
      return (...args) => {
        let transform_type = args.every(is_letter)
          ? by_charcode
          : by_unit;
        let rand_int = (...args) => Math.round(rand(...args))
        let value = transform_type(rand_int).apply(null, args)
        return push_stack(context, 'last_rand', value);
      }
    },

    ['nrand-int']({ context }) {
      return (...args) => {
        let transform_type = args.every(is_letter)
          ? by_charcode
          : by_unit;
        let nrand_int = (...args) => Math.round(nrand(...args))
        let value = transform_type(nrand_int).apply(null, args)
        return push_stack(context, 'last_rand', value);
      }
    },

    ['last-rand']({ context }) {
      return (n = 1) => {
        let stack = context.last_rand;
        return stack ? stack.last(n) : '';
      };
    },

    stripe() {
      return (...input) => {
        let colors = input.map(get_value);
        let max = colors.length;
        let default_count = 0;
        let custom_sizes = [];
        let prev;
        if (!max) {
          return '';
        }
        colors.forEach(step => {
          let [_, size] = parse_value_group(step);
          if (size !== undefined) custom_sizes.push(size);
          else default_count += 1;
        });
        let default_size = custom_sizes.length
          ? `(100% - ${custom_sizes.join(' - ')}) / ${default_count}`
          : `100% / ${max}`
        return colors.map((step, i) => {
          if (custom_sizes.length) {
            let [color, size] = parse_value_group(step);
            let prefix = prev ? (prev + ' + ') : '';
            prev = prefix + (size !== undefined ? size : default_size);
            return `${color} 0 calc(${ prev })`
          }
          return `${step} 0 ${100 / max * (i + 1)}%`
        })
        .join(',');
      }
    },

    reflect() {
      return (...input) => {
        return [
          ...input,
          ...input.slice(0, -1).reverse()
        ].join(',');
      }
    },

    calc() {
      return value => calc(get_value(value));
    },

    hex() {
      return value => parseInt(get_value(value)).toString(16);
    },

    svg: lazy((...args) => {
      let value = args.map(input => get_value(input()).trim()).join(',');
      if (!value.startsWith('<')) {
        let parsed = parse_svg(value);
        value = generate_svg(parsed);
      }
      let svg = normalize_svg(value);
      return create_svg_url(svg);
    }),

    ['svg-filter']: lazy((...args) => {
      let value = args.map(input => get_value(input()).trim()).join(',');
      let id = unique_id('filter-');
      if (!value.startsWith('<')) {
        let parsed = parse_svg(value, {
          type: 'block',
          name: 'filter'
        });
        value = generate_svg(parsed);
      }
      let svg = normalize_svg(value).replace(
        /<filter([\s>])/,
        `<filter id="${ id }"$1`
      );
      return create_svg_url(svg, id);
    }),

    var() {
      return value => `var(${ get_value(value) })`;
    },

    t() {
      return value => `var(--${ uniform_time.name })`;
    },

    point({ count, context, extra, position, grid }) {
      let key = 'offset-points' + position;
      return commands => {
        let [idx = count, _, __, max = grid.count] = extra || [];
        if (!context[key]) {
          let config = parse_shape_commands(commands);
          config.points = max;
          context[key] = create_shape_points(config, {min: 1, max: 65536});
        }
        return context[key][idx - 1];
      };
    },

    Point({ count, context, extra, position, grid }) {
      let key = 'offset-points' + position;
      return commands => {
        let [idx = count, _, __, max = grid.count] = extra || [];
        if (!context[key]) {
          let config = parse_shape_commands(commands);
          config.points = max;
          config.absolute = true;
          context[key] = create_shape_points(config, {min: 1, max: 65536});
        }
        return context[key][idx - 1];
      };
    },

    shape() {
      return memo('shape-function', (type = '', ...args) => {
        type = String(type).trim();
        let points = [];
        if (type.length) {
          if (typeof shapes[type] === 'function') {
            points = shapes[type](args);
          } else {
            let commands = type;
            let rest = args.join(',');
            if (rest.length) {
              commands = type + ',' + rest;
            }
            let config = parse_shape_commands(commands);
            points = create_shape_points(config, {min: 3, max: 3600});
          }
        }
        return `polygon(${points.join(',')})`;
      });
    },

    doodle() {
      return value => value;
    },

    shaders() {
      return value => value;
    },

    canvas() {
      return value => value;
    },

    path() {
      return value => value;
    },

    invert() {
      return commands => {
        let parsed = parse_svg_path(commands);
        if (!parsed.valid) return commands;
        return parsed.commands.map(({ name, value }) => {
          switch (name) {
            case 'v': return 'h' + value.join(' ');
            case 'V': return 'H' + value.join(' ');
            case 'h': return 'v' + value.join(' ');
            case 'H': return 'V' + value.join(' ');
            default:  return name + value.join(' ');
          }
        }).join(' ');
      };
    },

    flipH() {
      return commands => {
        let parsed = parse_svg_path(commands);
        if (!parsed.valid) return commands;
        return parsed.commands.map(({ name, value }) => {
          switch (name) {
            case 'h':
            case 'H': return name + value.map(flip_value).join(' ');
            default:  return name + value.join(' ');
          }
        }).join(' ');
      };
    },

    flipV() {
      return commands => {
        let parsed = parse_svg_path(commands);
        if (!parsed.valid) return commands;
        return parsed.commands.map(({ name, value }) => {
          switch (name) {
            case 'v':
            case 'V': return name + value.map(flip_value).join(' ');
            default:  return name + value.join(' ');
          }
        }).join(' ');
      };
    },

    flip(...args) {
      let flipH = Expose.flipH(...args);
      let flipV = Expose.flipV(...args);
      return commands => {
        return flipV(flipH(commands));
      }
    },

    reverse(...args) {
      return commands => {
        let parsed = parse_svg_path(commands);
        if (!parsed.valid) return commands;
        return parsed.commands.reverse().map(({ name, value }) => {
          return name + value.join(' ');
        }).join(' ');
      }
    },

  };

  function make_sequence(c) {
    return lazy((n, ...actions) => {
      if (!actions || !n) return '';
      let count = get_value(n());
      let evaluated = calc(count);
      if (evaluated === 0) {
        evaluated = count;
      }
      return sequence(
        evaluated,
        (...args) => {
          return actions.map(action => {
            return get_value(action(...args))
          }).join(',');
        }
      ).join(c);
    });
  }

  function push_stack(context, name, value) {
    if (!context[name]) context[name] = new Stack();
    context[name].push(value);
    return value;
  }

  function flip_value(num) {
    return -1 * num;
  }

  return alias_for(Expose, {
    'm': 'multiple',
    'M': 'multiple-with-space',

    'r':    'rand',
    'rn':   'nrand',
    'ri':   'rand-int',
    'rni':  'nrand-int',
    'lr':   'last-rand',

    'p':  'pick',
    'pn': 'pick-n',
    'pd': 'pick-d',
    'lp': 'last-pick',

    'rep': 'repeat',

    'i': 'index',
    'x': 'col',
    'y': 'row',
    'z': 'depth',

    'I': 'size',
    'X': 'size-col',
    'Y': 'size-row',
    'Z': 'size-depth',

    'flipv': 'flipV',
    'fliph': 'flipH',

    // legacy names, keep them before 1.0
    'nr': 'rn',
    'nri': 'nri',
    'ms': 'multiple-with-space',
    's':  'size',
    'sx': 'size-col',
    'sy': 'size-row',
    'sz': 'size-depth',
    'size-x': 'size-col',
    'size-y': 'size-row',
    'size-z': 'size-depth',
    'multi': 'multiple',
    'pick-by-turn': 'pick-n',
    'max-row': 'size-row',
    'max-col': 'size-col',
    'offset': 'point',
    'Offset': 'Point',

    // error prone
    'stripes': 'stripe',
    'strip':   'stripe',
  });
}

export default get_exposed;
<|endoftext|>


<commit_before>var SOSI = window.SOSI || {};

(function (ns, undefined) {
    "use strict";

    ns.Point = ns.Base.extend({

        knutepunkt: false,

        initialize: function (line, origo, unit) {
            if (_.isArray(line)) {
                line = line[1];
            }

            var coords = line.split(/\s+/);

            var numDecimals = 0;
            if (unit < 1) {
                numDecimals = String(unit).split(".")[1].length; /* broken for scientific notation */
                //numDecimals = Math.floor(Math.log(unit)/Math.LN10);
            }

            this.y = ns.util.round((parseInt(coords[0], 10) * unit) + origo.y, numDecimals);
            this.x = ns.util.round((parseInt(coords[1], 10) * unit) + origo.x, numDecimals);

            if (coords[2] && !isNaN(coords[2])) {
                this.z = ns.util.round(parseInt(coords[2], 10) * unit, numDecimals);
            }

            if (line.indexOf(".KP") !== -1) {
                this.setTiepoint(
                    line.substring(line.indexOf(".KP"), line.length).split(" ")[1]
                );
            }
        },

        setTiepoint: function (kode) {
            this.has_tiepoint = true;
            this.knutepunktkode = parseInt(kode, 10);
        }
    });

    ns.LineString = ns.Base.extend({
        initialize: function (lines, origo, unit) {
            this.kurve = _.compact(_.map(lines, function (line) {
                if (line.indexOf("NØ") === -1) {
                    return new ns.Point(line, origo, unit);
                }
            }));

            this.knutepunkter = _.filter(this.kurve, function (punkt) {
                return punkt.has_tiepoint;
            });
        }
    });

    function createPolygon(refs, features) {
        var flate =  _.flatten(_.map(refs, function (ref) {
            var id = Math.abs(ref);
            var kurve = features.getById(id);
            if (!kurve) {
                throw new Error("Fant ikke KURVE " + id + " for FLATE");
            }
            var geom = kurve.geometry.kurve;
            if (ref < 0) {
                geom = _.clone(geom).reverse();
            }
            return _.initial(geom);
        }));
        flate.push(flate[0]);
        return flate;
    }

    function parseRefs(refs) {
        return _.map(refs.trim().split(" "), function (ref) {
            return parseInt(ref.replace(":", ""), 10);
        });
    }

    ns.Polygon = ns.Base.extend({
        initialize: function (refs, features) {
            var shell = refs;
            var holes = [];
            var index = refs.indexOf("(");
            if (index !== -1) {
                shell = refs.substr(0, index);
                holes = refs.substr(index, refs.length);
            }

            shell = parseRefs(shell);
            holes = _.map(
                _.reduce(holes, function (result, character) {
                    if (character === "(") {
                        result.push("");
                    } else if (character !== ")" && character !== "") {
                        result[result.length - 1] += character;
                    }
                    return result;
                }, []),
                parseRefs
            );

            this.flate = createPolygon(shell, features);

            this.holes = _.map(holes, function (hole) {
                if (hole.length === 1) {
                    var feature = features.getById(Math.abs(hole[0]));
                    if (feature.geometryType === "FLATE") {
                        return feature.geometry.flate;
                    }
                }
                return createPolygon(hole, features);
            });
            this.shellRefs = shell;
            this.holeRefs = holes;
        }
    });
}(SOSI));
<commit_msg>re-fixing numDecimals, this time with the correct signage<commit_after>var SOSI = window.SOSI || {};

(function (ns, undefined) {
    "use strict";

    ns.Point = ns.Base.extend({

        knutepunkt: false,

        initialize: function (line, origo, unit) {
            if (_.isArray(line)) {
                line = line[1];
            }

            var coords = line.split(/\s+/);

            var numDecimals = 0;
            if (unit < 1) {
                numDecimals = -Math.floor(Math.log(unit)/Math.LN10);
            }

            this.y = ns.util.round((parseInt(coords[0], 10) * unit) + origo.y, numDecimals);
            this.x = ns.util.round((parseInt(coords[1], 10) * unit) + origo.x, numDecimals);

            if (coords[2] && !isNaN(coords[2])) {
                this.z = ns.util.round(parseInt(coords[2], 10) * unit, numDecimals);
            }

            if (line.indexOf(".KP") !== -1) {
                this.setTiepoint(
                    line.substring(line.indexOf(".KP"), line.length).split(" ")[1]
                );
            }
        },

        setTiepoint: function (kode) {
            this.has_tiepoint = true;
            this.knutepunktkode = parseInt(kode, 10);
        }
    });

    ns.LineString = ns.Base.extend({
        initialize: function (lines, origo, unit) {
            this.kurve = _.compact(_.map(lines, function (line) {
                if (line.indexOf("NØ") === -1) {
                    return new ns.Point(line, origo, unit);
                }
            }));

            this.knutepunkter = _.filter(this.kurve, function (punkt) {
                return punkt.has_tiepoint;
            });
        }
    });

    function createPolygon(refs, features) {
        var flate =  _.flatten(_.map(refs, function (ref) {
            var id = Math.abs(ref);
            var kurve = features.getById(id);
            if (!kurve) {
                throw new Error("Fant ikke KURVE " + id + " for FLATE");
            }
            var geom = kurve.geometry.kurve;
            if (ref < 0) {
                geom = _.clone(geom).reverse();
            }
            return _.initial(geom);
        }));
        flate.push(flate[0]);
        return flate;
    }

    function parseRefs(refs) {
        return _.map(refs.trim().split(" "), function (ref) {
            return parseInt(ref.replace(":", ""), 10);
        });
    }

    ns.Polygon = ns.Base.extend({
        initialize: function (refs, features) {
            var shell = refs;
            var holes = [];
            var index = refs.indexOf("(");
            if (index !== -1) {
                shell = refs.substr(0, index);
                holes = refs.substr(index, refs.length);
            }

            shell = parseRefs(shell);
            holes = _.map(
                _.reduce(holes, function (result, character) {
                    if (character === "(") {
                        result.push("");
                    } else if (character !== ")" && character !== "") {
                        result[result.length - 1] += character;
                    }
                    return result;
                }, []),
                parseRefs
            );

            this.flate = createPolygon(shell, features);

            this.holes = _.map(holes, function (hole) {
                if (hole.length === 1) {
                    var feature = features.getById(Math.abs(hole[0]));
                    if (feature.geometryType === "FLATE") {
                        return feature.geometry.flate;
                    }
                }
                return createPolygon(hole, features);
            });
            this.shellRefs = shell;
            this.holeRefs = holes;
        }
    });
}(SOSI));
<|endoftext|>


<commit_before>var request = require('request')
var asciify = require('asciify')

var messages = require('./messages.json')
var addContributor = require('./contributors.js')

var baseURL = 'https://api.github.com/repos/jlord/patchwork/'
var stats = {}

// When a new, open Pull Request comes in via the webhook set on jlord/patchwork
// the request is queued and one by one sent here to verify the PR is a part of
// the Git-it challenges (and not a real, other one) and to verify the file
// contents of the PR and merge, making comments when needed.
// called by:
// mergePR(pullreq, function(err, message) { if (err) console.log(new Date(), message, err)
  // callback(err)
// })

module.exports = function (pullreq, callback) {
  if (pullreq.pull_request) pullreq = pullreq.pull_request
  var prBranch = pullreq.head.ref.toLowerCase()
  stats.user = pullreq.user.login
  stats.prNum = pullreq.number

  // if branch name doesn't include username, it may be
  // a non git-it related normal PR
  if (!prBranch.match(stats.user.toLowerCase())) {
    return writeComment(messages.antipattern_branch, stats.prNum)
  }

  var options = {
    url: baseURL + 'pulls/' + stats.prNum,
    json: true,
    headers: { 'User-Agent': 'request',
               'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
    }
  }

  function getTime (error, response, body) {
    if (error) return callback(error, 'Error in request on PR via number')
    // if a test pr is coming in from @RR
    var info
    if (!error && response.statusCode === 200 && pullreq.user.login === 'reporobot') {
      info = body
      stats.time = info.created_at.toLocaleString()
      // RR is PRing on behalf of:
      console.log(new Date(), 'PR ', stats.prNum, 'Reporobot Pull Request on behalf of ', stats.user)
      return getFile(stats.prNum)
    }

    if (!error && response.statusCode === 200 && pullreq.user.login !== 'reporobot') {
      info = body
      stats.time = info.created_at
      return getFile(stats.prNum)
    }

    callback(body)
  }

  request(options, getTime)

  function getFile (prNum) {
    var options = {
      url: baseURL + 'pulls/' + prNum + '/files',
      json: true,
      headers: {
        'User-Agent': 'request',
        'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
      }
    }

    request(options, function returnFiles (error, response, body) {
      if (error || body.length === 0) return callback(error, 'Error finding file in PR')

      if (!error && response.statusCode === 200) {
        if (body.length > 1) {
          console.log(new Date(), 'PR ', stats.prNum, 'MORE THAN ONE FILE ', stats.user)
          return writeComment(messages.multi_files, stats.prNum)
        }

        var prInfo = body[0]

        if (prInfo === undefined) {
          console.log(new Date(), 'PR ', stats.prNum, 'FILE IS EMPTY ', stats.user)
          return writeComment(messages.empty_file, stats.prNum)
        }

        return verifyFilename(prInfo)
      }
      // huh? why sending this back to function(err, message)?
      callback(body)
    })
  }

  function verifyFilename (prInfo) {
    var filename = prInfo.filename.toLowerCase()
    if (filename.match('contributors/add-' + stats.user.toLowerCase() + '.txt')) {
      console.log(new Date(), 'PR ', stats.prNum, 'Filename: MATCH ', stats.user)
      return verifyContent(prInfo)
    } else {
      return writeComment(messages.bad_filename, stats.prNum)
    }
  }

  function verifyContent (prInfo) {
    // pull out the actual pr content
    var patchArray = prInfo.patch.split('@@')
    var patch = patchArray.pop()
    // generate the expected content
    asciify(stats.user, { font: 'isometric2' }, function (err, res) {
      if (err) return callback(err, 'Error generating ascii art to test against')
      console.log(patch)
      console.log(res)
      if (patch !== stats.user) {
        stats.userArt = res
        console.log(new Date(), 'PR ', stats.prNum, 'Content: MATCH ', stats.user)
        return setTimeout(mergePR(stats.prNum), 5000)
      } else {
        return writeComment(messages.bad_ascii, stats.prNum)
      }
    })
  }

  function writeComment (message, prNum) {
    stats.user = stats.user || 'a skipped PR'
    console.log(new Date(), 'PR ' + prNum + ' Uh oh, writing comment for ' + stats.user)
    var options = {
      url: baseURL + 'issues/' + prNum + '/comments',
      headers: {
        'User-Agent': 'request',
        'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
      },
      json: {'body': message}
    }

    request.post(options, function doneWriteComment (error, response, body) {
      if (error) return callback(error, 'Error writing comment on PR')
      callback()
    })
  }

  function mergePR (prNum) {
    var tries = 0
    var limit = 25

    tryMerge()

    function tryMerge () {
      var message = 'Merging PR from @' + stats.user
      var options = {
        url: baseURL + 'pulls/' + prNum + '/merge',
        headers: {
          'User-Agent': 'request',
          'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
        },
        json: {'commit_message': message}
      }

      request.put(options, function doneMerge (error, response, body) {
        if (error) return callback(error, 'Error merging PR')
        if (response.statusCode !== 200) {
          console.log(new Date(), prNum, 'ERROR MERGING', response.statusCode, body.message)
          console.log(new Date(), prNum, 'TRYING AGAIN')
          if (tries <= limit) {
            tries++
            return setTimeout(tryMerge(prNum), 3000)
          } else {
            callback(null, new Date() + 'Could not merge after ' + limit + ' tries ' + prNum)
          }
        }
        if (!error && response.statusCode === 200) {
          console.log(new Date(), 'PR ', prNum, 'MERGED', stats.user)
          // add contributor to file and then rebuild page
          return addContributor(stats, callback)
        } else {
          callback(error, body)
        }
      })
    }
  }
}
<commit_msg>Check if patch exists<commit_after>var request = require('request')
var asciify = require('asciify')

var messages = require('./messages.json')
var addContributor = require('./contributors.js')

var baseURL = 'https://api.github.com/repos/jlord/patchwork/'
var stats = {}

// When a new, open Pull Request comes in via the webhook set on jlord/patchwork
// the request is queued and one by one sent here to verify the PR is a part of
// the Git-it challenges (and not a real, other one) and to verify the file
// contents of the PR and merge, making comments when needed.
// called by:
// mergePR(pullreq, function(err, message) { if (err) console.log(new Date(), message, err)
  // callback(err)
// })

module.exports = function (pullreq, callback) {
  if (pullreq.pull_request) pullreq = pullreq.pull_request
  var prBranch = pullreq.head.ref.toLowerCase()
  stats.user = pullreq.user.login
  stats.prNum = pullreq.number

  // if branch name doesn't include username, it may be
  // a non git-it related normal PR
  if (!prBranch.match(stats.user.toLowerCase())) {
    return writeComment(messages.antipattern_branch, stats.prNum)
  }

  var options = {
    url: baseURL + 'pulls/' + stats.prNum,
    json: true,
    headers: { 'User-Agent': 'request',
               'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
    }
  }

  function getTime (error, response, body) {
    if (error) return callback(error, 'Error in request on PR via number')
    // if a test pr is coming in from @RR
    var info
    if (!error && response.statusCode === 200 && pullreq.user.login === 'reporobot') {
      info = body
      stats.time = info.created_at.toLocaleString()
      // RR is PRing on behalf of:
      console.log(new Date(), 'PR ', stats.prNum, 'Reporobot Pull Request on behalf of ', stats.user)
      return getFile(stats.prNum)
    }

    if (!error && response.statusCode === 200 && pullreq.user.login !== 'reporobot') {
      info = body
      stats.time = info.created_at
      return getFile(stats.prNum)
    }

    callback(body)
  }

  request(options, getTime)

  function getFile (prNum) {
    var options = {
      url: baseURL + 'pulls/' + prNum + '/files',
      json: true,
      headers: {
        'User-Agent': 'request',
        'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
      }
    }

    request(options, function returnFiles (error, response, body) {
      if (error || body.length === 0) return callback(error, 'Error finding file in PR')

      if (!error && response.statusCode === 200) {
        if (body.length > 1) {
          console.log(new Date(), 'PR ', stats.prNum, 'MORE THAN ONE FILE ', stats.user)
          return writeComment(messages.multi_files, stats.prNum)
        }

        var prInfo = body[0]
        // TODO do empty files not have a patch property?
        if (prInfo === undefined || !prInfo.patch) {
          console.log(new Date(), 'PR ', stats.prNum, 'FILE IS EMPTY ', stats.user)
          return writeComment(messages.empty_file, stats.prNum)
        }

        return verifyFilename(prInfo)
      }
      // huh? why sending this back to function(err, message)?
      callback(body)
    })
  }

  function verifyFilename (prInfo) {
    var filename = prInfo.filename.toLowerCase()
    if (filename.match('contributors/add-' + stats.user.toLowerCase() + '.txt')) {
      console.log(new Date(), 'PR ', stats.prNum, 'Filename: MATCH ', stats.user)
      return verifyContent(prInfo)
    } else {
      return writeComment(messages.bad_filename, stats.prNum)
    }
  }

  function verifyContent (prInfo) {
    // pull out the actual pr content
    var patchArray = prInfo.patch.split('@@')
    var patch = patchArray.pop()
    // generate the expected content
    asciify(stats.user, { font: 'isometric2' }, function (err, res) {
      if (err) return callback(err, 'Error generating ascii art to test against')
      console.log(patch)
      console.log(res)
      if (patch !== stats.user) {
        stats.userArt = res
        console.log(new Date(), 'PR ', stats.prNum, 'Content: MATCH ', stats.user)
        return setTimeout(mergePR(stats.prNum), 5000)
      } else {
        return writeComment(messages.bad_ascii, stats.prNum)
      }
    })
  }

  function writeComment (message, prNum) {
    stats.user = stats.user || 'a skipped PR'
    console.log(new Date(), 'PR ' + prNum + ' Uh oh, writing comment for ' + stats.user)
    var options = {
      url: baseURL + 'issues/' + prNum + '/comments',
      headers: {
        'User-Agent': 'request',
        'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
      },
      json: {'body': message}
    }

    request.post(options, function doneWriteComment (error, response, body) {
      if (error) return callback(error, 'Error writing comment on PR')
      callback()
    })
  }

  function mergePR (prNum) {
    var tries = 0
    var limit = 25

    tryMerge()

    function tryMerge () {
      var message = 'Merging PR from @' + stats.user
      var options = {
        url: baseURL + 'pulls/' + prNum + '/merge',
        headers: {
          'User-Agent': 'request',
          'Authorization': 'token ' + process.env['REPOROBOT_TOKEN']
        },
        json: {'commit_message': message}
      }

      request.put(options, function doneMerge (error, response, body) {
        if (error) return callback(error, 'Error merging PR')
        if (response.statusCode !== 200) {
          console.log(new Date(), prNum, 'ERROR MERGING', response.statusCode, body.message)
          console.log(new Date(), prNum, 'TRYING AGAIN')
          if (tries <= limit) {
            tries++
            return setTimeout(tryMerge(prNum), 3000)
          } else {
            callback(null, new Date() + 'Could not merge after ' + limit + ' tries ' + prNum)
          }
        }
        if (!error && response.statusCode === 200) {
          console.log(new Date(), 'PR ', prNum, 'MERGED', stats.user)
          // add contributor to file and then rebuild page
          return addContributor(stats, callback)
        } else {
          callback(error, body)
        }
      })
    }
  }
}
<|endoftext|>


<commit_before>(function($) {

	//////////////////////////////////////////////////////////////////////////////////////////
	//																						//
	//					Begin Template engine. You can easily swap it.						//
	//																						//
	//////////////////////////////////////////////////////////////////////////////////////////

	// doT.js
	// 2011, Laura Doktorova, https://github.com/olado/doT
	//
	// doT.js is an open source component of http://bebedo.com
	// Licensed under the MIT license.
	//
	var doT = {
		version: '0.2.0',
		templateSettings: {
			evaluate:    /\{\{([\s\S]+?)\}\}/g,
			interpolate: /\{\{=([\s\S]+?)\}\}/g,
			encode:      /\{\{!([\s\S]+?)\}\}/g,
			use:         /\{\{#([\s\S]+?)\}\}/g,
			define:      /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,
			conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,
			iterate:     /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,
			varname: 'binding',
			strip: true,
			append: true,
			selfcontained: false
		},
		template: undefined, //fn, compile template
		compile:  undefined  //fn, for express
	};

	var global = (function(){ return this || (0,eval)('this'); }());

	//	spasquali@gmail.com : We don't want (need) these in the global.
	//
	if (typeof module !== 'undefined' && module.exports) {
		//module.exports = doT;
	} else if (typeof define === 'function' && define.amd) {
		//define(function(){return doT;});
	} else {
		//global.doT = doT;
	}

	function encodeHTMLSource() {
		var encodeHTMLRules = { "&": "&", "<": "<", ">": ">", '"': '"', "'": ''', "/": '/' },
			matchHTML = /&(?!\\w+;)|<|>|"|'|\//g;
		return function(code) {
			return code ? code.toString().replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : code;
		};
	}
	global.encodeHTML = encodeHTMLSource();

	var startend = {
		append: { start: "'+(",      end: ")+'",      startencode: "'+encodeHTML(" },
		split:  { start: "';out+=(", end: ");out+='", startencode: "';out+=encodeHTML("}
	}, skip = /$^/;

	function resolveDefs(c, block, def) {
		return ((typeof block === 'string') ? block : block.toString())
		.replace(c.define || skip, function(m, code, assign, value) {
			if (code.indexOf('def.') === 0) {
				code = code.substring(4);
			}
			if (!(code in def)) {
				if (assign === ':') {
					def[code]= value;
				} else {
					eval("def['"+code+"']=" + value);
				}
			}
			return '';
		})
		.replace(c.use || skip, function(m, code) {
			var v = eval(code);
			return v ? resolveDefs(c, v, def) : v;
		});
	}

	function unescape(code) {
		return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, ' ');
	}

	doT.template = function(tmpl, c, def) {
		c = c || doT.templateSettings;
		var cse = c.append ? startend.append : startend.split, str, needhtmlencode, sid=0, indv;

		if (c.use || c.define) {
			var olddef = global.def; global.def = def || {}; // workaround minifiers
			str = resolveDefs(c, tmpl, global.def);
			global.def = olddef;
		} else str = tmpl;

		str = ("var out='" + (c.strip ? str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g,' ')
					.replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,''): str)
			.replace(/'|\\/g, '\\$&')
			.replace(c.interpolate || skip, function(m, code) {
				return cse.start + unescape(code) + cse.end;
			})
			.replace(c.encode || skip, function(m, code) {
				needhtmlencode = true;
				return cse.startencode + unescape(code) + cse.end;
			})
			.replace(c.conditional || skip, function(m, elsecase, code) {
				return elsecase ?
					(code ? "';}else if(" + unescape(code) + "){out+='" : "';}else{out+='") :
					(code ? "';if(" + unescape(code) + "){out+='" : "';}out+='");
			})
			.replace(c.iterate || skip, function(m, iterate, vname, iname) {
				if (!iterate) return "';} } out+='";
				sid+=1; indv=iname || "i"+sid; iterate=unescape(iterate);
				return "';var arr"+sid+"="+iterate+";if(arr"+sid+"){var "+vname+","+indv+"=-1,l"+sid+"=arr"+sid+".length-1;while("+indv+"<l"+sid+"){"
					+vname+"=arr"+sid+"["+indv+"+=1];out+='";
			})
			.replace(c.evaluate || skip, function(m, code) {
				return "';" + unescape(code) + "out+='";
			})
			+ "';return out;")
			.replace(/\n/g, '\\n').replace(/\t/g, '\\t').replace(/\r/g, '\\r')
			.replace(/(\s|;|}|^|{)out\+='';/g, '$1').replace(/\+''/g, '')
			.replace(/(\s|;|}|^|{)out\+=''\+/g,'$1out+=');

		if (needhtmlencode && c.selfcontained) {
			str = "var encodeHTML=(" + encodeHTMLSource.toString() + "());" + str;
		}
		try {
			return new Function(c.varname, str);
		} catch (e) {
			if (typeof console !== 'undefined') console.log("Could not create a template function: " + str);
			throw e;
		}
	};

	doT.compile = function(tmpl, def) {
		return doT.template(tmpl, null, def);
	};

	//////////////////////////////////////////////////////////////////////////////////////////
	//																						//
	//									End Template engine.								//
	//																						//
	//////////////////////////////////////////////////////////////////////////////////////////

	//	Override jQuery#data,#removeData methods, watching for changes (two arguments, remove),
	//	updating template if changes occur. No
	//
	//	Normal #data behavior persists, with no modification, first.
	//
	//	Errors should be noisy if you don't properly bind a template, etc.
	//
	var _data 		= $.fn.data;
	var _removeData	= $.fn.removeData;

	var update	= function(args, _this, force) {

		var $target	= $(_this);

		if(force || args.length === 2 || $.isPlainObject(args[0])) {
			var boundTemplateId = $target.attr("data-template");
			if(boundTemplateId) {
				$target.html(doT.template($("#" + boundTemplateId).text())($target.data()));
			}
		}
	};

	$.fn.data = function() {
		var methRes	= _data.apply(this, arguments);
		update(arguments, this);
		return methRes;
	};

	$.fn.removeData = function() {
		var methRes	= _removeData.apply(this, arguments);
		update(arguments, this, 1);
		return methRes;
	};

	return $;

})(jQuery);
<commit_msg>added #replayData method, which forces template refresh.<commit_after>(function($) {

	//////////////////////////////////////////////////////////////////////////////////////////
	//																						//
	//					Begin Template engine. You can easily swap it.						//
	//																						//
	//////////////////////////////////////////////////////////////////////////////////////////

	// doT.js
	// 2011, Laura Doktorova, https://github.com/olado/doT
	//
	// doT.js is an open source component of http://bebedo.com
	// Licensed under the MIT license.
	//
	var doT = {
		version: '0.2.0',
		templateSettings: {
			evaluate:    /\{\{([\s\S]+?)\}\}/g,
			interpolate: /\{\{=([\s\S]+?)\}\}/g,
			encode:      /\{\{!([\s\S]+?)\}\}/g,
			use:         /\{\{#([\s\S]+?)\}\}/g,
			define:      /\{\{##\s*([\w\.$]+)\s*(\:|=)([\s\S]+?)#\}\}/g,
			conditional: /\{\{\?(\?)?\s*([\s\S]*?)\s*\}\}/g,
			iterate:     /\{\{~\s*(?:\}\}|([\s\S]+?)\s*\:\s*([\w$]+)\s*(?:\:\s*([\w$]+))?\s*\}\})/g,
			varname: 'binding',
			strip: true,
			append: true,
			selfcontained: false
		},
		template: undefined, //fn, compile template
		compile:  undefined  //fn, for express
	};

	var global = (function(){ return this || (0,eval)('this'); }());

	//	spasquali@gmail.com : We don't want (need) these in the global.
	//
	if (typeof module !== 'undefined' && module.exports) {
		//module.exports = doT;
	} else if (typeof define === 'function' && define.amd) {
		//define(function(){return doT;});
	} else {
		//global.doT = doT;
	}

	function encodeHTMLSource() {
		var encodeHTMLRules = { "&": "&", "<": "<", ">": ">", '"': '"', "'": ''', "/": '/' },
			matchHTML = /&(?!\\w+;)|<|>|"|'|\//g;
		return function(code) {
			return code ? code.toString().replace(matchHTML, function(m) {return encodeHTMLRules[m] || m;}) : code;
		};
	}
	global.encodeHTML = encodeHTMLSource();

	var startend = {
		append: { start: "'+(",      end: ")+'",      startencode: "'+encodeHTML(" },
		split:  { start: "';out+=(", end: ");out+='", startencode: "';out+=encodeHTML("}
	}, skip = /$^/;

	function resolveDefs(c, block, def) {
		return ((typeof block === 'string') ? block : block.toString())
		.replace(c.define || skip, function(m, code, assign, value) {
			if (code.indexOf('def.') === 0) {
				code = code.substring(4);
			}
			if (!(code in def)) {
				if (assign === ':') {
					def[code]= value;
				} else {
					eval("def['"+code+"']=" + value);
				}
			}
			return '';
		})
		.replace(c.use || skip, function(m, code) {
			var v = eval(code);
			return v ? resolveDefs(c, v, def) : v;
		});
	}

	function unescape(code) {
		return code.replace(/\\('|\\)/g, "$1").replace(/[\r\t\n]/g, ' ');
	}

	doT.template = function(tmpl, c, def) {
		c = c || doT.templateSettings;
		var cse = c.append ? startend.append : startend.split, str, needhtmlencode, sid=0, indv;

		if (c.use || c.define) {
			var olddef = global.def; global.def = def || {}; // workaround minifiers
			str = resolveDefs(c, tmpl, global.def);
			global.def = olddef;
		} else str = tmpl;

		str = ("var out='" + (c.strip ? str.replace(/(^|\r|\n)\t* +| +\t*(\r|\n|$)/g,' ')
					.replace(/\r|\n|\t|\/\*[\s\S]*?\*\//g,''): str)
			.replace(/'|\\/g, '\\$&')
			.replace(c.interpolate || skip, function(m, code) {
				return cse.start + unescape(code) + cse.end;
			})
			.replace(c.encode || skip, function(m, code) {
				needhtmlencode = true;
				return cse.startencode + unescape(code) + cse.end;
			})
			.replace(c.conditional || skip, function(m, elsecase, code) {
				return elsecase ?
					(code ? "';}else if(" + unescape(code) + "){out+='" : "';}else{out+='") :
					(code ? "';if(" + unescape(code) + "){out+='" : "';}out+='");
			})
			.replace(c.iterate || skip, function(m, iterate, vname, iname) {
				if (!iterate) return "';} } out+='";
				sid+=1; indv=iname || "i"+sid; iterate=unescape(iterate);
				return "';var arr"+sid+"="+iterate+";if(arr"+sid+"){var "+vname+","+indv+"=-1,l"+sid+"=arr"+sid+".length-1;while("+indv+"<l"+sid+"){"
					+vname+"=arr"+sid+"["+indv+"+=1];out+='";
			})
			.replace(c.evaluate || skip, function(m, code) {
				return "';" + unescape(code) + "out+='";
			})
			+ "';return out;")
			.replace(/\n/g, '\\n').replace(/\t/g, '\\t').replace(/\r/g, '\\r')
			.replace(/(\s|;|}|^|{)out\+='';/g, '$1').replace(/\+''/g, '')
			.replace(/(\s|;|}|^|{)out\+=''\+/g,'$1out+=');

		if (needhtmlencode && c.selfcontained) {
			str = "var encodeHTML=(" + encodeHTMLSource.toString() + "());" + str;
		}
		try {
			return new Function(c.varname, str);
		} catch (e) {
			if (typeof console !== 'undefined') console.log("Could not create a template function: " + str);
			throw e;
		}
	};

	doT.compile = function(tmpl, def) {
		return doT.template(tmpl, null, def);
	};

	//////////////////////////////////////////////////////////////////////////////////////////
	//																						//
	//									End Template engine.								//
	//																						//
	//////////////////////////////////////////////////////////////////////////////////////////

	//	Override jQuery#data,#removeData methods, watching for changes (two arguments, remove),
	//	updating template if changes occur. No
	//
	//	Normal #data behavior persists, with no modification, first.
	//
	//	Errors should be noisy if you don't properly bind a template, etc.
	//
	var _data 		= $.fn.data;
	var _removeData	= $.fn.removeData;

	var update	= function(args, _this, force) {

		var $target	= $(_this);

		if(force || args.length === 2 || $.isPlainObject(args[0])) {
			var boundTemplateId = $target.attr("data-template");
			if(boundTemplateId) {
				$target.html(doT.template($("#" + boundTemplateId).text())($target.data()));
			}
		}
	};

	$.fn.data = function() {
		var methRes	= _data.apply(this, arguments);
		update(arguments, this);
		return methRes;
	};

	$.fn.removeData = function() {
		var methRes	= _removeData.apply(this, arguments);
		update(arguments, this, 1);
		return methRes;
	};

	$.fn.replayData = function() {
		update(null, this, 1);
		return this;
	};

	return $;

})(jQuery);
<|endoftext|>


<commit_before>var fs = require('fs');
var zlib = require('zlib');
var crc = require('crc').crc32;

function positiveNumberToBytes(number, bytes) {
  bytes = bytes || 4;
  var result = '';
  for(var i = 0; i < bytes; i++){
    result = String.fromCharCode(number % 256) + result;
    number = number / 256 | 0;
  }
  return result;
}

function chunk(type, data) {
  var length = positiveNumberToBytes(data.length, 4);
  return Buffer.concat([
      new Buffer(length, 'binary'),
      new Buffer(type + data, 'binary'),
      new Buffer(positiveNumberToBytes(+('0x' + crc(type + data)), 4), 'binary')
  ]);
}

function compress(payload, callback) {

  while(payload.length % 3) {
    payload += ' ';
  }

  var width = Math.ceil(Math.sqrt(payload.length / 3));
  var height = width;
  var padding = width * height - payload.length / 3;

  while(padding --> 0) {
    payload += '   ';
  }

  var fileSignature = new Buffer('\x89\x50\x4e\x47\x0d\x0a\x1a\x0a', 'binary');
  var IHDRChunk = chunk('IHDR',
    positiveNumberToBytes(width, 4) +
    positiveNumberToBytes(height, 4) +
    positiveNumberToBytes(8, 1) +
    positiveNumberToBytes(2, 1) +
    positiveNumberToBytes(0, 1) +
    positiveNumberToBytes(0, 1) +
    positiveNumberToBytes(0, 1));
  var html = '<!DOCTYPE html><meta charset="utf-8">' +
    '<title>Ninjadev</title>' +
    '' +
    '
' +
    '
Inakuwa Oasis
' +
    '
by
' +
    '
Ninjadev
' +
    '
The inaugural demo of our new demo tool \'nin\' (open source!).
' +
    '
Presented at Solskogen 2014.
' +
    '<button onclick=start() class=loading style="position:relative;font-size:40px;color:white;padding:40px;margin-left:-300px;border:0;outline:0;" id=start-button disabled>Loading...</button>' +
    '
' +
    '<canvas class=hide height='+ height + ' width=' + width + '></canvas> 0) {
    payload += '   ';
  }

  var fileSignature = new Buffer('\x89\x50\x4e\x47\x0d\x0a\x1a\x0a', 'binary');
  var IHDRChunk = chunk('IHDR',
    positiveNumberToBytes(width, 4) +
    positiveNumberToBytes(height, 4) +
    positiveNumberToBytes(8, 1) +
    positiveNumberToBytes(2, 1) +
    positiveNumberToBytes(0, 1) +
    positiveNumberToBytes(0, 1) +
    positiveNumberToBytes(0, 1));
  var html = '<!DOCTYPE html><meta charset="utf-8">' +
    '<title>Ninjadev</title>' +
    '' +
    '
' +
    '
Inakuwa Oasis
' +
    '
by
' +
    '
Ninjadev
' +
    '
The inaugural demo of our new demo tool \'nin\' (open source!).
' +
    '
Presented at Solskogen 2014.
' +
    '<button onclick=start() class=loading style="position:relative;font-size:40px;color:white;padding:40px;margin-left:-300px;border:0;outline:0;" id=start-button disabled>Loading...</button>' +
    '
' +
    '<canvas class=hide height='+ height + ' width=' + width + '></canvas>


<commit_before>/*jshint esversion: 6 */
var AWS = require("aws-sdk");

exports.handler = (event, context, callback) => {
    console.log(event);
    callback(null, 'Hello from Lambda');
};
<commit_msg>Split IP string and log<commit_after>/*jshint esversion: 6 */
var AWS = require("aws-sdk");

exports.handler = (event, context, callback) => {
    console.log(event);
    callback(null, 'Hello from Lambda');
    console.log(event.sourceIP.split(',', 1)[0])
};
<|endoftext|>