<commit_before>(function($) {

  function MapService() {
    this.map = null;
    this.inputs = new Array();
  }

  MapService.prototype.initMap = function(container) {
    if (this.map) {
      return;
    }

    this.map = new google.maps.Map(container, {
      center: new google.maps.LatLng(52.5167, 13.3833), // Berlin for the win!! :)
      zoom:   11
    });
  };

  MapService.prototype.addLocationInput = function(inputElement, onChangedCallback) {
    if (!this.map || !inputElement || !onChangedCallback) {
      return;
    }

    var input = new google.maps.places.Autocomplete(inputElement, { types: ['geocode'] });
    input.marker = null;
    this.inputs.push(input);

    var ref = this;

    google.maps.event.addListener(input, 'place_changed', function() {
      ref.onLocationInputChanged(input, onChangedCallback);
    });
  };

  MapService.prototype.onLocationInputChanged = function(input, callback) {
    if (!input.getPlace() || !input.getPlace().geometry) {
      if (input.marker) {
        this.removeMarker(input.marker);
        input.marker = null;
      }
      return;
    }

    var position = input.getPlace().geometry.location;

    if (input.marker) {
      input.marker.setPosition(position);
    } else {
      input.marker = this.createMarker(position);
    }

    callback();
  };

  MapService.prototype.createMarker = function(latLng) {
    if (!this.map) {
      return;
    }

    return new google.maps.Marker({
      position: latLng,
      map:      this.map
    });
  };

  MapService.prototype.removeMarker = function(marker) {
    if (!this.map || !marker) {
      return;
    }

    marker.setMap(null);
  };

  MapService.prototype.getMarkerPosition = function(index) {
    if (!this.map || index < 0 || index > this.inputs.length - 1) {
      return null;
    }

    var marker = this.inputs[index].marker;
    return marker ? marker.getPosition() : null;
  };

  MapService.prototype.panToMarkers = function() {
    if (!this.map) {
      return null;
    }

    var sw = null, ne = null;

    for (var i = 0; i < this.inputs.length; ++i) {
      var position = this.getMarkerPosition(i);

      if (! position) {
        continue;
      }

      if (sw === null) {
        sw = position;
      } else {
        sw = new google.maps.LatLng(Math.min(sw.lat(), position.lat()),
                                    Math.min(sw.lng(), position.lng()));
      }

      if (ne === null) {
        ne = position;
      } else {
        ne = new google.maps.LatLng(Math.max(ne.lat(), position.lat()),
                                    Math.max(ne.lng(), position.lng()));
      }
    }

    if (sw === null || ne === null) {
      return;
    }

    if (sw.lat() === ne.lat() && sw.lng() === ne.lng()) {
      this.map.panTo(sw);
      this.map.setZoom(11);
    } else {
      this.map.panToBounds(new google.maps.LatLngBounds(sw, ne));
    }
  };

  MapService.prototype.addRect = function(rect) {
    rect.setMap(this.map);
  };

  function DirectionService() {
    this.service = new google.maps.DirectionsService();
  }

  DirectionService.prototype.getTravelDuration = function(from, to, callback) {
    var departure = new Date();
    departure.setHours(7);

    var ref = this;

    this.service.route({
      origin:         from,
      destination:    to,
      travelMode:     google.maps.TravelMode.TRANSIT,
      transitOptions: { departureTime: departure }
    }, function(result, status) {
      if (status === 'OVER_QUERY_LIMIT') {
        setTimeout(function() {
          ref.getTravelDuration(from, to, callback);
        }, 1000);
      } else if (status === 'OK') {
        callback(result.routes[0].legs[0].duration.value);
      }
    });
  };

  function RectService(mapService) {
    this.mapService = mapService;
    this.rects = new Array();
  }

  RectService.prototype.removeAllRects = function() {
    for (var i = 0; i < this.rects.length; ++i) {
      this.rects[i].setMap(null);
    }

    this.rects = new Array();
  };

  RectService.prototype.addRect = function(position, size, duration1, duration2) {
    var sw = new google.maps.LatLng(position.lat() - deltaKmToDeltaLatitude(size / 2.0), position.lng() - deltaKmToDeltaLongitude(size / 2.0, position.lat()));
    var ne = new google.maps.LatLng(position.lat() + deltaKmToDeltaLatitude(size / 2.0), position.lng() + deltaKmToDeltaLongitude(size / 2.0, position.lat()));

    var red = Math.round(Math.min(duration1 + duration2, 7200) / 7200 * 255);
    var green = 255 - red;
    var colorString = '#' + (red < 16 ? '0' : '') + red.toString(16).toUpperCase() + (green < 16 ? '0' : '') + green.toString(16).toUpperCase() + '00';

    var rect = new google.maps.Rectangle({
      bounds: new google.maps.LatLngBounds(sw, ne),
      strokeColor: colorString,
      strokeOpacity: 0.5,
      strokeWeight: 1,
      fillColor: colorString,
      fillOpacity: 0.2
    });

    this.mapService.addRect(rect);
    this.rects.push(rect);
  };

  function SpiralingGridWalker(callback) {
    this.callback = callback;
    this.loopIndex = 0;
    this.cellIndex = 0;
  }

  SpiralingGridWalker.prototype.step = function() {
    var x = null, y = null;

    if (this.loopIndex === 0) {
      x = 0;
      y = 0;
    } else {
      var edgeLength = 2 * this.loopIndex + 1;

      if (this.cellIndex < edgeLength) { // Left border
        x = -this.loopIndex;
        y = this.loopIndex - this.cellIndex;
      } else if (this.cellIndex < 2 * edgeLength - 1) { // Bottom border
        x = -this.loopIndex + this.cellIndex - (edgeLength - 1);
        y = -this.loopIndex;
      } else if (this.cellIndex < 3 * edgeLength -2) { // Right border
        x = this.loopIndex;
        y = -this.loopIndex + this.cellIndex - (2 * edgeLength - 2);
      } else { // Top border
        x = this.loopIndex - this.cellIndex + (3 * edgeLength - 3);
        y = this.loopIndex;
      }
    }

    this.callback(x, y);

    if (this.loopFinished()) {
      this.loopIndex += 1;
      this.cellIndex = 0;
    } else {
      this.cellIndex += 1;
    }
  };

  SpiralingGridWalker.prototype.loopFinished = function() {
    return (this.loopIndex === 0 || this.cellIndex === 8 * this.loopIndex - 1);
  };

  SpiralingGridWalker.prototype.getLoopIndex = function() {
    return this.loopIndex;
  };

  var mapService = new MapService();
  var directionService = new DirectionService();
  var rectService = new RectService(mapService)

  var numRequests = 0;
  var startOfFirstRequest = null;
  var startOfLastRequest = null;
  var durationOfLastRequest = 0;

  const GRID_SIZE = 20;
  const GRID_SPACING = 1;

  $(document).ready(function() {
    mapService.initMap(document.getElementById('map'));
    mapService.addLocationInput(document.getElementById('location1'), onLocationChanged);
    mapService.addLocationInput(document.getElementById('location2'), onLocationChanged);
  });

  function onLocationChanged() {
    mapService.panToMarkers();

    var destination1 = mapService.getMarkerPosition(0);
    var destination2 = mapService.getMarkerPosition(1);

    if (destination1 && destination2) {
      calculateDirections(destination1, destination2);
    }
  }

  function calculateDirections(destination1, destination2) {
    var midPoint = calculateMidPoint(destination1, destination2);

    numRequests = 0;

    var walker = new SpiralingGridWalker(function(x, y) {
      var lat = midPoint.lat() + deltaKmToDeltaLatitude(GRID_SPACING * y);
      var lng = midPoint.lng() + deltaKmToDeltaLongitude(GRID_SPACING * x, lat);
      var position = new google.maps.LatLng(lat, lng);

      if (!startOfFirstRequest) {
        startOfFirstRequest = new Date();
      }

      startOfLastRequest = new Date();

      $('.progressBar').css('margin-left', '-100%');

      directionService.getTravelDuration(position, destination1, function(duration1) {
        $('.progressBar').css('margin-left', '-50%');

        directionService.getTravelDuration(position, destination2, function(duration2) {
          var endOfLastRequest = new Date();
          durationOfLastRequest = endOfLastRequest.getTime() - startOfLastRequest.getTime();
          ++numRequests;

          $('.progressBar').css('margin-left', '0%');

          rectService.addRect(position, GRID_SPACING, duration1, duration2);

          if (walker.getLoopIndex() < 9) {
            walker.step();
          }
        });
      });
    });

    walker.step();
  }

  function calculateMidPoint(position1, position2) {
    return new google.maps.LatLng((position1.lat() + position2.lat()) / 2.0,
                                  (position1.lng() + position2.lng()) / 2.0);
  }

  function deltaKmToDeltaLatitude(km) {
    // 1° lat = 110.54km => 1km = 1° / 110.54
    return km / 110.54;
  }

  function deltaKmToDeltaLongitude(km, lat) {
    // 1° lng = 111.32km * cos(lat) => 1km = 1° / 111.32 / cos(lat)
    return km / 111.32 / Math.cos(lat / 180 * Math.PI);
  }

})(jQuery);
<commit_msg>Removed unneeded time measurement<commit_after>(function($) {

  function MapService() {
    this.map = null;
    this.inputs = new Array();
  }

  MapService.prototype.initMap = function(container) {
    if (this.map) {
      return;
    }

    this.map = new google.maps.Map(container, {
      center: new google.maps.LatLng(52.5167, 13.3833), // Berlin for the win!! :)
      zoom:   11
    });
  };

  MapService.prototype.addLocationInput = function(inputElement, onChangedCallback) {
    if (!this.map || !inputElement || !onChangedCallback) {
      return;
    }

    var input = new google.maps.places.Autocomplete(inputElement, { types: ['geocode'] });
    input.marker = null;
    this.inputs.push(input);

    var ref = this;

    google.maps.event.addListener(input, 'place_changed', function() {
      ref.onLocationInputChanged(input, onChangedCallback);
    });
  };

  MapService.prototype.onLocationInputChanged = function(input, callback) {
    if (!input.getPlace() || !input.getPlace().geometry) {
      if (input.marker) {
        this.removeMarker(input.marker);
        input.marker = null;
      }
      return;
    }

    var position = input.getPlace().geometry.location;

    if (input.marker) {
      input.marker.setPosition(position);
    } else {
      input.marker = this.createMarker(position);
    }

    callback();
  };

  MapService.prototype.createMarker = function(latLng) {
    if (!this.map) {
      return;
    }

    return new google.maps.Marker({
      position: latLng,
      map:      this.map
    });
  };

  MapService.prototype.removeMarker = function(marker) {
    if (!this.map || !marker) {
      return;
    }

    marker.setMap(null);
  };

  MapService.prototype.getMarkerPosition = function(index) {
    if (!this.map || index < 0 || index > this.inputs.length - 1) {
      return null;
    }

    var marker = this.inputs[index].marker;
    return marker ? marker.getPosition() : null;
  };

  MapService.prototype.panToMarkers = function() {
    if (!this.map) {
      return null;
    }

    var sw = null, ne = null;

    for (var i = 0; i < this.inputs.length; ++i) {
      var position = this.getMarkerPosition(i);

      if (! position) {
        continue;
      }

      if (sw === null) {
        sw = position;
      } else {
        sw = new google.maps.LatLng(Math.min(sw.lat(), position.lat()),
                                    Math.min(sw.lng(), position.lng()));
      }

      if (ne === null) {
        ne = position;
      } else {
        ne = new google.maps.LatLng(Math.max(ne.lat(), position.lat()),
                                    Math.max(ne.lng(), position.lng()));
      }
    }

    if (sw === null || ne === null) {
      return;
    }

    if (sw.lat() === ne.lat() && sw.lng() === ne.lng()) {
      this.map.panTo(sw);
      this.map.setZoom(11);
    } else {
      this.map.panToBounds(new google.maps.LatLngBounds(sw, ne));
    }
  };

  MapService.prototype.addRect = function(rect) {
    rect.setMap(this.map);
  };

  function DirectionService() {
    this.service = new google.maps.DirectionsService();
  }

  DirectionService.prototype.getTravelDuration = function(from, to, callback) {
    var departure = new Date();
    departure.setHours(7);

    var ref = this;

    this.service.route({
      origin:         from,
      destination:    to,
      travelMode:     google.maps.TravelMode.TRANSIT,
      transitOptions: { departureTime: departure }
    }, function(result, status) {
      if (status === 'OVER_QUERY_LIMIT') {
        setTimeout(function() {
          ref.getTravelDuration(from, to, callback);
        }, 1000);
      } else if (status === 'OK') {
        callback(result.routes[0].legs[0].duration.value);
      }
    });
  };

  function RectService(mapService) {
    this.mapService = mapService;
    this.rects = new Array();
  }

  RectService.prototype.removeAllRects = function() {
    for (var i = 0; i < this.rects.length; ++i) {
      this.rects[i].setMap(null);
    }

    this.rects = new Array();
  };

  RectService.prototype.addRect = function(position, size, duration1, duration2) {
    var sw = new google.maps.LatLng(position.lat() - deltaKmToDeltaLatitude(size / 2.0), position.lng() - deltaKmToDeltaLongitude(size / 2.0, position.lat()));
    var ne = new google.maps.LatLng(position.lat() + deltaKmToDeltaLatitude(size / 2.0), position.lng() + deltaKmToDeltaLongitude(size / 2.0, position.lat()));

    var red = Math.round(Math.min(duration1 + duration2, 7200) / 7200 * 255);
    var green = 255 - red;
    var colorString = '#' + (red < 16 ? '0' : '') + red.toString(16).toUpperCase() + (green < 16 ? '0' : '') + green.toString(16).toUpperCase() + '00';

    var rect = new google.maps.Rectangle({
      bounds: new google.maps.LatLngBounds(sw, ne),
      strokeColor: colorString,
      strokeOpacity: 0.5,
      strokeWeight: 1,
      fillColor: colorString,
      fillOpacity: 0.2
    });

    this.mapService.addRect(rect);
    this.rects.push(rect);
  };

  function SpiralingGridWalker(callback) {
    this.callback = callback;
    this.loopIndex = 0;
    this.cellIndex = 0;
  }

  SpiralingGridWalker.prototype.step = function() {
    var x = null, y = null;

    if (this.loopIndex === 0) {
      x = 0;
      y = 0;
    } else {
      var edgeLength = 2 * this.loopIndex + 1;

      if (this.cellIndex < edgeLength) { // Left border
        x = -this.loopIndex;
        y = this.loopIndex - this.cellIndex;
      } else if (this.cellIndex < 2 * edgeLength - 1) { // Bottom border
        x = -this.loopIndex + this.cellIndex - (edgeLength - 1);
        y = -this.loopIndex;
      } else if (this.cellIndex < 3 * edgeLength -2) { // Right border
        x = this.loopIndex;
        y = -this.loopIndex + this.cellIndex - (2 * edgeLength - 2);
      } else { // Top border
        x = this.loopIndex - this.cellIndex + (3 * edgeLength - 3);
        y = this.loopIndex;
      }
    }

    this.callback(x, y);

    if (this.loopFinished()) {
      this.loopIndex += 1;
      this.cellIndex = 0;
    } else {
      this.cellIndex += 1;
    }
  };

  SpiralingGridWalker.prototype.loopFinished = function() {
    return (this.loopIndex === 0 || this.cellIndex === 8 * this.loopIndex - 1);
  };

  SpiralingGridWalker.prototype.getLoopIndex = function() {
    return this.loopIndex;
  };

  var mapService = new MapService();
  var directionService = new DirectionService();
  var rectService = new RectService(mapService)

  const GRID_SIZE = 20;
  const GRID_SPACING = 1;

  $(document).ready(function() {
    mapService.initMap(document.getElementById('map'));
    mapService.addLocationInput(document.getElementById('location1'), onLocationChanged);
    mapService.addLocationInput(document.getElementById('location2'), onLocationChanged);
  });

  function onLocationChanged() {
    mapService.panToMarkers();

    var destination1 = mapService.getMarkerPosition(0);
    var destination2 = mapService.getMarkerPosition(1);

    if (destination1 && destination2) {
      calculateDirections(destination1, destination2);
    }
  }

  function calculateDirections(destination1, destination2) {
    var midPoint = calculateMidPoint(destination1, destination2);

    var walker = new SpiralingGridWalker(function(x, y) {
      var lat = midPoint.lat() + deltaKmToDeltaLatitude(GRID_SPACING * y);
      var lng = midPoint.lng() + deltaKmToDeltaLongitude(GRID_SPACING * x, lat);
      var position = new google.maps.LatLng(lat, lng);

      $('.progressBar').css('margin-left', '-100%');

      directionService.getTravelDuration(position, destination1, function(duration1) {
        $('.progressBar').css('margin-left', '-50%');

        directionService.getTravelDuration(position, destination2, function(duration2) {
          $('.progressBar').css('margin-left', '0%');

          rectService.addRect(position, GRID_SPACING, duration1, duration2);

          if (walker.getLoopIndex() < 9) {
            walker.step();
          }
        });
      });
    });

    walker.step();
  }

  function calculateMidPoint(position1, position2) {
    return new google.maps.LatLng((position1.lat() + position2.lat()) / 2.0,
                                  (position1.lng() + position2.lng()) / 2.0);
  }

  function deltaKmToDeltaLatitude(km) {
    // 1° lat = 110.54km => 1km = 1° / 110.54
    return km / 110.54;
  }

  function deltaKmToDeltaLongitude(km, lat) {
    // 1° lng = 111.32km * cos(lat) => 1km = 1° / 111.32 / cos(lat)
    return km / 111.32 / Math.cos(lat / 180 * Math.PI);
  }

})(jQuery);
<|endoftext|>


<commit_before>'use strict';

var Node = require('../node');

var TYPE = 'gravity';

var PARAMS = {
    source: Node.PARAM.NODE(Node.GEOMETRY.ANY), // "populated places"
    target: Node.PARAM.NODE(Node.GEOMETRY.POINT), // "malls"
    weightColunn: Node.PARAM.STRING(),
    weightThreshold: Node.PARAM.NULLABLE(Node.PARAM.NUMBER()),
    popColumn: Node.PARAM.STRING(),
    maxDistance: Node.PARAM.NUMBER(), // meters
    targetID: Node.PARAM.NUMBER() // the "mall" to be studied
};

var Gravity = Node.create(TYPE, PARAMS, {cache: true, version: 1});

module.exports = Gravity;
module.exports.TYPE = TYPE;
module.exports.PARAMS = PARAMS;

var gravityTemplate = Node.template([
    'WITH ',
    ' raw_s as({{=it.sourceQuery}}),',
    ' raw_t as({{=it.targetQuery}})',
    ' s as(',
        'SELECT',
        ' array_agg(cartodb_id::bigint) as id',
        ' array_agg(the_geom) as g,',
        ' array_agg(coalesce({{=it.p}},0)::numeric) as p',
        ' FROM raw_s',
    '),',
    ' t as(',
        'SELECT',
        ' array_agg(cartodb_id::bigint) as id',
        ' array_agg(the_geom) as g,',
        ' array_agg(coalesce({{=it.w}},0)::numeric) as p',
        ' FROM raw_t',
    ')',
    'SELECT ',
    ' g.source_id as cartodb_id,',
    ' g.the_geom,',
    ' ST_transform(g.the_geom, 3857) as the_geom_webmercator,',
    ' g.h as patronage_prob,',
    ' g.hpop patronaging_pop',
    ' g.dist as dist_to_target ',
    'FROM ',
    ' t,',
    ' s,',
    ' CDB_Gravity(t.id, t.g, t.w, s.id, s.g, s.p,',
    '  {{=it.targetID}}, {{=it.r}}, {{=it.wt}}) g'
].join('\n'));

Gravity.prototype.sql = function(){
    return gravityTemplate({
        sourceQuery: this.source.getQuery(),
        targetQuery: this.target.getQuery(),
        targetID: this.targetID,
        w: this.weightColunn,
        wt: this.weightThreshold,
        p: this.popColumn,
        r: this.maxDistance
    });
};
<commit_msg>fixed missed commas and params names<commit_after>'use strict';

var Node = require('../node');

var TYPE = 'gravity';

var PARAMS = {
    source: Node.PARAM.NODE(Node.GEOMETRY.ANY), // "populated places"
    target: Node.PARAM.NODE(Node.GEOMETRY.POINT), // "malls"
    weight_column: Node.PARAM.STRING(),
    weight_threshold: Node.PARAM.NULLABLE(Node.PARAM.NUMBER()),
    pop_column: Node.PARAM.STRING(),
    max_distance: Node.PARAM.NUMBER(), // meters
    target_id: Node.PARAM.NUMBER() // the "mall" to be studied
};

var Gravity = Node.create(TYPE, PARAMS, {cache: true, version: 1});

module.exports = Gravity;
module.exports.TYPE = TYPE;
module.exports.PARAMS = PARAMS;

var gravityTemplate = Node.template([
    'WITH ',
    ' raw_s as({{=it.sourceQuery}}),',
    ' raw_t as({{=it.targetQuery}}),',
    ' s as(',
        'SELECT',
        ' array_agg(cartodb_id::bigint) as id,',
        ' array_agg(the_geom) as g,',
        ' array_agg(coalesce({{=it.p}},0)::numeric) as p',
        ' FROM raw_s',
    '),',
    ' t as(',
        'SELECT',
        ' array_agg(cartodb_id::bigint) as id,',
        ' array_agg(the_geom) as g,',
        ' array_agg(coalesce({{=it.w}},0)::numeric) as p',
        ' FROM raw_t',
    ')',
    'SELECT ',
    ' g.source_id as cartodb_id,',
    ' g.the_geom,',
    ' ST_transform(g.the_geom, 3857) as the_geom_webmercator,',
    ' g.h as patronage_prob,',
    ' g.hpop patronaging_pop,',
    ' g.dist as dist_to_target ',
    'FROM ',
    ' t,',
    ' s,',
    ' CDB_Gravity(t.id, t.g, t.w, s.id, s.g, s.p,',
    '  {{=it.targetID}}, {{=it.r}}, {{=it.wt}}) g'
].join('\n'));

Gravity.prototype.sql = function(){
    return gravityTemplate({
        sourceQuery: this.source.getQuery(),
        targetQuery: this.target.getQuery(),
        targetID: this.target_id,
        w: this.weight_column,
        wt: this.weight_threshold,
        p: this.pop_column,
        r: this.max_distance
    });
};
<|endoftext|>


<commit_before>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

module('Path Curves');

test('path.curves Synchronisation', function() {
	var path = new Path();

	path.add(new Point(0, 100));
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } }", "path.segments: path.add(new Point(0, 100));");
	equals(path.curves.toString(), "", "path.curves: path.add(new Point(0, 100));");
	path.add(new Point(100, 100));
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 100, y: 100 } }", "path.segments: path.add(new Point(100, 100));");
	equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, point2: { x: 100, y: 100 } }", "path.curves: path.add(new Point(100, 100));");
	path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } },{ point: { x: 100, y: 100 } }", "path.segments: path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});");
	equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } }", "path.curves: path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});");
	path.closed = true;
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } },{ point: { x: 100, y: 100 } }", "path.segments: path.closed = true;");
	equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }", "path.curves: path.closed = true;");
	path.removeSegments(2, 3);
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } }", "path.segments: path.removeSegments(2, 3);");
	equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 0, y: 100 } }", "path.curves: path.removeSegments(2, 3);");
	path.add(new Point(100, 100));
	path.removeSegments(1, 2);
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 100, y: 100 } }", "path.segments: path.add(new Point(100, 100));\npath.removeSegments(1, 2);");
	equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }", "path.curves: path.add(new Point(100, 100));\npath.removeSegments(1, 2);");

	// Transform the path, and the curves length should be invalidated (first, force-cache the first segment's length by accessing it
	path.curves[0].length;
	ok(path.curves[0]._length, 'Curve length does not appear to be cached');
	path.scale(2, [0, 0]);
	equals(path.curves[0].length, 200, 'Curve length should be updated when path is transformed');
});

test('path.flatten(maxDistance)', function() {
	var path = new Path.Circle(new Size(80, 50), 35);

	// Convert its curves to points, with a max distance of 20:
	path.flatten(20);

	equals(function() {
		return path.lastSegment.point.equals(path.firstSegment.point);
	}, false, 'The points of the last and first segments should not be the same.');

	equals(function() {
		return path.lastSegment.point.toString() != path.segments[path.segments.length - 2].point.toString();
	}, true, 'The points of the last and before last segments should not be so close, that calling toString on them returns the same string value.');
});
<commit_msg>Tests: add curve tests, of which one currently fails.<commit_after>/*
 * Paper.js
 *
 * This file is part of Paper.js, a JavaScript Vector Graphics Library,
 * based on Scriptographer.org and designed to be largely API compatible.
 * http://paperjs.org/
 * http://scriptographer.org/
 *
 * Copyright (c) 2011, Juerg Lehni & Jonathan Puckey
 * http://lehni.org/ & http://jonathanpuckey.com/
 *
 * Distributed under the MIT license. See LICENSE file for details.
 *
 * All rights reserved.
 */

module('Path Curves');

test('path.curves Synchronisation', function() {
	var path = new Path();

	path.add(new Point(0, 100));
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } }", "path.segments: path.add(new Point(0, 100));");
	equals(path.curves.toString(), "", "path.curves: path.add(new Point(0, 100));");
	path.add(new Point(100, 100));
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 100, y: 100 } }", "path.segments: path.add(new Point(100, 100));");
	equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, point2: { x: 100, y: 100 } }", "path.curves: path.add(new Point(100, 100));");
	path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } },{ point: { x: 100, y: 100 } }", "path.segments: path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});");
	equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } }", "path.curves: path.insert(1, {point:[50, 0], handleIn:[-25, 0], handleOut:[25, 0]});");
	path.closed = true;
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } },{ point: { x: 100, y: 100 } }", "path.segments: path.closed = true;");
	equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }", "path.curves: path.closed = true;");
	path.removeSegments(2, 3);
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 50, y: 0 }, handleIn: { x: -25, y: 0 }, handleOut: { x: 25, y: 0 } }", "path.segments: path.removeSegments(2, 3);");
	equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, handle2: { x: -25, y: 0 }, point2: { x: 50, y: 0 } },{ point1: { x: 50, y: 0 }, handle1: { x: 25, y: 0 }, point2: { x: 0, y: 100 } }", "path.curves: path.removeSegments(2, 3);");
	path.add(new Point(100, 100));
	path.removeSegments(1, 2);
	equals(path.segments.toString(), "{ point: { x: 0, y: 100 } },{ point: { x: 100, y: 100 } }", "path.segments: path.add(new Point(100, 100));\npath.removeSegments(1, 2);");
	equals(path.curves.toString(), "{ point1: { x: 0, y: 100 }, point2: { x: 100, y: 100 } },{ point1: { x: 100, y: 100 }, point2: { x: 0, y: 100 } }", "path.curves: path.add(new Point(100, 100));\npath.removeSegments(1, 2);");

	// Transform the path, and the curves length should be invalidated (first, force-cache the first segment's length by accessing it
	path.curves[0].length;
	ok(path.curves[0]._length, 'Curve length does not appear to be cached');
	path.scale(2, [0, 0]);
	equals(path.curves[0].length, 200, 'Curve length should be updated when path is transformed');
});

test('path.flatten(maxDistance)', function() {
	var path = new Path.Circle(new Size(80, 50), 35);

	// Convert its curves to points, with a max distance of 20:
	path.flatten(20);

	equals(function() {
		return path.lastSegment.point.equals(path.firstSegment.point);
	}, false, 'The points of the last and first segments should not be the same.');

	equals(function() {
		return path.lastSegment.point.toString() != path.segments[path.segments.length - 2].point.toString();
	}, true, 'The points of the last and before last segments should not be so close, that calling toString on them returns the same string value.');
});

test('Curve list after removing a segment - 1', function() {
	var path = new paper.Path([0, 0], [1, 1], [2, 2]);

	equals(function() {
		return path.curves.length;
	}, 2, 'After creating a path with three segments, we should have two curves. By accessing path.curves we also make sure the curves are created internally.');

	path.segments[1].remove();
	equals(function() {
		return path.curves.length;
	}, 1, 'After removing the middle segment, we should be left with one curve');
});

test('Curve list after removing a segment - 2', function() {
	var path = new paper.Path([0, 0], [1, 1], [2, 2]);

	equals(function() {
		return path.curves.length;
	}, 2, 'After creating a path with three segments, we should have two curves. By accessing path.curves we also make sure the curves are created internally.');

	path.segments[2].remove();

	equals(function() {
		return path.curves.length;
	}, 1, 'After removing the last segment, we should be left with one curve');
});<|endoftext|>


<commit_before>/*
 *
 */

import * as fs from './filesystem.js'
import * as msg from './messaging.js'

import sysfs from './fs/sys.js'
import httpfs from './fs/http.js'
import html5fs from './fs/html5.js'
import githubfs from './fs/github.js'
import dropboxfs from './fs/dropbox.js'

import focalStorage from './external/focalStorage.js';

import { Cache } from './cache.js';

const storagePrefix = "LivelySync_";

class ServiceWorker {
  constructor() {
    this.filesystem = new fs.Filesystem();

    // default file system
    this.filesystem.mount('/', githubfs, {repo: 'LivelyKernel/Lively4', branch: 'master'}) // mounting lively4-core is to irritating
    this.filesystem.mount('/sys', sysfs, this);
    this.filesystem.mount('/local', html5fs);

    // here we should remount previous filesystem (remembered in focalStorage)

    // Create cache
    this._cache = new Cache('lively4_swx_cache_v1');
  }

  static instance() {
    var startTime = Date.now();
    var instance = new ServiceWorker();
    __instance__ = instance; // Global side effect #TODO

    return instance.filesystem.loadMounts().then( () => {
      console.log("mount FS in" + (Date.now() - startTime) + "ms");

      instance.resolvePendingRequests();
      return instance;
    })
  }

  resolvePendingRequests() {
    // DR: `pendingRequests` is defined during boot, but for later requests it did not exist, so the original check caused a ReferenceError
    if (typeof pendingRequests === 'undefined' || !pendingRequests) {
      console.log("no pending requests");
      return;
    }
    console.log("resolve pending requests: " + pendingRequests);
    // #Hack needed, because the swx-solved loads asyncronously and the service worker expects and syncronouse answer or promise.
    pendingRequests.forEach(ea => {
      console.log("work on pendingRequest " + ea.url);
      this.fetch(ea.event, ea);
    });
    pendingRequests = null; // stop listening to requests..

  }

  fetch(event, pending) {
    console.log("SWX.fetch " + event + ", " + pending);
    let request = event.request;
    if (!request) return;

    let  url   = new URL(request.url),
      promise = undefined

    if (url.pathname.match(/\/_git\//)) return;
    if (url.pathname.match(/\/_search\//)) return;
    if (url.pathname.match(/\/_meta\//)) return;
    if (url.pathname.match(/lively4-serviceworker/)) return;

    if (url.hostname !== 'lively4' && url.hostname == location.hostname && request.mode != 'navigate') {
      try {
        var p = new Promise(async (resolve, reject) => {
          var email = await focalStorage.getItem(storagePrefix+ "githubEmail");
          var username = await focalStorage.getItem(storagePrefix+ "githubUsername");
          var token = await focalStorage.getItem(storagePrefix+ "githubToken");

           // we have to manually recreate a request, because you cannot modify the original
           // see http://stackoverflow.com/questions/35420980/how-to-alter-the-headers-of-a-request
           var options = {
              method: request.method,
              headers: new Headers(),
              mode: request.mode,
              credentials: request.credentials,
              redirect: request.redirect
          }
          if (request.method == "PUT") {
            options.body =  await request.blob();
          }

          for (var pair of request.headers.entries()) {
            options.headers.set(pair[0], pair[1]);
          }
          options.headers.set("gitusername", username);
          options.headers.set("gitemail", email);
          options.headers.set("gitpassword", token);

          var req = new Request(request.url, options );

          // use system here to prevent recursion...
          resolve(self.fetch(req).then(result => {
            if (result instanceof Response) {
              return result;
            } else {
              return new Response(result);
            }
          }).catch(e => {
            console.log("fetch error: "  + e);
            return new Response("Could not fetch " + url +", because of: " + e);
          }))
        });

        if (pending) {
          pending.resolve(p);
        } else {
          // Use the cache if possible
          event.respondWith(
            this._cache.fetch(event.request, p)
          );
        }
      } catch(err) {
        // TODO: improve the solution, matching errors by message should be done better
        if (err.toString().match("The fetch event has already been responded to.")) {
          console.log("How can we check for this before? ", err);
        } else {
          throw err;
        }
      }
    } else if (url.hostname === 'lively4') {

      let response = this.filesystem.handle(request, url);

      response = response.then((result) => {
        if (result instanceof Response) {
          return result;
        } else if (result && result.toResponse) {
          return result.toResponse();
        } else {
          return new Response(result);
        }
      }).catch((err) => {
        console.error('Error while processing fetch event:', err);

        let message = err.toString();
        let content = JSON.stringify({message: message});

        return new Response(content, {status: 500, statusText: message});
      })

      if (pending) {
        console.log("resolve pending request: " + pending.url)
        pending.resolve(response);
      } else
        event.respondWith(response);
    }
  }

  message(event) {
    return msg.process(event)
  }
}

/*
 * function to object adapter
 */

var __instance__
var __instancePromise__
export async function instance() {
  return __instance__
}

export async function instancePromise() {
  if(typeof  __instancePromise__ === 'undefined') {
    __instancePromise__ = ServiceWorker.instance() // sets __instance__
  }
  return  __instancePromise__
}

export function install() {
  return self.skipWaiting()
}

export function activate() {
  return self.clients.claim()
}

export function fetch(event) {
  // console.log("fetch swx.js " + event.request.url)
  return instancePromise().then((swx) => swx.fetch(event));
}

export function message(event) {
  return instancePromise().then((swx) => swx.message(event))
}

export {
  focalStorage
}

console.log("load swx");
instancePromise(); // force constructor

// console.log("Loaded swx.js")
<commit_msg>Add comment about requests to https://lively4/<commit_after>/*
 *
 */

import * as fs from './filesystem.js'
import * as msg from './messaging.js'

import sysfs from './fs/sys.js'
import httpfs from './fs/http.js'
import html5fs from './fs/html5.js'
import githubfs from './fs/github.js'
import dropboxfs from './fs/dropbox.js'

import focalStorage from './external/focalStorage.js';

import { Cache } from './cache.js';

const storagePrefix = "LivelySync_";

class ServiceWorker {
  constructor() {
    this.filesystem = new fs.Filesystem();

    // default file system
    this.filesystem.mount('/', githubfs, {repo: 'LivelyKernel/Lively4', branch: 'master'}) // mounting lively4-core is to irritating
    this.filesystem.mount('/sys', sysfs, this);
    this.filesystem.mount('/local', html5fs);

    // here we should remount previous filesystem (remembered in focalStorage)

    // Create cache
    this._cache = new Cache('lively4_swx_cache_v1');
  }

  static instance() {
    var startTime = Date.now();
    var instance = new ServiceWorker();
    __instance__ = instance; // Global side effect #TODO

    return instance.filesystem.loadMounts().then( () => {
      console.log("mount FS in" + (Date.now() - startTime) + "ms");

      instance.resolvePendingRequests();
      return instance;
    })
  }

  resolvePendingRequests() {
    // DR: `pendingRequests` is defined during boot, but for later requests it did not exist, so the original check caused a ReferenceError
    if (typeof pendingRequests === 'undefined' || !pendingRequests) {
      console.log("no pending requests");
      return;
    }
    console.log("resolve pending requests: " + pendingRequests);
    // #Hack needed, because the swx-solved loads asyncronously and the service worker expects and syncronouse answer or promise.
    pendingRequests.forEach(ea => {
      console.log("work on pendingRequest " + ea.url);
      this.fetch(ea.event, ea);
    });
    pendingRequests = null; // stop listening to requests..

  }

  fetch(event, pending) {
    console.log("SWX.fetch " + event + ", " + pending);
    let request = event.request;
    if (!request) return;

    let  url   = new URL(request.url),
      promise = undefined

    if (url.pathname.match(/\/_git\//)) return;
    if (url.pathname.match(/\/_search\//)) return;
    if (url.pathname.match(/\/_meta\//)) return;
    if (url.pathname.match(/lively4-serviceworker/)) return;

    if (url.hostname !== 'lively4' && url.hostname == location.hostname && request.mode != 'navigate') {
      try {
        var p = new Promise(async (resolve, reject) => {
          var email = await focalStorage.getItem(storagePrefix+ "githubEmail");
          var username = await focalStorage.getItem(storagePrefix+ "githubUsername");
          var token = await focalStorage.getItem(storagePrefix+ "githubToken");

           // we have to manually recreate a request, because you cannot modify the original
           // see http://stackoverflow.com/questions/35420980/how-to-alter-the-headers-of-a-request
           var options = {
              method: request.method,
              headers: new Headers(),
              mode: request.mode,
              credentials: request.credentials,
              redirect: request.redirect
          }
          if (request.method == "PUT") {
            options.body =  await request.blob();
          }

          for (var pair of request.headers.entries()) {
            options.headers.set(pair[0], pair[1]);
          }
          options.headers.set("gitusername", username);
          options.headers.set("gitemail", email);
          options.headers.set("gitpassword", token);

          var req = new Request(request.url, options );

          // use system here to prevent recursion...
          resolve(self.fetch(req).then(result => {
            if (result instanceof Response) {
              return result;
            } else {
              return new Response(result);
            }
          }).catch(e => {
            console.log("fetch error: "  + e);
            return new Response("Could not fetch " + url +", because of: " + e);
          }))
        });

        if (pending) {
          pending.resolve(p);
        } else {
          // Use the cache if possible
          event.respondWith(
            this._cache.fetch(event.request, p)
          );
        }
      } catch(err) {
        // TODO: improve the solution, matching errors by message should be done better
        if (err.toString().match("The fetch event has already been responded to.")) {
          console.log("How can we check for this before? ", err);
        } else {
          throw err;
        }
      }
    } else if (url.hostname === 'lively4') {
      // QUESTION: When opening a folder, lively sometimes sends a OPTION request to https://lively4/
      // This request is then handled here and forwarded to the github filesystem, which returns an error 405
      // (there is never any actual path, the request always goes to https://lively4/)
      // Why is this happening? Is this still necessary?
      let response = this.filesystem.handle(request, url);

      response = response.then((result) => {
        if (result instanceof Response) {
          return result;
        } else if (result && result.toResponse) {
          return result.toResponse();
        } else {
          return new Response(result);
        }
      }).catch((err) => {
        console.error('Error while processing fetch event:', err);

        let message = err.toString();
        let content = JSON.stringify({message: message});

        return new Response(content, {status: 500, statusText: message});
      })

      if (pending) {
        console.log("resolve pending request: " + pending.url)
        pending.resolve(response);
      } else
        event.respondWith(response);
    }
  }

  message(event) {
    return msg.process(event)
  }
}

/*
 * function to object adapter
 */

var __instance__
var __instancePromise__
export async function instance() {
  return __instance__
}

export async function instancePromise() {
  if(typeof  __instancePromise__ === 'undefined') {
    __instancePromise__ = ServiceWorker.instance() // sets __instance__
  }
  return  __instancePromise__
}

export function install() {
  return self.skipWaiting()
}

export function activate() {
  return self.clients.claim()
}

export function fetch(event) {
  // console.log("fetch swx.js " + event.request.url)
  return instancePromise().then((swx) => swx.fetch(event));
}

export function message(event) {
  return instancePromise().then((swx) => swx.message(event))
}

export {
  focalStorage
}

console.log("load swx");
instancePromise(); // force constructor

// console.log("Loaded swx.js")
<|endoftext|>


<commit_before>(function ($) {

    "use strict";

    var List = function ($element, options) {
        var list = this;
        list.$list = $element;
        list.settings = $.extend({
            // options that may be overriden by html attributes
            'entity': list.$list.attr('data-list-entity'),
            'entityType': list.$list.attr('data-list-entity-type') || null,
            'entityId': list.$list.attr('data-list-entity-id') || null,
            'filters': list.$list.attr('data-list-filters') || null,
            'filtersElement': list.$list.attr('data-list-filters-element') || 'li',
            'channels': typeof list.$list.attr('data-list-channels') === "undefined" ? false : true,
            'fetchMoreButton': typeof list.$list.attr('data-list-fetch-more-button') === "undefined" ? false : true,
            'fetchMoreButtonClass': list.$list.attr('data-list-fetch-more-button-class') || 'data-list-fetch-more-button',
            'result': !list.$list.attr('data-list-result') ? list.$list : $(list.$list.attr('data-list-result')),
            'scrollable': typeof list.$list.attr('data-list-scrollable') === "undefined" ? false : true,
            'montage': typeof list.$list.attr('data-list-montage') === "undefined" ? false : true,
            // other options
            'preloaderImage': '/bundles/dodicifansworldweb/images/ajax-loader-small.gif'
        }, options || {});
        list.filter = $('[data-list-filter-type].active').attr('data-list-filter-type') || null;
        list.target = null;
        list.methodName = null;
        list.fetchedCount = null;
        list.page = 1;
        list.preloader = {
            'show': function () {
                list.preloader.hide();
                var $preloader = $('');
                $(list.settings.filters).append($preloader);
            },
            'hide': function () {
                $('.list-preloader').remove();
            }
        };

        list.init = function () {
            if (list.settings.montage) {
                montageHelper.doMontage(list.$list, {});
            }

            // set filters handling
            var $filterItems = $(list.settings.filters).find(list.settings.filtersElement);
            $filterItems.each(function () {
                $(this).click(function () {
                    var $btn = $(this);
                    if (!list.$list.data('fetchLock') && !$btn.hasClass('active')) {
                        list.page = 1;
                        list.settings.result.html("");
                        list.preloader.show();
                        if (list.settings.channels) {
                            list.target =  $btn.attr('data-list-target');
                            $('.js-subscribe').attr('data-active-channel', list.target);
                            // showing highlight panels
                            $('.tab-pane').hide();
                            $('.tab-pane#' + list.target).show();

                            // updating bottom list
                            var relatedList = $('#montage-video-list').data('list');
                            relatedList.settings.target = list.target;
                            relatedList.$list.data('fetchLock', true);
                            relatedList.page = 1;
                            relatedList.fetchList();
                        } else {
                            list.filter =  $btn.attr('data-list-filter-type');
                        }
                        list.$list.data('fetchLock', true);
                        $filterItems.removeClass('active');
                        $btn.addClass('active');

                        list.fetchList();

                    } else {
                        return false;
                    }
                });
            });

            if (list.settings.scrollable) {
                list.setScrollable(function () {
                    list.fetchList();
                });
            }

        };

        list.setScrollable = function (callback) {
            $(window).endlessScroll({
                fireOnce: true,
                enableScrollTop: false,
                inflowPixels: 100,
                fireDelay: 250,
                intervalFrequency: 2000,
                ceaseFireOnEmpty: false,
                loader: '',
                callback: function () {
                    if (typeof callback !== "undefined") {
                        list.preloader.show();
                        callback();
                    }
                }
            });
        };

        // fetch items list via ajax, and render the template
        list.fetchList = function () {
            list.fetchedCount = 0;
            list.methodName = list.settings.entity + '_' + list.filter;

            console.log(list);

            var opts = {
                'page': list.page,
                'entity': list.settings.entity
            };

            if (list.settings.channels) {
                list.methodName = list.settings.entity + '_ajaxcategory';
            }

            if (list.target !== null) {
                opts.category = list.target;
            }

            if (list.settings.entityType && list.settings.entityId) {
                opts.entityType = list.settings.entityType;
                opts.entityId = list.settings.entityId;
            }

            window.endlessScrollPaused = true;
            ajax.genericAction(list.methodName, opts, function (response) {
                if (!response.elements || !response.elements.length) {
                    list.preloader.hide();
                    list.settings.result.html("
No se encontraron videos.
");
                    list.$list.data('fetchLock', false);

                    return false;
                }

                if (list.settings.montage) {
                    list.renderMontage(response);
                } else {
                    list.renderRawList(response);
                }

                if (response.addMore) {
                    window.endlessScrollPaused = false;
                } else {
                    window.endlessScrollPaused = true;
                }

                return true;

            }, function (msg) {
                console.error(msg);
            });

            list.page++;
        };

        list.renderMontage = function (response) {
            for (var i in response.elements) {
                var element = response.elements[i];

                templateHelper.renderTemplate(list.settings.entity + "-list_element", element, list.settings.result, false, function () {
                    site.startMosaic(list.settings.result, {
                        minw: 150,
                        margin: 0,
                        liquid: true,
                        minsize: false
                    });

                    $("[data-new-element]").imagesLoaded(function () {
                        list.fetchedCount++;
                        if (response.elements.length === list.fetchedCount) {
                            list.preloader.hide();
                        }

                        if (i > 0) {
                            list.settings.result.montage('add', $("[data-new-element]"));
                        }
                        $("[data-new-element]").removeAttr('data-new-element');
                    });

                    list.$list.data('fetchLock', false);

                    if (response.addMore && list.settings.fetchMoreButton) {
                        $('.' + list.settings.fetchMoreButtonClass).remove();

                        var $button = $('Ver más');
                        $button.addClass(list.settings.fetchMoreButtonClass);

                        $button.click(function () {
                            list.fetchList();
                        });

                        list.$list.after($button);
                    } else {
                        $('.' + list.settings.fetchMoreButtonClass).remove();
                    }
                });
            }
        }

        list.renderRawList = function (response) {
            list.settings.result.html("");
            for(var i in response.elements) {
                list.settings.result.append(response.elements[i].view);
            }
            list.$list.data('fetchLock', false);
            list.preloader.hide();
        }

        list.init();

    };

    // plugin creation
    $.fn.list = function (options) {

        $(this).each(function () {
            var $element = $(this);

            if ($element.data('list')) {
                return;
            }
            $element.data('list', new List($element, options));
        });

    };

}(jQuery));
<commit_msg>preloader fix <commit_after>(function ($) {

    "use strict";

    var List = function ($element, options) {
        var list = this;
        list.$list = $element;
        list.settings = $.extend({
            // options that may be overriden by html attributes
            'entity': list.$list.attr('data-list-entity'),
            'entityType': list.$list.attr('data-list-entity-type') || null,
            'entityId': list.$list.attr('data-list-entity-id') || null,
            'filters': list.$list.attr('data-list-filters') || null,
            'filtersElement': list.$list.attr('data-list-filters-element') || 'li',
            'channels': typeof list.$list.attr('data-list-channels') === "undefined" ? false : true,
            'fetchMoreButton': typeof list.$list.attr('data-list-fetch-more-button') === "undefined" ? false : true,
            'fetchMoreButtonClass': list.$list.attr('data-list-fetch-more-button-class') || 'data-list-fetch-more-button',
            'result': !list.$list.attr('data-list-result') ? list.$list : $(list.$list.attr('data-list-result')),
            'scrollable': typeof list.$list.attr('data-list-scrollable') === "undefined" ? false : true,
            'montage': typeof list.$list.attr('data-list-montage') === "undefined" ? false : true,
            // other options
            'preloaderImage': '/bundles/dodicifansworldweb/images/ajax-loader-small.gif'
        }, options || {});
        list.filter = $('[data-list-filter-type].active').attr('data-list-filter-type') || null;
        list.target = null;
        list.methodName = null;
        list.fetchedCount = null;
        list.page = 1;
        list.preloader = {
            'show': function () {
                //list.preloader.hide();
                //var $preloader = $('');
                //$(list.settings.filters).append($preloader);
                $("[data-list-montage]").find('*').hide();
                $("[data-list-montage]").addClass('loading');
            },
            'hide': function () {
                //$('.list-preloader').remove();
                $("[data-list-montage]").removeClass('loading');
                $("[data-list-montage]").find('*').show();
            }
        };

        list.init = function () {
            if (list.settings.montage) {
                montageHelper.doMontage(list.$list, {});
            }

            // set filters handling
            var $filterItems = $(list.settings.filters).find(list.settings.filtersElement);
            $filterItems.each(function () {
                $(this).click(function () {
                    var $btn = $(this);
                    if (!list.$list.data('fetchLock') && !$btn.hasClass('active')) {
                        list.page = 1;
                        list.settings.result.html("");
                        list.preloader.show();
                        if (list.settings.channels) {
                            list.target =  $btn.attr('data-list-target');
                            $('.js-subscribe').attr('data-active-channel', list.target);
                            // showing highlight panels
                            $('.tab-pane').hide();
                            $('.tab-pane#' + list.target).show();

                            // updating bottom list
                            var relatedList = $('#montage-video-list').data('list');
                            relatedList.settings.target = list.target;
                            relatedList.$list.data('fetchLock', true);

                            relatedList.page = 1;
                            relatedList.fetchList();
                        } else {
                            list.filter =  $btn.attr('data-list-filter-type');
                        }
                        console.log(list.$list);
                        list.$list.data('fetchLock', true);
                        $filterItems.removeClass('active');
                        $btn.addClass('active');

                        list.fetchList();

                    } else {
                        return false;
                    }
                });
            });

            if (list.settings.scrollable) {
                list.setScrollable(function () {
                    list.fetchList();
                });
            }

        };

        list.setScrollable = function (callback) {
            $(window).endlessScroll({
                fireOnce: true,
                enableScrollTop: false,
                inflowPixels: 100,
                fireDelay: 250,
                intervalFrequency: 2000,
                ceaseFireOnEmpty: false,
                loader: '',
                callback: function () {
                    if (typeof callback !== "undefined") {
                        list.preloader.show();
                        callback();
                    }
                }
            });
        };

        // fetch items list via ajax, and render the template
        list.fetchList = function () {
            list.fetchedCount = 0;
            list.methodName = list.settings.entity + '_' + list.filter;

            var opts = {
                'page': list.page,
                'entity': list.settings.entity
            };

            if (list.settings.channels) {
                list.methodName = list.settings.entity + '_ajaxcategory';
            }

            if (list.target !== null) {
                opts.category = list.target;
            }

            if (list.settings.entityType && list.settings.entityId) {
                opts.entityType = list.settings.entityType;
                opts.entityId = list.settings.entityId;
            }

            window.endlessScrollPaused = true;
            ajax.genericAction(list.methodName, opts, function (response) {

                if (!response.elements || !response.elements.length) {
                    list.preloader.hide();
                    list.settings.result.html("
No se encontraron videos.
");
                    list.$list.data('fetchLock', false);

                    return false;
                }

                if (list.settings.montage) {
                    list.renderMontage(response);
                } else {
                    list.renderRawList(response);
                }

                if (response.addMore) {
                    window.endlessScrollPaused = false;
                } else {
                    window.endlessScrollPaused = true;
                }

                return true;

            }, function (msg) {
                console.error(msg);
            });

            list.page++;
        };

        list.renderMontage = function (response) {
            for (var i in response.elements) {
                var element = response.elements[i];

                templateHelper.renderTemplate(list.settings.entity + "-list_element", element, list.settings.result, false, function () {
                    site.startMosaic(list.settings.result, {
                        minw: 150,
                        margin: 0,
                        liquid: true,
                        minsize: false
                    });

                    $("[data-new-element]").imagesLoaded(function () {
                        list.fetchedCount++;
                        if (response.elements.length === list.fetchedCount) {
                            list.preloader.hide();
                        }

                        if (i > 0) {
                            list.settings.result.montage('add', $("[data-new-element]"));
                        }
                        $("[data-new-element]").removeAttr('data-new-element');
                    });

                    list.$list.data('fetchLock', false);

                    if (response.addMore && list.settings.fetchMoreButton) {
                        $('.' + list.settings.fetchMoreButtonClass).remove();

                        var $button = $('Ver más');
                        $button.addClass(list.settings.fetchMoreButtonClass);

                        $button.click(function () {
                            list.fetchList();
                        });

                        list.$list.after($button);
                    } else {
                        $('.' + list.settings.fetchMoreButtonClass).remove();
                    }
                });
            }
        }

        list.renderRawList = function (response) {
            list.settings.result.html("");
            for(var i in response.elements) {
                list.settings.result.append(response.elements[i].view);
            }
            list.$list.data('fetchLock', false);
            list.preloader.hide();
        }

        list.init();

    };

    // plugin creation
    $.fn.list = function (options) {

        $(this).each(function () {
            var $element = $(this);

            if ($element.data('list')) {
                return;
            }
            $element.data('list', new List($element, options));
        });

    };

}(jQuery));
<|endoftext|>


<commit_before>define([
    'uijet_dir/uijet',
    'importer/app',
    'i18n'
], function (uijet, Importer, i18n) {

    function translate (data) {
        data.i18n = i18n;
    }

    return {
        parseDate           : function (date) {
            return [date.getFullYear(), date.getMonth() + 1, date.getDate()].join('-');
        },
        processDivisions    : function (data) {
            translate(data);
            data.results = data.results.filter(function (item, i) {
                return item.budgeting;
            });
        },
        processEntities     : function (data) {
            translate(data);
            //! Array.prototype.filter
            data.results = data.results.filter(function (item, i) {
                //return item.division.budgeting;
                return true;
            });
        },
        formExtConfigByType : function (type) {
            var config = {
                    template_name   : type + '-form'
                };

            switch ( type ) {
                case 'template':
                    config.partials = {
                        divisions   : 'divisions'
                    };
                    config.signals = {
                        post_render : function () {
                            uijet.start({
                                type    : 'DatepickerInput',
                                config  : {
                                    element     : '#period_start',
                                    datepicker  : {
                                        app_events  : {
                                            'period_start_picker.wake'  : 'wake+',
                                            'period_start_picker.sleep' : 'sleep'
                                        }
                                    }
                                }
                            })
                            .then( this.wakeContained.bind(this) );
                        },
                        process_data: this.processDivisions
                    };
                    config.data_url = Importer.BASE_API_URL + 'divisions/';
                    break;
                case 'sheet':
                    config.partials = {
                        entities: 'entities'
                    };
                    config.signals = {
                        process_data: this.processEntities,
                        post_render : function () {
                            uijet.start([{
                                type    : 'DatepickerInput',
                                config  : {
                                    element     : '#period_start',
                                    datepicker  : {
                                        app_events  : {
                                            'period_start_picker.wake'  : 'wake+',
                                            'period_end_picker.wake'    : 'sleep',
                                            'period_start_picker.sleep' : 'sleep'
                                        }
                                    }
                                }
                            }, {
                                type    : 'DatepickerInput',
                                config  : {
                                    element     : '#period_end',
                                    datepicker  : {
                                        app_events  : {
                                            'period_end_picker.wake'    : 'wake+',
                                            'period_start_picker.wake'  : 'sleep',
                                            'period_end_picker.sleep'   : 'sleep'
                                        }
                                    }
                                }
                            }])
                            .then( this.wakeContained.bind(this) );
                        }
                    };
                    config.data_url = Importer.BASE_API_URL + 'entities/';
                    break;
            }

            return config;
        }
    };
});
<commit_msg>Fixed entities query<commit_after>define([
    'uijet_dir/uijet',
    'importer/app',
    'i18n'
], function (uijet, Importer, i18n) {

    function translate (data) {
        data.i18n = i18n;
    }

    return {
        parseDate           : function (date) {
            return [date.getFullYear(), date.getMonth() + 1, date.getDate()].join('-');
        },
        processDivisions    : function (data) {
            translate(data);
            data.results = data.results.filter(function (item, i) {
                return item.budgeting;
            });
        },
        processEntities     : function (data) {
            translate(data);
            //! Array.prototype.filter
            data.results = data.results.filter(function (item, i) {
                //return item.division.budgeting;
                return true;
            });
        },
        formExtConfigByType : function (type) {
            var config = {
                    template_name   : type + '-form'
                };

            switch ( type ) {
                case 'template':
                    config.partials = {
                        divisions   : 'divisions'
                    };
                    config.signals = {
                        post_render : function () {
                            uijet.start({
                                type    : 'DatepickerInput',
                                config  : {
                                    element     : '#period_start',
                                    datepicker  : {
                                        app_events  : {
                                            'period_start_picker.wake'  : 'wake+',
                                            'period_start_picker.sleep' : 'sleep'
                                        }
                                    }
                                }
                            })
                            .then( this.wakeContained.bind(this) );
                        },
                        process_data: this.processDivisions
                    };
                    config.data_url = Importer.BASE_API_URL + 'divisions/';
                    break;
                case 'sheet':
                    config.partials = {
                        entities: 'entities'
                    };
                    config.signals = {
                        process_data: this.processEntities,
                        post_render : function () {
                            uijet.start([{
                                type    : 'DatepickerInput',
                                config  : {
                                    element     : '#period_start',
                                    datepicker  : {
                                        app_events  : {
                                            'period_start_picker.wake'  : 'wake+',
                                            'period_end_picker.wake'    : 'sleep',
                                            'period_start_picker.sleep' : 'sleep'
                                        }
                                    }
                                }
                            }, {
                                type    : 'DatepickerInput',
                                config  : {
                                    element     : '#period_end',
                                    datepicker  : {
                                        app_events  : {
                                            'period_end_picker.wake'    : 'wake+',
                                            'period_start_picker.wake'  : 'sleep',
                                            'period_end_picker.sleep'   : 'sleep'
                                        }
                                    }
                                }
                            }])
                            .then( this.wakeContained.bind(this) );
                        }
                    };
                    config.data_url = Importer.BASE_API_URL + 'entities/?page_by=300&ordering=name';
                    break;
            }

            return config;
        }
    };
});
<|endoftext|>


<commit_before>import Vue from 'vue';
import VueMaterial from 'vue-material';
import 'vue-material/dist/vue-material.css';
import 'vue-material/dist/theme/default.css';
Vue.use(VueMaterial);

import { LinearModel2d } from '../linear_model/Stats.js';
import Tabs from './Tabs.js';
import * as Util from './Util.js';
import StairstepChart from './StairstepChart.js';
import PieChart from './PieChart.js';

import Main from '../App.vue';

// Array a -> Getter a a Number Number -> Array Number
// Take an array of anything, and a function that gets numbers out of
// the array, and return an array of cumulative values
export function runningTotal(data, lens) {
  lens = lens || Util.identity;
  let result = data.reduce(function(acc, value) {
    let current = lens(value) + acc.total;
    return {
      data : acc.data.concat([current]),
      total : current
    }
  }, { total : 0, data : [] });
  return result.data;
}

// { selector : String, data :: Array [year, value] }
export function run(options) {

  let boulderLinearModel = new LinearModel2d(options.data.boulder);
  let boulderData = projectData(
      boulderLinearModel,
    cumulativeData(options.data.boulder)
  );
  let foCoLinearModel = new LinearModel2d(options.data.fortCollins);
  let fcData = projectData(
      foCoLinearModel,
      cumulativeData(options.data.fortCollins)
  );

  let stairstepData = {
    boulder: Util.toProjectionFormat(boulderData),
    fortCollins: Util.toProjectionFormat(fcData)
  };

  Tabs({
    tabs : [
      {
        id: 'projections',
        display: 'block',
        label: 'Projections',
        callback : function(element) {
          element.innerHTML='<canvas id="stairstep-chart" width="600" height="400"></canvas>';
          StairstepChart({
            selector : "#stairstep-chart",
            data: stairstepData
          });
        }
      }, {
        id: 'ratios',
        display: 'none',
        label: 'Ratios',
        callback : function(element) {
          element.innerHTML='<canvas id="pie-chart" width="600" height="400"></canvas>';

          PieChart({
            selector : "#pie-chart",
            data: {
              "Electric":50,
              "Ground Travel":26,
              "Natural Gas":19,
              "Solid Waste":4,
              "Water Related":.3
            }
          });
        }
      }
    ]
  })
}

export let boulderData = (function() {
  return [
    [2006, 53],
    [2007, 548],
    [2008, 1399],
    [2009, 1765],
    [2010, 2371],
    [2011, 2072],
    [2012, 1409],
    [2013, 1903],
    [2014, 8791],
    [2015, 1136],
    [2016, 1556],
    [2017, 595],
  ];
}());

let fortCollinsDataProcessor = function(apiRawResponse) {
    const apiResponse = JSON.parse(apiRawResponse);
    let aggregatedByYear = {};
    apiResponse.forEach((r) => {
        let regex = /\d+\/\d+\/(\d+) \d+:\d+:\d+/;
        const regSearchResult = regex.exec(r.date_of_service);
        if (regSearchResult == null) return;
        const year = regSearchResult[1];
        const previousValue = aggregatedByYear[year] ? aggregatedByYear[year]: 0;
        aggregatedByYear[year] = previousValue + parseFloat(r.system_capacity_kw_dc);
    });

    return Object.keys(aggregatedByYear).map(function(key) {
        return [Number(key), Math.round(aggregatedByYear[key])];
    });
};

// Array [year, value] -> Array [year, value]
export function cumulativeData (data) {
  let years = data.map(Util.first);
  let values = data.map(Util.second);
  return Util.zip(years, runningTotal(values));
}

// LinearModel -> Array [year, value] -> {
//   all : Array { date : Date, value : Number },
//   past : Array { date : Date, value : Number },
//   future : Array { date : Date, value : Number },
//   futureMinus : Array { date : Date, value : Number },
//   futurePlus : Array { date : Date, value : Number }
// }
// Will attempt to from 2016 to 2030.  Future data points are projected based on
// past data.
export function projectData(linearmodel, origData) {
  // Clone the data so we won't modify the
  // original copy.
  let data = Util.cloneArray(origData)
                 .map(Util.cloneArray);

  let lastYear = Util.tail(data)[0];
  // let linearmodel = new LinearModel2d(data);

  for (let year = lastYear + 1; year <= 2030; year++) {
    let projection = linearmodel.project_r_squared(year, year-lastYear+1);
    data.push([year, Math.round(projection[1])]);
  }

  return data;
}

let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://opencity.fcgov.com/resource/ykei-s9zt.json');
xhr.onload = function() {
    if (xhr.status === 200) {
        new Vue({
            mounted() {
                run({
                    selector: '#stairstep-chart-tabs',
                    data: {
                        boulder: boulderData,
                        fortCollins: fortCollinsDataProcessor(xhr.responseText)
                    },
                });
            },
            render: h => h(Main),
        }).$mount('#app');
    }
    else {
        alert('FoCo API request failed.  Returned status of ' + xhr.status);
    }
};
xhr.send();
<commit_msg>Adding updated Boulder data Ian added in #55<commit_after>import Vue from 'vue';
import VueMaterial from 'vue-material';
import 'vue-material/dist/vue-material.css';
import 'vue-material/dist/theme/default.css';
Vue.use(VueMaterial);

import { LinearModel2d } from '../linear_model/Stats.js';
import Tabs from './Tabs.js';
import * as Util from './Util.js';
import StairstepChart from './StairstepChart.js';
import PieChart from './PieChart.js';

import Main from '../App.vue';

// Array a -> Getter a a Number Number -> Array Number
// Take an array of anything, and a function that gets numbers out of
// the array, and return an array of cumulative values
export function runningTotal(data, lens) {
  lens = lens || Util.identity;
  let result = data.reduce(function(acc, value) {
    let current = lens(value) + acc.total;
    return {
      data : acc.data.concat([current]),
      total : current
    }
  }, { total : 0, data : [] });
  return result.data;
}

// { selector : String, data :: Array [year, value] }
export function run(options) {

  let boulderLinearModel = new LinearModel2d(options.data.boulder);
  let boulderData = projectData(
      boulderLinearModel,
    cumulativeData(options.data.boulder)
  );
  let foCoLinearModel = new LinearModel2d(options.data.fortCollins);
  let fcData = projectData(
      foCoLinearModel,
      cumulativeData(options.data.fortCollins)
  );

  let stairstepData = {
    boulder: Util.toProjectionFormat(boulderData),
    fortCollins: Util.toProjectionFormat(fcData)
  };

  Tabs({
    tabs : [
      {
        id: 'projections',
        display: 'block',
        label: 'Projections',
        callback : function(element) {
          element.innerHTML='<canvas id="stairstep-chart" width="600" height="400"></canvas>';
          StairstepChart({
            selector : "#stairstep-chart",
            data: stairstepData
          });
        }
      }, {
        id: 'ratios',
        display: 'none',
        label: 'Ratios',
        callback : function(element) {
          element.innerHTML='<canvas id="pie-chart" width="600" height="400"></canvas>';

          PieChart({
            selector : "#pie-chart",
            data: {
              "Electric":50,
              "Ground Travel":26,
              "Natural Gas":19,
              "Solid Waste":4,
              "Water Related":.3
            }
          });
        }
      }
    ]
  })
}

export let boulderData = (function() {
  return [
    [2006, 53],
    [2007, 548],
    [2008, 1399],
    [2009, 1765],
    [2010, 2371],
    [2011, 2072],
    [2012, 1409],
    [2013, 1903],
    [2014, 8791],
    [2015, 1136],
    [2016, 1556],
    [2017, 1812],
    [2018, 2097]
  ];
}());

let fortCollinsDataProcessor = function(apiRawResponse) {
    const apiResponse = JSON.parse(apiRawResponse);
    let aggregatedByYear = {};
    apiResponse.forEach((r) => {
        let regex = /\d+\/\d+\/(\d+) \d+:\d+:\d+/;
        const regSearchResult = regex.exec(r.date_of_service);
        if (regSearchResult == null) return;
        const year = regSearchResult[1];
        const previousValue = aggregatedByYear[year] ? aggregatedByYear[year]: 0;
        aggregatedByYear[year] = previousValue + parseFloat(r.system_capacity_kw_dc);
    });

    return Object.keys(aggregatedByYear).map(function(key) {
        return [Number(key), Math.round(aggregatedByYear[key])];
    });
};

// Array [year, value] -> Array [year, value]
export function cumulativeData (data) {
  let years = data.map(Util.first);
  let values = data.map(Util.second);
  return Util.zip(years, runningTotal(values));
}

// LinearModel -> Array [year, value] -> {
//   all : Array { date : Date, value : Number },
//   past : Array { date : Date, value : Number },
//   future : Array { date : Date, value : Number },
//   futureMinus : Array { date : Date, value : Number },
//   futurePlus : Array { date : Date, value : Number }
// }
// Will attempt to from 2016 to 2030.  Future data points are projected based on
// past data.
export function projectData(linearmodel, origData) {
  // Clone the data so we won't modify the
  // original copy.
  let data = Util.cloneArray(origData)
                 .map(Util.cloneArray);

  let lastYear = Util.tail(data)[0];
  // let linearmodel = new LinearModel2d(data);

  for (let year = lastYear + 1; year <= 2030; year++) {
    let projection = linearmodel.project_r_squared(year, year-lastYear+1);
    data.push([year, Math.round(projection[1])]);
  }

  return data;
}

let xhr = new XMLHttpRequest();
xhr.open('GET', 'https://opencity.fcgov.com/resource/ykei-s9zt.json');
xhr.onload = function() {
    if (xhr.status === 200) {
        new Vue({
            mounted() {
                run({
                    selector: '#stairstep-chart-tabs',
                    data: {
                        boulder: boulderData,
                        fortCollins: fortCollinsDataProcessor(xhr.responseText)
                    },
                });
            },
            render: h => h(Main),
        }).$mount('#app');
    }
    else {
        alert('FoCo API request failed.  Returned status of ' + xhr.status);
    }
};
xhr.send();
<|endoftext|>


<commit_before><commit_msg>Delete unused file<commit_after><|endoftext|>


<commit_before>var box2d, stage, world, mppx = 50, canvasWidth = 300, canvasHeight = 440;

puckt.main = (function () {
    "use strict";
    var init = function () {
        // Set up stage and enable touch controls
        var canvas = document.getElementById("ice-rink");
        puckt.util.setCanvasSize(canvas, canvasWidth, canvasHeight);
        stage = new createjs.Stage(canvas);
        createjs.Touch.enable(stage);

        // Create scene
        createScene();

        // Declare settings for scene ticker
        createjs.Ticker.addListener(this);
        createjs.Ticker.setFPS(60);
        createjs.Ticker.useRAF = true;
    },
    createScene = function () {
        // Create world with no gravity
        world = new box2d.b2World(new box2d.b2Vec2(0, 0), true);

        // Enables debugging shapes for box2d
        puckt.debug.run(function () {
            var debugDraw = new box2d.b2DebugDraw(),
                debugCanvas = document.createElement('canvas');

            puckt.util.setCanvasSize(debugCanvas, canvasWidth, canvasHeight);
            stage.canvas.parentNode.appendChild(debugCanvas);

            debugDraw.SetSprite(stage.canvas.getContext("2d"));
            debugDraw.SetFlags(box2d.b2DebugDraw.e_shapeBit | box2d.b2DebugDraw.e_jointBit);
            world.SetDebugDraw(debugDraw);

            // Set up event proxies
            puckt.debug.proxyEvents(debugCanvas, stage.canvas, 'mousedown', 'mousemove', 'mouseup');
        });

        // Create objects in scene
        var p = new Puck();
        stage.addChild(p.view);
        // Eventually load in the levels into here
        new Touch(p.view);
    },
    tickrolled = function () {
        // Update stage
        stage.update();

        world.Step(1/60, 10, 10);
        world.ClearForces();
    };
    // Set the options for the box2d variable
    box2d = {
        b2Vec2 : Box2D.Common.Math.b2Vec2,
        b2BodyDef : Box2D.Dynamics.b2BodyDef,
        b2Body : Box2D.Dynamics.b2Body,
        b2FixtureDef : Box2D.Dynamics.b2FixtureDef,
        b2Fixture : Box2D.Dynamics.b2Fixture,
        b2World : Box2D.Dynamics.b2World,
        b2MassData : Box2D.Collision.Shapes.b2MassData,
        b2PolygonShape : Box2D.Collision.Shapes.b2PolygonShape,
        b2CircleShape : Box2D.Collision.Shapes.b2CircleShape,
        b2DebugDraw : Box2D.Dynamics.b2DebugDraw
    };
    return {
        init: init,
        tickrolled: tickrolled
    }
}());
// Declare tick function outside of the namespace to ensure it is called
function tick () {
    puckt.main.tickrolled();
}

window.addEventListener("load", puckt.main.init);<commit_msg>Fixed missed merge error<commit_after>var box2d, stage, world, mppx = 50, canvasWidth = 300, canvasHeight = 440;

puckt.main = (function () {
    "use strict";
    var init = function () {
        // Set up stage and enable touch controls
        var canvas = document.getElementById("ice-rink");
        puckt.util.setCanvasSize(canvas, canvasWidth, canvasHeight);
        stage = new createjs.Stage(canvas);
        createjs.Touch.enable(stage);

        // Create scene
        createScene();

        // Declare settings for scene ticker
        createjs.Ticker.addListener(this);
        createjs.Ticker.setFPS(60);
        createjs.Ticker.useRAF = true;
    },
    createScene = function () {
        // Create world with no gravity
        world = new box2d.b2World(new box2d.b2Vec2(0, 0), true);

        // Enables debugging shapes for box2d
        puckt.debug.run(function () {
            var debugDraw = new box2d.b2DebugDraw(),
                debugCanvas = document.createElement('canvas');

            puckt.util.setCanvasSize(debugCanvas, canvasWidth, canvasHeight);
            stage.canvas.parentNode.appendChild(debugCanvas);

            debugDraw.SetSprite(stage.canvas.getContext("2d"));
            debugDraw.SetFlags(box2d.b2DebugDraw.e_shapeBit | box2d.b2DebugDraw.e_jointBit);
            world.SetDebugDraw(debugDraw);

            // Set up event proxies
            puckt.debug.proxyEvents(debugCanvas, stage.canvas, 'mousedown', 'mousemove', 'mouseup');
        });
        // Create objects in scene
        var p = new Puck(150, 440/8*7);
        stage.addChild(p.view);
        // Eventually load in the levels into here
        new Touch(p.view);
    },
    tickrolled = function () {
        // Update stage
        stage.update();

        world.Step(1/60, 10, 10);
        world.ClearForces();
    };
    // Set the options for the box2d variable
    box2d = {
        b2Vec2 : Box2D.Common.Math.b2Vec2,
        b2BodyDef : Box2D.Dynamics.b2BodyDef,
        b2Body : Box2D.Dynamics.b2Body,
        b2FixtureDef : Box2D.Dynamics.b2FixtureDef,
        b2Fixture : Box2D.Dynamics.b2Fixture,
        b2World : Box2D.Dynamics.b2World,
        b2MassData : Box2D.Collision.Shapes.b2MassData,
        b2PolygonShape : Box2D.Collision.Shapes.b2PolygonShape,
        b2CircleShape : Box2D.Collision.Shapes.b2CircleShape,
        b2DebugDraw : Box2D.Dynamics.b2DebugDraw
    };
    return {
        init: init,
        tickrolled: tickrolled
    }
}());
// Declare tick function outside of the namespace to ensure it is called
function tick () {
    puckt.main.tickrolled();
}

window.addEventListener("load", puckt.main.init);<|endoftext|>


<commit_before>const Tx = require('../index.js')
const tape = require('tape')
const ethUtil = require('ethereumjs-util')
const argv = require('minimist')(process.argv.slice(2))
const testing = require('ethereumjs-testing')

const forkNames = [
  'Byzantium',
  'Constantinople',
  'EIP150',
  'EIP158',
  'Frontier',
  'Homestead',
]

tape('TransactionTests', (t) => {
  const fileFilterRegex = argv.file ? new RegExp(argv.file + '[^\\w]') : undefined

  testing.getTests('TransactionTests', (filename, testName, testData) => {
    let rawTx
    let tx
    t.test(testName, (st) => {
      const rawTx = ethUtil.toBuffer(testData.rlp)
      let tx
      let sender
      let hash
      forkNames.forEach(forkName => {
        try {
          tx = new Tx(rawTx)
          if (forkName !== 'Homestead') {
            tx._homestead = false
          }
          const sender = tx.getSenderAddress().toString('hex')
          const hash = tx.hash().toString('hex')
          st.assert(sender === testData[forkName].sender && hash === testData[forkName].hash, `Sender and hash should be correct on ${forkName}`)
        } catch (e) {
          if (tx !== undefined) {
            st.equal(e.message, 'Invalid Signature', `Transaction signature should be invalid on ${forkName}`)
          } else {
            st.pass(`Transaction should be invalid and should error on creation on ${forkName}`)
          }
        }
      })
      st.end()
    })
  }, fileFilterRegex)
  .then(() => {
    t.end()
  })
})
<commit_msg>Ensure transaction runner handles all forks, valid and invalid tests correctly.<commit_after>const Tx = require('../index.js')
const tape = require('tape')
const ethUtil = require('ethereumjs-util')
const argv = require('minimist')(process.argv.slice(2))
const testing = require('ethereumjs-testing')

const forkNames = [
  'Byzantium',
  'Constantinople',
  'EIP150',
  'EIP158',
  'Frontier',
  'Homestead',
]

const forkNameMap = {
  Byzantium: 'byzantium',
  Constantinople: 'constantinople',
  EIP150: 'tangerineWhistle',
  EIP158: 'spuriousDragon',
  Frontier: 'chainstart',
  Homestead: 'homestead',
}

tape('TransactionTests', (t) => {
  const fileFilterRegex = argv.file ? new RegExp(argv.file + '[^\\w]') : undefined

  testing.getTests('TransactionTests', (filename, testName, testData) => {
    let rawTx
    let tx
    t.test(testName, (st) => {
      const rawTx = ethUtil.toBuffer(testData.rlp)

      let tx
      let sender
      let hash
      forkNames.forEach(forkName => {
        const forkTestData = testData[forkName]
        const shouldBeInvalid = Object.keys(forkTestData).length === 0
        try {
          tx = new Tx(rawTx, {
            hardfork: forkNameMap[forkName],
          })

          const sender = tx.getSenderAddress().toString('hex')
          const hash = tx.hash().toString('hex')

          const validationErrors = tx.validate(true)
          const transactionIsValid = validationErrors.length === 0
          const hashAndSenderAreCorrect = forkTestData && (sender === forkTestData.sender && hash === forkTestData.hash)

          if (shouldBeInvalid) {
            st.assert(!transactionIsValid, `Transaction should be invalid on ${forkName}`)
          } else {
            st.assert(hashAndSenderAreCorrect && transactionIsValid, `Transaction should be valid on ${forkName}`)
          }
        } catch (e) {
          if (shouldBeInvalid) {
            st.assert(shouldBeInvalid, `Transaction should be invalid on ${forkName}`)
          } else {
            st.fail(`Transaction should be valid on ${forkName}`)
          }
        }
      })
      st.end()
    })
  }, fileFilterRegex)
  .then(() => {
    t.end()
  })
})
<|endoftext|>