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

    console.log('SearcherCtrl setup');
    define([
        'angular' //,
        // 'ngGrid'
    ], function(angular) {
        console.log('SearcherCtrl define');

        function SearcherCtrl($scope) {
            $scope.findGrpDisabled = false;
            $scope.searchTermGrp = "Chicago";
            $scope.searchTermMap = "Chicago Crime";
            $scope.signInOutGrp = "Sign In";
            $scope.signInOutMap = "Sign In";
            $scope.data = [
                {"id" : "ca8219b99d9442a8b21cd61e71ee48b8","title" : "Somewhere in Chicago", "snippet" : "foo", "thumbnail" : "foo.jpg"},
                {"id" : "0ba4d84db84e4564b936ec548ea91575","title" : "2013 Midwest Tornado Outbreak", "snippet" : "bar", "thumbnail" : "bar.jpg"}
                ];
            $scope.isMapAccPanelOpen = false;
            $scope.mapGriddata = [
                {"id" : "ca8219b99d9442a8b21cd61e71ee48b8","title" : "Somewhere in Chicago", "snippet" : "foo", "thumbnail" : "thumbnail/foo.jpg"},
                {"id" : "0ba4d84db84e4564b936ec548ea91575","title" : "2013 Midwest Tornado Outbreak", "snippet" : "bar", "thumbnail" : "thumbnail/bar.jpg"}
                ];

            $scope.imgWebMapUrlBase = 'http://www.arcgis.com/sharing/rest/content/items/';
            $scope.imgWebMapTmplt =
                '';

            $scope.gridMapOptions = {
                data: 'mapGriddata',
                rowHeight: '50',
                plugins: [layoutPlugin],

                columnDefs: [
                    {field:'thumbnail',
                     width: '50px',
                     displayName:'Img',
                     cellTemplate: $scope.imgWebMapTmplt},
                    {field:'snippet',
                     width: '60px',
                     displayName:'Description'},
                    {field:'title',
                     width: '56px',
                     displayName:'Map Title'},
                    {field:'id',
                     width: '58px',
                     displayName:'ID'}
                ]

            };
            var self = this;
            self.scope = $scope;

            var layoutPlugin = new ngGridLayoutPlugin();

            $scope.updateLayout = function(){
              layoutPlugin.updateGridLayout();
            };
            $scope.selectedItm = "Nada";
            $scope.selectionChanged = function(rowItem,event){
                console.debug(rowItem.entity);
                console.debug(rowItem.entity.title   + '/' + rowItem.entity.thumbnail);
                $scope.isMapAccPanelOpen = ! $scope.isMapAccPanelOpen;
                console.log("isMapAccPanelOpen = " + $scope.isMapAccPanelOpen);
                var accPane = angular.element(document.getElementById("MapSearcherPane"));
                console.debug(accPane);
                $scope.findMapsForGroup(rowItem.entity.id);
                // $scope.selectedItm = rowItem.entity.thumbnail;
            }

            $scope.imgUrlBase = 'http://www.arcgis.com/sharing/rest/community/groups/';

            $scope.imgTmplt =
                '';

            $scope.gridGrpOptions = {
                data: 'data',
                // enablePaging: true,
                rowHeight: '50' ,
                // plugins: [layoutPlugin],
                multiSelect: false,
                afterSelectionChange:  $scope.selectionChanged,
                columnDefs: [
                    {field:'thumbnail',
                     width: '50px',
                     displayName:'Img',
                     cellTemplate: $scope.imgTmplt},
                    {field:'title',
                     width: '124px',
                     displayName: 'Group'},
                    {field: 'snippet',
                     width: '124px',
                     displayName: 'Description'},
                    {field: 'id',
                     visible: false,
                     displayName: '#'}
                ]
            };

            var portal = null;
               // find groups based on input keyword
            $scope.findArcGISGroup = function(portalForSearch) {
              self.portal = portalForSearch;
              console.log('findArcGISGroup');
              var keyword = $scope.searchTermGrp;
              var params = {
                q:  keyword,
                num:20  //find 40 items - max is 100
               };
               portalForSearch.queryGroups(params).then(function (data) {
                $scope.showGroupResults(data);
               });
            }

            $scope.getGridStyleMap = function () {

                var vrbg = angular.element(document.getElementById("verbagePan"));
                var accHead = angular.element(document.getElementById("AccdianNews"));
                var srchWrap = angular.element(document.getElementById("searchToolWrapperMap"));
                var marginborder = (1 + 1) * 2;
                var accinnermarginborder = (1 + 9) * 2;
                var availableHgt = vrbg[0].offsetHeight - srchWrap[0].offsetHeight - accinnermarginborder -
                                    4 * (accHead[0].offsetHeight + marginborder);
                var rowHeight = 50;
                var headerHeight = 34;
                var height = +($scope.data.length * rowHeight + headerHeight);
                if (height > availableHgt) {
                    height = availableHgt;
                }
                return {
                    height: height + "px"
                }
            }

            $scope.getGridStyleGroup = function () {

                var vrbg = angular.element(document.getElementById("verbagePan"));
                var accHead = angular.element(document.getElementById("AccdianNews"));
                var srchWrap = angular.element(document.getElementById("searchToolWrapperGroup"));
                var marginborder = (1 + 1) * 2;
                var accinnermarginborder = (1 + 9) * 2;
                var availableHgt = vrbg[0].offsetHeight - srchWrap[0].offsetHeight - accinnermarginborder -
                                    4 * (accHead[0].offsetHeight + marginborder);
                var rowHeight = 50;
                var headerHeight = 34;
                var height = +($scope.data.length * rowHeight + headerHeight);
                if (height > availableHgt) {
                    height = availableHgt;
                }
                return {
                    height: height + "px"
                }
            };

            $scope.redrawGrid = function () {
                window.setTimeout(function () {
                    $(window).resize();
                    $(window).resize();
                }, 250);
            };

            $scope.showGroupResults = function(response) {
                //clear any existing results
                console.log('$scope.showGroupResults');

                    // gridGroupLocal.on("dgrid-select", function(event){
                        // Report the item from the selected row to the console.
                if (response.total > 0) {
                    var grddata = response.results;
                    //create the grid
                    $scope.data = response.results;
                    // $scope.gridGrpOptions.data = response.results;
                    console.debug($scope.data);
                    $scope.redrawGrid();
                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }
                    // gridGrpOptions.data = data;
                        // console.log("Row selected: ", event.rows[0].data.title);
                        // console.log("Row selected: ", event.rows[0].data.id);
                    // });
              } else {
                dojo.byId('groupResults').innerHTML = '
Group Results

No groups were found. If the group is not public use the sign-in link to sign in and find private groups.
';
              }
            }

            $scope.findArcGISGroupMaps = function(portal, searchTermMap) {
              utils.showLoading()
              var keyword = searchTermMap; //dojo.byId('mapFinder').value;
              var params = {
                q: ' type:"Web Map" -type:"Web Mapping Application" ' + keyword,
                num: 20
              };
              portal.queryItems(params).then(function (data) {
                    $scope.showMapResults(data);
                });
            }

            $scope.findMapsForGroup = function(gId)
            {
              console.log("findMapsForGroup : " + gId);
              var params = {
                 q:  'id : ' +  gId,
                 num:20  //find 40 items - max is 100
                };

                self.portal.queryGroups(params).then(function(groups){
                //get group title and thumbnail url
                if (groups.results.length > 0) {
                  console.log("group 0 results:");
                  var group = groups.results[0];
                  console.debug(group);

                  //Retrieve the web maps and applications from the group and display
                  var params = {
                    q: ' type:"Web Map" -type:"Web Mapping Application"',
                    num: 10
                  };
                  group.queryItems(params).then(function (data) {
                        $scope.showMapResults(data);
                    });
                }
              });
            }

            // gets private groups as well
            $scope.signInFromGroupTab = function() {
              console.log("signInFromGroupTab");

              if ($scope.signInOutGrp.indexOf('In') !== -1) {
                portalForSearch.signIn().then(function (loggedInUser) {
                    $scope.signInOutGrp = "Sign Out";
                    $scope.signInOutMap = "Sign Out";
                    $scope.findArcGISGroup(portalForSearch);   // update results
                }, function (error) { //error so reset sign in link
                    $scope.signInOutGrp = "Sign In";
                    $scope.signInOutMap = "Sign In";
                });
              } else {
                portalForSearch.signOut().then(function (portalInfo) {
                    $scope.signInOutGrp = "Sign In";
                    $scope.signInOutMap = "Sign In";
                    findArcGISGroup(portalForSearch);
                });
              }
            }

            // gets private groups as well
            $scope.signInFromMapTab = function() {
              console.log("signInFromMapTab");

              if ($scope.signInOutMap.indexOf('In') !== -1) {
                portal.signIn().then(function (loggedInUser) {
                    $scope.signInOutGrp = "Sign Out";
                    $scope.signInOutMap = "Sign Out";
                  findArcGISGroupMaps(portal, $scope.searchTermMap);   // update results
                }, function (error) {  //error so reset sign in link
                    $scope.signInOutGrp = "Sign In";
                    $scope.signInOutMap = "Sign In";
                });
              } else {
                portal.signOut().then(function (portalInfo) {
                    $scope.signInOutGrp = "Sign In";
                    $scope.signInOutMap = "Sign In";
                    findArcGISGroupMaps(portal, $scope.searchTermMap);
                });
              }
            }

            //display a list of groups that match the input user name

            $scope.showMapResults = function(response) {
                // utils.hideLoading();
                //clear any existing results
                console.log("showMapResults");
                console.debug(response);
                if (response.total > 0) {
                    var mpdata = response.results;
                    //create the grid
                    $scope.mapGriddata = response.results;
                    // $scope.gridGrpOptions.data = response.results;
                    console.debug($scope.mapGriddata);
                    $scope.redrawGrid();
                    $scope.updateLayout();
                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }

                 }
            }
        }

        function init(App) {
            console.log('SearcherCtrl init');
            App.controller('SearcherCtrl', ['$scope', SearcherCtrl]);
            return SearcherCtrl;
        }

        return { start: init };

    });

}).call(this);<commit_msg>Introduced error that prevents compilation.<commit_after>
(function() {
    "use strict";

    console.log('SearcherCtrl setup');
    define([
        'angular' //,
        // 'ngGrid'
    ], function(angular) {
        console.log('SearcherCtrl define');

        function SearcherCtrl($scope) {
            $scope.findGrpDisabled = false;
            $scope.searchTermGrp = "Chicago";
            $scope.searchTermMap = "Chicago Crime";
            $scope.signInOutGrp = "Sign In";
            $scope.signInOutMap = "Sign In";
            $scope.data = [
            /*
                {"id" : "ca8219b99d9442a8b21cd61e71ee48b8","title" : "Somewhere in Chicago", "snippet" : "foo", "thumbnail" : "foo.jpg"},
                {"id" : "0ba4d84db84e4564b936ec548ea91575","title" : "2013 Midwest Tornado Outbreak", "snippet" : "bar", "thumbnail" : "bar.jpg"}
                 */
                ];
            $scope.isMapAccPanelOpen = false;
            $scope.mapGriddata = [
            /*
                {"id" : "ca8219b99d9442a8b21cd61e71ee48b8","title" : "Somewhere in Chicago", "snippet" : "foo", "thumbnail" : "thumbnail/foo.jpg"},
                {"id" : "0ba4d84db84e4564b936ec548ea91575","title" : "2013 Midwest Tornado Outbreak", "snippet" : "bar", "thumbnail" : "thumbnail/bar.jpg"}
                 */
                ];

            $scope.imgWebMapUrlBase = ""; /*  'http://www.arcgis.com/sharing/rest/content/items/'; */
            $scope.imgWebMapTmplt = "";
              /*   '';
                 */
            $scope.gridMapOptions = {
                data: 'mapGriddata',
                rowHeight: '50',
                plugins: [layoutPlugin],

                columnDefs: [
                    {field:'thumbnail',
                     width: '50px',
                     displayName:'Img',
                     cellTemplate: $scope.imgWebMapTmplt},
                    {field:'snippet',
                     width: '60px',
                     displayName:'Description'},
                    {field:'title',
                     width: '56px',
                     displayName:'Map Title'},
                    {field:'id',
                     width: '58px',
                     displayName:'ID'}
                ]

            };
            var self = this;
            self.scope = $scope;

            var layoutPlugin = new ngGridLayoutPlugin();

            $scope.updateLayout = function(){
              layoutPlugin.updateGridLayout();
            };
            $scope.selectedItm = "Nada";
            $scope.selectionChanged = function(rowItem,event){
                console.debug(rowItem.entity);
                console.debug(rowItem.entity.title   + '/' + rowItem.entity.thumbnail);
                $scope.isMapAccPanelOpen = ! $scope.isMapAccPanelOpen;
                console.log("isMapAccPanelOpen = " + $scope.isMapAccPanelOpen);
                var accPane = angular.element(document.getElementById("MapSearcherPane"));
                console.debug(accPane);
                $scope.findMapsForGroup(rowItem.entity.id);
                // $scope.selectedItm = rowItem.entity.thumbnail;
            };

            $scope.imgUrlBase = 'http://www.arcgis.com/sharing/rest/community/groups/';

            $scope.imgTmplt =
                '';

            $scope.gridGrpOptions = {
                data: 'data',
                // enablePaging: true,
                rowHeight: '50' ,
                // plugins: [layoutPlugin],
                multiSelect: false,
                afterSelectionChange:  $scope.selectionChanged,
                columnDefs: [
                    {field:'thumbnail',
                     width: '50px',
                     displayName:'Img',
                     cellTemplate: $scope.imgTmplt},
                    {field:'title',
                     width: '124px',
                     displayName: 'Group'},
                    {field: 'snippet',
                     width: '124px',
                     displayName: 'Description'},
                    {field: 'id',
                     visible: false,
                     displayName: '#'}
                ]
            };

            var portal = null;
               // find groups based on input keyword
            $scope.findArcGISGroup = function() { //portalForSearch) {
              // self.portal = portalForSearch;
              console.log('findArcGISGroup');
              var keyword = $scope.searchTermGrp;
              var params = {
                q:  keyword,
                num:20  //find 40 items - max is 100
               };
               portalForSearch.queryGroups(params).then(function (data) {
                $scope.showGroupResults(data);
               });
            };

            $scope.getGridStyleMap = function () {
                /*
                var vrbg = angular.element(document.getElementById("verbagePan"));
                var accHead = angular.element(document.getElementById("AccdianNews"));
                var srchWrap = angular.element(document.getElementById("searchToolWrapperMap"));
                var marginborder = (1 + 1) * 2;
                var accinnermarginborder = (1 + 9) * 2;
                var availableHgt = vrbg[0].offsetHeight - srchWrap[0].offsetHeight - accinnermarginborder -
                                    4 * (accHead[0].offsetHeight + marginborder);
                var rowHeight = 50;
                var headerHeight = 34;
                var height = +($scope.data.length * rowHeight + headerHeight);
                if (height > availableHgt) {
                    height = availableHgt;
                }
                return {
                    height: height + "px"
                }; */

            };

            $scope.getGridStyleGroup = function () {

                var vrbg = angular.element(document.getElementById("verbagePan"));
                var accHead = angular.element(document.getElementById("AccdianNews"));
                var srchWrap = angular.element(document.getElementById("searchToolWrapperGroup"));
                var marginborder = (1 + 1) * 2;
                var accinnermarginborder = (1 + 9) * 2;
                var availableHgt = vrbg[0].offsetHeight - srchWrap[0].offsetHeight - accinnermarginborder -
                                    4 * (accHead[0].offsetHeight + marginborder);
                var rowHeight = 50;
                var headerHeight = 34;
                var height = +($scope.data.length * rowHeight + headerHeight);
                if (height > availableHgt) {
                    height = availableHgt;
                }
                return {
                    height: height + "px"
                };
            };

            $scope.redrawGrid = function () {
                window.setTimeout(function () {
                    $(window).resize();
                    $(window).resize();
                }, 250);
            };

            $scope.showGroupResults = function(response) {
                //clear any existing results
                console.log('$scope.showGroupResults');

                    // gridGroupLocal.on("dgrid-select", function(event){
                        // Report the item from the selected row to the console.
                if (response.total > 0) {
                    var grddata = response.results;
                    //create the grid
                    $scope.data = response.results;
                    // $scope.gridGrpOptions.data = response.results;
                    console.debug($scope.data);
                    $scope.redrawGrid();
                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }
                    // gridGrpOptions.data = data;
                        // console.log("Row selected: ", event.rows[0].data.title);
                        // console.log("Row selected: ", event.rows[0].data.id);
                    // });
              } else {
                dojo.byId('groupResults').innerHTML = '
Group Results

No groups were found. If the group is not public use the sign-in link to sign in and find private groups.
';
              }
            };

            $scope.findArcGISGroupMaps = function(portal, searchTermMap) {
              utils.showLoading();
              var keyword = searchTermMap; //dojo.byId('mapFinder').value;
              var params = {
                q: ' type:"Web Map" -type:"Web Mapping Application" ' + keyword,
                num: 20
              };
              portal.queryItems(params).then(function (data) {
                    $scope.showMapResults(data);
                });
            };

            $scope.findMapsForGroup = function(gId)
            {
              console.log("findMapsForGroup : " + gId);
              var params = {
                 q:  'id : ' +  gId,
                 num:20  //find 40 items - max is 100
                };

                self.portal.queryGroups(params).then(function(groups){
                //get group title and thumbnail url
                if (groups.results.length > 0) {
                  console.log("group 0 results:");
                  var group = groups.results[0];
                  console.debug(group);

                  //Retrieve the web maps and applications from the group and display
                  var params = {
                    q: ' type:"Web Map" -type:"Web Mapping Application"',
                    num: 10
                  };
                  group.queryItems(params).then(function (data) {
                        $scope.showMapResults(data);
                    });
                }
              });
            };

            // gets private groups as well
            $scope.signInFromGroupTab = function() {
              console.log("signInFromGroupTab");
              self.portal = portalForSearch;

              if ($scope.signInOutGrp.indexOf('In') !== -1) {
                portalForSearch.signIn().then(function (loggedInUser) {
                    $scope.signInOutGrp = "Sign Out";
                    $scope.signInOutMap = "Sign Out";
                    $scope.findArcGISGroup(); // portalForSearch);   // update results
                }, function (error) { //error so reset sign in link
                    $scope.signInOutGrp = "Sign In";
                    $scope.signInOutMap = "Sign In";
                });
              } else {
                portalForSearch.signOut().then(function (portalInfo) {
                    $scope.signInOutGrp = "Sign In";
                    $scope.signInOutMap = "Sign In";
                    findArcGISGroup(portalForSearch);
                });
              }
            };

            // gets private groups as well
            $scope.signInFromMapTab = function() {
              console.log("signInFromMapTab");
              self.portal = portalForSearch;

              if ($scope.signInOutMap.indexOf('In') !== -1) {
                portal.signIn().then(function (loggedInUser) {
                    $scope.signInOutGrp = "Sign Out";
                    $scope.signInOutMap = "Sign Out";
                  findArcGISGroupMaps(portal, $scope.searchTermMap);   // update results
                }, function (error) {  //error so reset sign in link
                    $scope.signInOutGrp = "Sign In";
                    $scope.signInOutMap = "Sign In";
                });
              } else {
                portal.signOut().then(function (portalInfo) {
                    $scope.signInOutGrp = "Sign In";
                    $scope.signInOutMap = "Sign In";
                    findArcGISGroupMaps(portal, $scope.searchTermMap);
                });
              }
            };

            //display a list of groups that match the input user name

            $scope.showMapResults = function(response) {
                // utils.hideLoading();
                //clear any existing results
                console.log("showMapResults");
                console.debug(response);
                if (response.total > 0) {
                    var mpdata = response.results;
                    //create the grid
                    $scope.mapGriddata = response.results;
                    // $scope.gridGrpOptions.data = response.results;
                    console.debug($scope.mapGriddata);
                    $scope.redrawGrid();
                    $scope.updateLayout();
                    if (!$scope.$$phase) {
                        $scope.$apply();
                    }

                 }
            };
        }

        function init(App) {
            console.log('SearcherCtrl init');
            App.controller('SearcherCtrl', ['$scope', SearcherCtrl]);
            return SearcherCtrl;
        }

        return { start: init };

    });

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


<commit_before>//     (c) 2015-2016 Hernán Rodríguez Colmeiro
//     Tortuga may be freely distributed under the MIT license.
/*
 * Create a Tortuga.
 *  canvasSelector: String, canvas element selector
 *  initx:          Int, initial X coordinate (optional, default 0)
 *  inity:          Int, initial Y coordinate (optional, default 0)
 *  length:         Int, default length used by forward (optional, default 100)
 */
function Tortuga(canvasSelector, initx, inity, length) {
  // Check if the selector matches
  this.canvasSelector = canvasSelector || '#tortuga';
  try {
    this.ctx = document.querySelector(this.canvasSelector).getContext('2d');
  } catch (e) {
    throw Error(
      'The canvasSelector `' + this.canvasSelector + '` matched no element'
    );
  }

  // Parse optional parameters
  this.position = [initx || 0, inity || 0];
  this.length = length || 100;

  // Set internal variables
  this.direction = 0; // Direction is in degrees
  this._penDown = true;

  // Tortuga pre-set color palette. To store new colors or modify existing
  // ones just modify this list.
  this.palette = [
    [0, 0, 0], // black
    [0, 0, 255], // blue
    [0, 255, 0], // green
    [0, 255, 255], // cyan
    [255, 0, 0], // red
    [255, 0, 255], // magenta
    [255, 255, 0], // yellow
    [255, 255, 255], // white
    [155, 96, 59], // brown
    [255, 149, 119], // tan
    [34, 139, 34], // 10 forest
    [127, 255, 212], // 11 aqua
    [250, 128, 114], // 12 salmon
    [128, 0, 128], // 13 purple
    [255, 163, 0], // orange
    [183, 183, 183] // grey
  ];

  // Set stroke style to white and the fill style to black.
  this.penColor = 'rgb(' + this.palette[7].join(',') + ')';
  this.ctx.strokeStyle = this.penColor;
  this.ctx.fillStyle = 'rgb(' + this.palette[0].join(',') + ')';

  // Set the pen width to the default 1
  this.size(1);

  // Y axis on screen is rotated, so fix it
  this.fixAxis();

  this.clean();
  this.begin();
}

// Helper to set the origin at the center and axis
// to increase towards top right.
Tortuga.prototype.fixAxis = function fixAxis() {
  this.ctx.resetTransform();
  this.ctx.translate(this.ctx.canvas.width / 2, this.ctx.canvas.height / 2);
  this.ctx.scale(1, -1);
};

// Clean the current turtle drawing.
Tortuga.prototype.clean = function clean() {
  // Paint it black!
  var height = this.ctx.canvas.height;
  var width = this.ctx.canvas.width;
  // Origin is at the center, so start painting from bottom left.
  this.ctx.fillRect(width * -1 / 2, height * -1 / 2, width, height);
};

// Clear the current turtle drawing and reset turtle position.
Tortuga.prototype.reset = function reset() {
  this.home();
  this.clean();
  this.begin();
};

// Usually shouldn't be used outside Tortuga, begins a new path.
Tortuga.prototype.begin = function begin() {
  this.ctx.beginPath();
  this.ctx.moveTo(this.position[0], this.position[1]);
};

// Draw the current turtle path, and begin a new one.
Tortuga.prototype.drawPath = function drawPath() {
  this.ctx.stroke();
  this.begin();
};

// Change the pen color, draws the current path.
// Accepts either a color string or rgb values.
Tortuga.prototype.color = function color(r, g, b) {
  var colorIndex = 0;
  if (arguments.length === 3) {
    // rgb was passed as arguments
    this.penColor = 'rgb(' + r + ',' + g + ',' + b + ')';
  } else {
    // Check if first parameter is string or int
    if (isNaN(parseInt(r, 10))) {
      // Use this string as strokeStyle
      this.penColor = r;
    } else {
      // Palette color was sent
      // Only allow indexes available for this.palette
      colorIndex = parseInt(r, 10) % this.palette.length;
      this.penColor = 'rgb(' + this.palette[colorIndex].join(',') + ')';
    }
  }
  this.ctx.strokeStyle = this.penColor;
  this.drawPath();
};

// Step the pen color through the rainbow.
Tortuga.prototype.rainbow = function rainbow(step, totalSteps) {
  this.color('hsl(' + Math.ceil(step / totalSteps * 360) + ', 100%, 50%)');
};

// Set the pen size.
Tortuga.prototype.size = function size(_size) {
  this.penSize = parseFloat(_size, 10);
  this.ctx.lineWidth = this.penSize;
};

// Lift the pen, draws the current path.
Tortuga.prototype.penUp = function penUp() {
  this.drawPath();
  this._penDown = false;
};

// Set the pen down.
Tortuga.prototype.penDown = function penDown() {
  this._penDown = true;
};

// Returns the pen status.
Tortuga.prototype.isPenDown = function isPenDown() {
  return this._penDown;
};

// Move the turtle to the specified absolute [`x`, `y`] position.
Tortuga.prototype.setXY = function setXY(x, y) {
  // Update position
  this.position = [x, y];

  // If the pen is down, write. Otherwise just move
  if (this.isPenDown()) {
    this.ctx.lineTo(x, y);
  } else {
    this.ctx.moveTo(x, y);
  }
};

// Move the turtle horizontally to the new `x` coordinate.
Tortuga.prototype.setX = function setX(x) {
  this.setXY(x, this.position[1]);
};

// Move the turtle vertically to the new `y` coordinate.
Tortuga.prototype.setY = function setY(y) {
  this.setXY(this.position[0], y);
};

// Move the turtle to it's initial position at [0, 0] and heading 0.
Tortuga.prototype.home = function home() {
  this.setXY(0, 0);
  this.setHeading(0);
};

// Move forward the specified length, or use the default one.
Tortuga.prototype.forward = function forward(length) {
  // `this.direction` is measured clockwise from the Y axis,
  // but the canvas measures angles counterclockwise from the X axis,
  // so we have to convert it first to something canvas understands.
  var _length = length === undefined ? this.length : length;
  var x = this.position[0];
  var y = this.position[1];
  var angle = -1 * this.direction + 90;

  // And then convert the angle to radians
  angle = Math.PI * (angle) / 180;

  // And finally add the displacement
  x += Math.cos(angle) * _length;
  y += Math.sin(angle) * _length;

  this.setXY(x, y);
};

// A handy rename to move backwards.
Tortuga.prototype.back = function back(length) {
  // Change the direction momentarily
  this.direction -= 180;
  // Use forward to avoid repeating code
  this.forward(length);
  // Restore the direction as it was before
  this.direction += 180;
};

// Rotate the turtle by the desired angle in deg, clockwise.
Tortuga.prototype.right = function right(deg) {
  this.direction = (this.direction + deg) % 360;
};

// Rotate the turtle by the desired angle in deg, counterclockwise.
Tortuga.prototype.left = function left(deg) {
  this.right(-1 * deg);
};

// Set the turtle absolute heading to the specified angle in deg.
Tortuga.prototype.setHeading = function setHeading(heading) {
  this.direction = heading % 360;
};

// Return the direction for the turtle to point directly to the destination.
Tortuga.prototype.towards = function towards(x, y) {
  // Get the position vector (r) for this.position->(x,y)
  var r = [x - this.position[0], y - this.position[1]];
  // Get the position vector angle
  var heading = Math.atan2(r[0], r[1]);
  // Return heading in degrees
  return heading * 180 / Math.PI;
};
<commit_msg>Parse integer inputs.<commit_after>//     (c) 2015-2016 Hernán Rodríguez Colmeiro
//     Tortuga may be freely distributed under the MIT license.
/*
 * Create a Tortuga.
 *  canvasSelector: String, canvas element selector
 *  initx:          Int, initial X coordinate (optional, default 0)
 *  inity:          Int, initial Y coordinate (optional, default 0)
 *  length:         Int, default length used by forward (optional, default 100)
 */
function Tortuga(canvasSelector, initx, inity, length) {
  // Check if the selector matches
  this.canvasSelector = canvasSelector || '#tortuga';
  try {
    this.ctx = document.querySelector(this.canvasSelector).getContext('2d');
  } catch (e) {
    throw Error(
      'The canvasSelector `' + this.canvasSelector + '` matched no element'
    );
  }

  // Parse optional parameters
  this.position = [parseInt(initx, 10) || 0, parseInt(inity, 10) || 0];
  this.length = length || 100;

  // Set internal variables
  this.direction = 0; // Direction is in degrees
  this._penDown = true;

  // Tortuga pre-set color palette. To store new colors or modify existing
  // ones just modify this list.
  this.palette = [
    [0, 0, 0], // black
    [0, 0, 255], // blue
    [0, 255, 0], // green
    [0, 255, 255], // cyan
    [255, 0, 0], // red
    [255, 0, 255], // magenta
    [255, 255, 0], // yellow
    [255, 255, 255], // white
    [155, 96, 59], // brown
    [255, 149, 119], // tan
    [34, 139, 34], // 10 forest
    [127, 255, 212], // 11 aqua
    [250, 128, 114], // 12 salmon
    [128, 0, 128], // 13 purple
    [255, 163, 0], // orange
    [183, 183, 183] // grey
  ];

  // Set stroke style to white and the fill style to black.
  this.penColor = 'rgb(' + this.palette[7].join(',') + ')';
  this.ctx.strokeStyle = this.penColor;
  this.ctx.fillStyle = 'rgb(' + this.palette[0].join(',') + ')';

  // Set the pen width to the default 1
  this.size(1);

  // Y axis on screen is rotated, so fix it
  this.fixAxis();

  this.clean();
  this.begin();
}

// Helper to set the origin at the center and axis
// to increase towards top right.
Tortuga.prototype.fixAxis = function fixAxis() {
  this.ctx.resetTransform();
  this.ctx.translate(this.ctx.canvas.width / 2, this.ctx.canvas.height / 2);
  this.ctx.scale(1, -1);
};

// Clean the current turtle drawing.
Tortuga.prototype.clean = function clean() {
  // Paint it black!
  var height = this.ctx.canvas.height;
  var width = this.ctx.canvas.width;
  // Origin is at the center, so start painting from bottom left.
  this.ctx.fillRect(width * -1 / 2, height * -1 / 2, width, height);
};

// Clear the current turtle drawing and reset turtle position.
Tortuga.prototype.reset = function reset() {
  this.home();
  this.clean();
  this.begin();
};

// Usually shouldn't be used outside Tortuga, begins a new path.
Tortuga.prototype.begin = function begin() {
  this.ctx.beginPath();
  this.ctx.moveTo(this.position[0], this.position[1]);
};

// Draw the current turtle path, and begin a new one.
Tortuga.prototype.drawPath = function drawPath() {
  this.ctx.stroke();
  this.begin();
};

// Change the pen color, draws the current path.
// Accepts either a color string or rgb values.
Tortuga.prototype.color = function color(r, g, b) {
  var colorIndex = 0;
  if (arguments.length === 3) {
    // rgb was passed as arguments
    this.penColor = 'rgb(' + r + ',' + g + ',' + b + ')';
  } else {
    // Check if first parameter is string or int
    if (isNaN(parseInt(r, 10))) {
      // Use this string as strokeStyle
      this.penColor = r;
    } else {
      // Palette color was sent
      // Only allow indexes available for this.palette
      colorIndex = parseInt(r, 10) % this.palette.length;
      this.penColor = 'rgb(' + this.palette[colorIndex].join(',') + ')';
    }
  }
  this.ctx.strokeStyle = this.penColor;
  this.drawPath();
};

// Step the pen color through the rainbow.
Tortuga.prototype.rainbow = function rainbow(_step, _totalSteps) {
  var step = parseInt(_step, 10);
  var totalSteps = parseInt(_totalSteps, 10);
  this.color('hsl(' + Math.ceil(step / totalSteps * 360) + ', 100%, 50%)');
};

// Set the pen size.
Tortuga.prototype.size = function size(_size) {
  this.penSize = parseFloat(_size, 10);
  this.ctx.lineWidth = this.penSize;
};

// Lift the pen, draws the current path.
Tortuga.prototype.penUp = function penUp() {
  this.drawPath();
  this._penDown = false;
};

// Set the pen down.
Tortuga.prototype.penDown = function penDown() {
  this._penDown = true;
};

// Returns the pen status.
Tortuga.prototype.isPenDown = function isPenDown() {
  return this._penDown;
};

// Move the turtle to the specified absolute [`x`, `y`] position.
Tortuga.prototype.setXY = function setXY(x, y) {
  // Update position
  this.position = [parseInt(x, 10), parseInt(y, 10)];

  // If the pen is down, write. Otherwise just move
  if (this.isPenDown()) {
    this.ctx.lineTo(this.position[0], this.position[1]);
  } else {
    this.ctx.moveTo(this.position[0], this.position[1]);
  }
};

// Move the turtle horizontally to the new `x` coordinate.
Tortuga.prototype.setX = function setX(x) {
  this.setXY(parseInt(x, 10), this.position[1]);
};

// Move the turtle vertically to the new `y` coordinate.
Tortuga.prototype.setY = function setY(y) {
  this.setXY(this.position[0], parseInt(y, 10));
};

// Move the turtle to it's initial position at [0, 0] and heading 0.
Tortuga.prototype.home = function home() {
  this.setXY(0, 0);
  this.setHeading(0);
};

// Move forward the specified length, or use the default one.
Tortuga.prototype.forward = function forward(length) {
  // `this.direction` is measured clockwise from the Y axis,
  // but the canvas measures angles counterclockwise from the X axis,
  // so we have to convert it first to something canvas understands.
  var _length = length === undefined ? this.length : parseInt(length, 10);
  var x = this.position[0];
  var y = this.position[1];
  var angle = -1 * this.direction + 90;

  // And then convert the angle to radians
  angle = Math.PI * (angle) / 180;

  // And finally add the displacement
  x += Math.cos(angle) * _length;
  y += Math.sin(angle) * _length;

  this.setXY(x, y);
};

// A handy rename to move backwards.
Tortuga.prototype.back = function back(length) {
  // Change the direction momentarily
  this.direction -= 180;
  // Use forward to avoid repeating code
  this.forward(parseInt(length, 10));
  // Restore the direction as it was before
  this.direction += 180;
};

// Rotate the turtle by the desired angle in deg, clockwise.
Tortuga.prototype.right = function right(deg) {
  this.direction = (this.direction + parseInt(deg, 10)) % 360;
};

// Rotate the turtle by the desired angle in deg, counterclockwise.
Tortuga.prototype.left = function left(deg) {
  this.right(-1 * parseInt(deg, 10));
};

// Set the turtle absolute heading to the specified angle in deg.
Tortuga.prototype.setHeading = function setHeading(heading) {
  this.direction = parseInt(heading, 10) % 360;
};

// Return the direction for the turtle to point directly to the destination.
Tortuga.prototype.towards = function towards(x, y) {
  // Get the position vector (r) for this.position->(x,y)
  var r = [
    parseInt(x, 10) - this.position[0],
    parseInt(y, 10) - this.position[1]
  ];
  // Get the position vector angle
  var heading = Math.atan2(r[0], r[1]);
  // Return heading in degrees
  return heading * 180 / Math.PI;
};
<|endoftext|>


<commit_before>// load core.lispz
// convert lambda, alias, etc to lispz in core
// (args a b c) ==> var a = arguments[1], ...;
// scoped name as in cond.else
var lispz = function() {
    var alias, load;
    // characters that are not space separated atoms (n becomes linefeed in regex)
    var delims = "(){}[];'`|n".split('');
    var not_delims = delims.join("\\");
    delims = delims.join('|\\')
    var stringRE = "'{1,2}.*?'{1,2}|" + '".*?[^\\\\]"|""|';
    // Keep state stack for when we start a new inner list ()[]{}
    var push_state = function(env) {
        env.stack.push(env.list);
        env.list = [env.atom]
    };
    var pop_state = function(env) {
        var list = env.list;
        (env.list = env.stack.pop()).push(list);
    };
    // when a list is closed we process it given the opening command/type
    var list2js = function(env, list) {
      return env.list2js[list[0]](env, list)
    };
    // processing pairs of list elements
    pairs = function(env, list) {
      var el = [], pairs = list[1], fore = list2js(env, list[2]);
      var tween = list2js(env, list[3]), aft = list2js(env, list[4]);
      for (var i = 1, l = pairs.length; i < l; i += 2) {
          el.push(list2js(env, pairs[i]) + tween + list2js(env, pairs[i + 1]))
      };
      return fore + el.join(',') + aft
    }
    // Convert a list of lists to a list of js fragments
    var lists2list = function(env, lists) {
      return lists.map(function(list, index, parent) {
        env.parent = parent; env.parent_index = index;
        return list2js(env, list);
      }).filter(function(a) { return a && a.length });
    };
    // convert a list to a javascript call
    var call2js = function(env, list) {
      var js = ' ';
      if (env.list2js[list[1][1]]) {
        return env.list2js[list[1][1]](env, list.slice(1))
      }
      var params = lists2list(env, list.slice(2))
      return " " + list2js(env, list[1]) + "(" + params.join(',') + ')'
    };
    // Convert (js parameters) to javascript
    params2js = function(env, list) {
      return lists2list(env, list.slice(1)).join('');
    }
    // Take symbols javascript doesn't recognise and convert
    replacements = {
        '!': "$bang$", '#': "$hash$", '%': "$percent$", '&': "$ampersand",
        '*': "$star$", '+': "$plus$", '-': "$dash$", '/': "$slash$",
        ':': "$colon$", ';': "$semicolon$", '<': "$less$", '=': "$equal",
        '>': "$greater$", '?': "$question$", '@': "$at$", '\\': "$slosh$",
        '^': "$caret$", '~': "$tilde$"
    }
    var jsify = function(atom) {
      var last = atom.length - 1;
      if (atom[0] === '"' && atom[last] === '"') return atom;
      if (atom[0] === "'" && atom[last] === "'") return atom.slice(1,last);
      return atom.replace(/\W/g, function(symbol) {
          var rep = replacements[symbol];
          return rep ? rep : symbol
      })
    };
    // pull function params from a list
    var list2params = function(list) {
      return list.slice(1).map(function(p, i) { return jsify(p[1]) });
    };
    // convert a list to a function definition
    var lambda2js = function(env, list) {
      return "(function(" + list2params(list[1]).join(',') + "){return " +
          lists2list(env, list.slice(2)).join(",") + "})"
    };
    // retrieve the next atom from the input stream. Returns false on no more
    var next_atom = function(env) {
        if (!(env.atom = env.tkre.exec(env.source))) return false;
        if (env.alias[env.atom = env.atom[1]]) env.atom = env.alias[env.atom];
        return env.atom;
    };
    // convert an atom to a simple list
    var atom2list = function(env) {
      if (env.delimiter[env.atom]) {
        env.delimiter[env.atom](env)
      } else {
        env.list.push([".atom", env.atom])
      }
    };
    // Create a lambda that expands a named macro
    var build_macro = function(env, list, async) {
      var macro_name = list2js(env, list[1]);
      var macro_params = {".callback":list[2].length}, body = list.slice(3);
      list2params(list[2]).forEach(function(p, i) { macro_params[p] = i + 1 })
      var clone = function(macro_body, replacements) {
        if (macro_body[0] === ".atom") {
          var is_ref = (macro_body[1][0] === '*'); // *rest
          var name = is_ref ? macro_body[1].slice(1) : macro_body[1];
          if (macro_params[name]) { // replace with param or list of rest
            if (name === ".callback") async = true;
            if (!is_ref) return replacements[macro_params[name]];
            macro_body = replacements.slice(macro_params[name]);
            macro_body.unshift("[");
            return macro_body;
          }
        }
        return macro_body.map(function(element){
          if (element instanceof Array) { return clone(element, replacements); }
          return element;
        })
      }
      env.list2js[macro_name] = function(env, replacements) {
        if (async) {
          callback = ["lambda", ["("]].concat(env.parent.slice(++env.parent_index));
          env.parent.length = env.parent_index;
          replacements = replacements.concat([callback]);
        }
        return lists2list(env, clone(body, replacements)).join('');
      }
      return '';
    };
    // put raw javascript at end of last atom
    var append_raw = function(env, raw) {
      var list = env.list.length ? env.list : env.stack[env.stack.length - 1];
      list.push([".raw", raw]);
    }
    // Environment under which a lispz command executes
    var env = {
        line_number: 1, skip: false, atom: "", stack: [], list: ['['],
        // We find atoms using this regex - fast in a good js system
        tkre: new RegExp('(' + stringRE + '\\' + delims + "|[^\\s" + not_delims + "]+)", 'g'),
        // Called for delimiters when they are found in the input stream
        delimiter: { // start gathering a list or performing other delimiter function
            '(': push_state, '[': push_state, '{': push_state,
            ')': pop_state, ']': pop_state, '}': pop_state,
            ';': function(env) { env.skip = true },
            '\n': function(env) { append_raw(env, " //#"+(env.line_number++)+"\n") }
        },
        // called for closing delimiters when encountered in the stream
        list2js: { // process a list once gathered.
            '(': call2js,
            '[': function(env, list) { // list of atoms (array)
                   return '[' + lists2list(env, list.slice(1)).join(',') + ']'
                 },
            'lambda': lambda2js, 'macro': build_macro,
            'async': function(env, list) { return build_macro(env, list, true) },
            '.atom': function(env, list) { return jsify(list[1]) },
            '.raw': function(env, list) { return list[1] },
            '.js': params2js, ".pairs": pairs, 'alias': alias
        },
        alias: {}
    };
    // add all standard binary operations (+, -, etc)
    var binop = function(ops) {
        ops.forEach(function(op) {
            env.list2js[op] = function(env, list) {
                return '(' + lists2list(env, list.slice(1)).join(op) + ')'
            }
        })
    }
    binop("+,-,*,/,&&,||,==,===,<=,>=,!=".split(','));
    // use a different name for a lambdas, such as and for &&
    var alias = function(env, list) {
        for (var i = 0, l = list.length; i < l; i += 2) env.alias[list[i]] = list[i + 1]
    }
    alias(env, "and,&&,or,||,is,==,isnt,!=,not,!".split(','));
    // generate javascript from lispz
    var compile = function(source) {
      env.tkre.lastIndex = 0; env.list = ['[']; env.stack = [];
      env.line_number = 1; env.source = source;
      while (next_atom(env)) {
          if (!env.skip) {
            atom2list(env);
          } else if (env.atom === '\n') {
            env.skip = false;
          }
      };
      js = lists2list(env,env.list.slice(1)).join('');
      return js;
    };
    // lispz script loader
    var load_cache = {};
    load = function(url, callback) {
      if (load_cache[url] !== undefined) return callback(load_cache[url]);
      var script = document.createElement("script");
      script.type = "application/lispz";
      script.onerror = function (err) {
        callback("The script " + err.target.src + " is not accessible.");
      }
      script.onload = function() {
        callback(null, load_cache[url] = eval(compile(script.textContent)));
      }
      document.head.appendChild(script);
      script.src = url  + '.lispz';
    };
    window.onload = function(){ load('core') }
    return { compile:compile, env:env, load:load}
}()
<commit_msg>added { back into js<commit_after>var lispz = function() {
    var alias, load;
    // characters that are not space separated atoms (n becomes linefeed in regex)
    var delims = "(){}[];'`|n".split('');
    var not_delims = delims.join("\\");
    delims = delims.join('|\\')
    var stringRE = "'{1,2}.*?'{1,2}|" + '".*?[^\\\\]"|""|';
    // Keep state stack for when we start a new inner list ()[]{}
    var push_state = function(env) {
        env.stack.push(env.list);
        env.list = [env.atom]
    };
    var pop_state = function(env) {
        var list = env.list;
        if (env.stack.length) return (env.list = env.stack.pop()).push(list);
        return console.log("Too many closing braces on line "+env.line_number);
    };
    // when a list is closed we process it given the opening command/type
    var list2js = function(env, list) {
      return env.list2js[list[0]](env, list)
    };
    // processing pairs of list elements
    var pairs = function(env, fore, tween, aft) {
      return function(env, list) {
        return dot_pairs(env, ["", list, ['.atom',fore], ['.atom',tween], ['.atom',aft]]);
      }
    };
    // processing pairs of list elements
    var dot_pairs = function(env, list) {
      var el = [], pairs = list[1], fore = list2js(env, list[2]);
      var tween = list2js(env, list[3]), aft = list2js(env, list[4]);
      for (var i = 1, l = pairs.length; i < l; i += 2) {
          el.push(list2js(env, pairs[i]) + tween + list2js(env, pairs[i + 1]))
      };
      return fore + el.join(',') + aft
    }
    // Convert a list of lists to a list of js fragments
    var lists2list = function(env, lists) {
      return lists.map(function(list, index, parent) {
        env.parent = parent; env.parent_index = index;
        return list2js(env, list);
      }).filter(function(a) { return a && a.length });
    };
    // convert a list to a javascript call
    var call2js = function(env, list) {
      var js = ' ';
      if (env.list2js[list[1][1]]) {
        return env.list2js[list[1][1]](env, list.slice(1))
      }
      var params = lists2list(env, list.slice(2))
      return " " + list2js(env, list[1]) + "(" + params.join(',') + ')'
    };
    // Convert (js parameters) to javascript
    params2js = function(env, list) {
      return lists2list(env, list.slice(1)).join('');
    }
    // Take symbols javascript doesn't recognise and convert
    replacements = {
        '!': "$bang$", '#': "$hash$", '%': "$percent$", '&': "$ampersand",
        '*': "$star$", '+': "$plus$", '-': "$dash$", '/': "$slash$",
        ':': "$colon$", ';': "$semicolon$", '<': "$less$", '=': "$equal",
        '>': "$greater$", '?': "$question$", '@': "$at$", '\\': "$slosh$",
        '^': "$caret$", '~': "$tilde$"
    }
    var jsify = function(atom) {
      var last = atom.length - 1;
      if (atom[0] === '"' && atom[last] === '"') return atom;
      if (atom[0] === "'" && atom[last] === "'") return atom.slice(1,last);
      return atom.replace(/\W/g, function(symbol) {
          var rep = replacements[symbol];
          return rep ? rep : symbol
      })
    };
    // pull function params from a list
    var list2params = function(list) {
      return list.slice(1).map(function(p, i) { return jsify(p[1]) });
    };
    // convert a list to a function definition
    var lambda2js = function(env, list) {
      return "(function(" + list2params(list[1]).join(',') + "){return " +
          lists2list(env, list.slice(2)).join(",") + "})"
    };
    // retrieve the next atom from the input stream. Returns false on no more
    var next_atom = function(env) {
        if (!(env.atom = env.tkre.exec(env.source))) return false;
        if (env.alias[env.atom = env.atom[1]]) env.atom = env.alias[env.atom];
        return env.atom;
    };
    // convert an atom to a simple list
    var atom2list = function(env) {
      if (env.delimiter[env.atom]) {
        env.delimiter[env.atom](env)
      } else {
        env.list.push([".atom", env.atom])
      }
    };
    // Create a lambda that expands a named macro
    var build_macro = function(env, list, async) {
      var macro_name = list2js(env, list[1]);
      var macro_params = {".callback":list[2].length}, body = list.slice(3);
      list2params(list[2]).forEach(function(p, i) { macro_params[p] = i + 1 })
      var clone = function(macro_body, replacements) {
        if (macro_body[0] === ".atom") {
          var is_ref = (macro_body[1][0] === '*'); // *rest
          var name = is_ref ? macro_body[1].slice(1) : macro_body[1];
          if (macro_params[name]) { // replace with param or list of rest
            if (name === ".callback") async = true;
            if (!is_ref) return replacements[macro_params[name]];
            macro_body = replacements.slice(macro_params[name]);
            macro_body.unshift("[");
            return macro_body;
          }
        }
        return macro_body.map(function(element){
          if (element instanceof Array) { return clone(element, replacements); }
          return element;
        })
      }
      env.list2js[macro_name] = function(env, replacements) {
        if (async) {
          callback = ["lambda", ["("]].concat(env.parent.slice(++env.parent_index));
          env.parent.length = env.parent_index;
          replacements = replacements.concat([callback]);
        }
        return lists2list(env, clone(body, replacements)).join('');
      }
      return '';
    };
    // put raw javascript at end of last atom
    var append_raw = function(env, raw) {
      var list = env.list.length ? env.list : env.stack[env.stack.length - 1];
      list.push([".raw", raw]);
    }
    // Environment under which a lispz command executes
    var env = {
        line_number: 1, skip: false, atom: "", stack: [], list: ['['],
        // We find atoms using this regex - fast in a good js system
        tkre: new RegExp('(' + stringRE + '\\' + delims + "|[^\\s" + not_delims + "]+)", 'g'),
        // Called for delimiters when they are found in the input stream
        delimiter: { // start gathering a list or performing other delimiter function
            '(': push_state, '[': push_state, '{': push_state,
            ')': pop_state, ']': pop_state, '}': pop_state,
            ';': function(env) { env.skip = true },
            '\n': function(env) { append_raw(env, " //#"+(env.line_number++)+"\n") }
        },
        // called for closing delimiters when encountered in the stream
        list2js: { // process a list once gathered.
            '(': call2js,
            '[': function(env, list) { // list of atoms (array)
                   return '[' + lists2list(env, list.slice(1)).join(',') + ']'
                 },
            '{': pairs(env, '({', ':', '})'), // {a:1,b:2}
            'lambda': lambda2js, 'macro': build_macro,
            'async': function(env, list) { return build_macro(env, list, true) },
            '.atom': function(env, list) { return jsify(list[1]) },
            '.raw': function(env, list) { return list[1] },
            '.js': params2js, ".pairs": dot_pairs, 'alias': alias
        },
        alias: {}
    };
    // add all standard binary operations (+, -, etc)
    var binop = function(ops) {
        ops.forEach(function(op) {
            env.list2js[op] = function(env, list) {
                return '(' + lists2list(env, list.slice(1)).join(op) + ')'
            }
        })
    }
    binop("+,-,*,/,&&,||,==,===,<=,>=,!=".split(','));
    // use a different name for a lambdas, such as and for &&
    var alias = function(env, list) {
        for (var i = 0, l = list.length; i < l; i += 2) env.alias[list[i]] = list[i + 1]
    }
    alias(env, "and,&&,or,||,is,==,isnt,!=,not,!".split(','));
    // generate javascript from lispz
    var compile = function(source) {
      env.tkre.lastIndex = 0; env.list = ['[']; env.stack = [];
      env.line_number = 1; env.source = source;
      while (next_atom(env)) {
         if (!env.skip) {
            atom2list(env);
          } else if (env.atom === '\n') {
            env.skip = false; env.line_number++;
          }
      };
      js = lists2list(env,env.list.slice(1)).join('');
      return js;
    };
    // lispz script loader (needed now to get core.lispz)
    var load_cache = {};
    load = function(uri, callback) {
      if (load_cache[uri] !== undefined) return callback(load_cache[uri]);

      var req = new XMLHttpRequest();
      req.open("GET", uri+".lispz", true);
      req.onerror = function (err) {
        callback("The script " + uri + " is not accessible.");
      }
      req.onload = function() {
        if (req.status != 200) return req.error(req.statusText);
        callback(null, load_cache[uri] = new Function(env, compile(req.responseText)));
      }
      req.send();
    };
    //window.onload = function(){ load('core') }
    return { compile:compile, env:env, load:load}
}()
<|endoftext|>


<commit_before>var csv_data; // global variable with complete data

// constant
var nutritionals = [
	"nutrition_score_uk_100g",
	"nutrition_score_fr_100g",
	"sodium_100g",
	"salt_100g",
	"proteins_100g",
	//"energy_100g",
	"saturated_fat_100g",
	"sugars_100g",
	"fat_100g",
	"carbohydrates_100g"
];
var levels = {
	0: "root",
	1: "category",
	2: "subcategory",
	3: "product_name"
}

data = d3.csv('static/data/data.csv')
	.row(function(r) {
		return {
			product_name: r.product_name,
			code_country: r.code_country,
			category: r.pnns_groups_1,
			subcategory: r.pnns_groups_2,
			nutrition_score_uk_100g: +r["nutrition-score-uk_100g"],
			nutrition_score_fr_100g: +r["nutrition-score-fr_100g"],
			sodium_100g: +r.sodium_100g,
			salt_100g: +r.salt_100g,
			proteins_100g: +r.proteins_100g,
			//energy_100g: +r.energy_100g,
			saturated_fat_100g: +r["saturated-fat_100g"],
			sugars_100g: +r.sugars_100g,
			fat_100g: +r.fat_100g,
			carbohydrates_100g: +r.carbohydrates_100g
		}
	})
	.get(function(error, rows) {
		console.log(rows);
		csv_data = rows;
	});

var test_new_data_0 = {country_id: "DEU", category: null};
var test_new_data_1 = {country_id: null, category: ["root", "Sugary sncacks"]};

function rename_nested(data, level) {
	//console.log("[RENAME_NESTED] input (data, level)");
	//console.log(data);
	//console.log(level);
	var children = [];
	if (data.values != null)
		children = data.values.map(function(d) {return rename_nested(d, level+1);});
	return {
		name: data.key,
		level: level,
		children: children
	};
}

function prune_nested(nested_data, level, category) {
	/*
	 * Prune the nested data: only one element up until "level", then all of its children
	 */
	//console.log("[PRUNE] arguments received (nested_data, level, category");
	//console.log(nested_data);
	//console.log(level);
	//console.log(category);
	var children;
	// if we are at the children we want to display
	if (nested_data.level > level) children = [];
	// if we are at the node clicked on by the user
	else if (nested_data.level === level && nested_data.name === category) {
		children = nested_data.children.map(function(d) {return prune_nested(d, level, category);});
	}
	// if we are at the brother nodes that we do not want to display
	else if (nested_data.level === level)  return null;
	// if we are at a (grand)parent or (grand)uncle nodes
	else {
		children = nested_data.children
			.map(function(d) {return prune_nested(d, level, category);})
			.filter(function(d) {return d != null;});
		// if all children are null, then we should not display the node
		if (children.length === 0) return null;
	}
	//nested_data["children"] = children;
	//console.log("[PRUNE] output nested_data");
	//console.log(nested_data);
	return {
		name: nested_data.name,
		level: nested_data.level,
		children: children
	};
}

function compute_data(new_data) {
	/* new_data is an object with possible fields :
	 *   country_id (string): used in case the user click on a country on the map
	 *   query (string): used in case the user click on the tree afte
	 *   level (int)
	 *   category (string)
	 */
	console.log("[COMPUTE_DATA]: received argument");
	console.log(new_data);
	var country_id_list;
	var nested_data;
	var stats;
	var useful_data;
	// Second case next step : a category or a product has been selected
	if ("category" in new_data && new_data.category != null &&
		 "level" in new_data && new_data.level != null &
		 "query" in new_data && new_data.query === "reset") {
		console.log("category is input ! (after reset)");
		// we filter on the selected category

		useful_data = csv_data.filter(function(d) {
			return d[levels[new_data.level]] === new_data.category;
		});
		// we compute the tree
		nested_data = {
			name: "root",
			level: 0,
			children: d3.nest()
				.key(function(d) { return d.category; })
				.key(function(d) { return d.subcategory; })
				.key(function(d) { return d.product_name; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {return rename_nested(d, 1);})
		};
		// we prune the tree
		console.log("[COMPUTE_DATA]: full tree before pruning");
		console.log(nested_data);

		nested_data = prune_nested(nested_data, new_data.level, new_data.category);

		console.log("[COMPUTE_DATA]: tree after pruning");
		console.log(nested_data);

		// and we show all the countries concerned
		country_id_list = [... new Set(csv_data.map(function(d) {return d.code_country}))];
		query = "reset";
	}
	// Reset case
	else if("query" in new_data && new_data.query === "reset") {
		// we compute the tree
		useful_data = csv_data;
		nested_data = {
			name: "root",
			level: 0,
			children: d3.nest()
				.key(function(d) { return d.category; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {
					return {
						name: d.key,
						level: 1,
						children: []
					};
				})
		};
		// and we only show the selected contry
		country_id_list = [];
		query = "reset";
	}
	// Fist case : the country_id
	else if("country_id" in new_data && new_data.country_id != null) {
		// we filter on the selected country
		useful_data = csv_data.filter(function(d) {
			return (d.code_country === new_data.country_id)
		});
		// we compute the tree
		nested_data = {
			name: "root",
			level: 0,
			children: d3.nest()
				.key(function(d) { return d.category; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {
					return {
						name: d.key,
						level: 1,
						children: []
					};
				})
		};
		// and we only show the selected contry
		country_id_list = [new_data.country_id];
		query = new_data.country_id;
	}
	// First case next step : a category or a product has been selected
	else if ("category" in new_data && new_data.category != null &&
		 "level" in new_data && new_data.level != null &
		 "query" in new_data && new_data.query != null) {
		console.log("manage category !");
		// we filter on the selected country
		useful_data = csv_data.filter(function(d) {
			return (d.code_country === new_data.query)
		});
		// we compute the tree
		nested_data = {
			name: "root",
			level: 0,
			children: d3.nest()
				.key(function(d) { return d.category; })
				.key(function(d) { return d.subcategory; })
				.key(function(d) { return d.product_name; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {return rename_nested(d, 1);})
		};
		// we prune the tree
		console.log("[COMPUTE_DATA]: full tree before pruning");
		console.log(nested_data);

		nested_data = prune_nested(nested_data, new_data.level, new_data.category);

		console.log("[COMPUTE_DATA]: tree after pruning");
		console.log(nested_data);

		// and we only show the selected contry
		country_id_list = [query];
		query = new_data.query;
	}
	// we compute the stats
	stats = {
		labels: nutritionals,
		series: [
			{
			label: 'Nutritional Value',
			values: nutritionals.map(function(n) {
				var m = d3.mean(useful_data, function(d) { return d[n] });
				if(typeof m !== 'undefined') return m;
				return 0;
				})
			},
			{
			label: 'Mean nutritional value of category',
			values: nutritionals.map(function(n) {
				var m = d3.mean(csv_data, function(d) { return d[n] });
				if(typeof m !== 'undefined') return m;
				return 0;
				})
			}
		]
	}
	update_all({
		country_id_list: country_id_list,
		tree: nested_data,
		stats: stats,
		query: query
	});
}

function update_all(data) {
	console.log("update_all");
	console.log(data);

	update_tree(data.tree,data.query);
	update_map(data.country_id_list);
	update_bars(data.stats);
}
<commit_msg>bug fixes<commit_after>var csv_data; // global variable with complete data

// constant
var nutritionals = [
	"nutrition_score_uk_100g",
	"nutrition_score_fr_100g",
	"sodium_100g",
	"salt_100g",
	"proteins_100g",
	//"energy_100g",
	"saturated_fat_100g",
	"sugars_100g",
	"fat_100g",
	"carbohydrates_100g"
];
var levels = {
	0: "root",
	1: "category",
	2: "subcategory",
	3: "product_name"
}

data = d3.csv('static/data/data.csv')
	.row(function(r) {
		return {
			product_name: r.product_name,
			code_country: r.code_country,
			root: "root",
			category: r.pnns_groups_1,
			subcategory: r.pnns_groups_2,
			nutrition_score_uk_100g: +r["nutrition-score-uk_100g"],
			nutrition_score_fr_100g: +r["nutrition-score-fr_100g"],
			sodium_100g: +r.sodium_100g,
			salt_100g: +r.salt_100g,
			proteins_100g: +r.proteins_100g,
			//energy_100g: +r.energy_100g,
			saturated_fat_100g: +r["saturated-fat_100g"],
			sugars_100g: +r.sugars_100g,
			fat_100g: +r.fat_100g,
			carbohydrates_100g: +r.carbohydrates_100g
		}
	})
	.get(function(error, rows) {
		console.log(rows);
		csv_data = rows;
	});

var test_new_data_0 = {country_id: "DEU", category: null};
var test_new_data_1 = {country_id: null, category: ["root", "Sugary sncacks"]};

function rename_nested(data, level) {
	//console.log("[RENAME_NESTED] input (data, level)");
	//console.log(data);
	//console.log(level);
	var children = [];
	if (data.values != null)
		children = data.values.map(function(d) {return rename_nested(d, level+1);});
	return {
		name: data.key,
		level: level,
		children: children
	};
}

function compute_data(new_data) {
	/* new_data is an object with possible fields :
	 *   country_id (string): used in case the user click on a country on the map
	 *   query (string): used in case the user click on the tree afte
	 *   level (int)
	 *   category (string)
	 */
	console.log("[COMPUTE_DATA]: received argument");
	console.log(new_data);
	var country_id_list;
	var nested_data;
	var stats;
	var useful_data;
	// Second case next step : a category or a product has been selected
	if ("category" in new_data && new_data.category != null &&
		 "level" in new_data && new_data.level != null &
		 "query" in new_data && new_data.query === "reset") {
		console.log("category is input ! (after reset)");
		// we filter on the selected category

		useful_data = csv_data.filter(function(d) {
			return d[levels[new_data.level]] === new_data.category;
		});
		// we compute the tree
		var children;
		if(new_data.level === 0) children = d3.nest()
				.key(function(d) { return d.category; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {return rename_nested(d, 1);});
		else if(new_data.level === 1) children = d3.nest()
				.key(function(d) { return d.category; })
				.key(function(d) { return d.subcategory; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {return rename_nested(d, 1);});
		else if(new_data.level >= 2) children = d3.nest()
				.key(function(d) { return d.category; })
				.key(function(d) { return d.subcategory; })
				.key(function(d) { return d.product_name; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {return rename_nested(d, 1);});
		nested_data = {
			name: "root",
			level: 0,
			children: children
		};

		// and we show all the countries concerned
		country_id_list = [... new Set(csv_data.map(function(d) {return d.code_country}))];
		query = "reset";
	}
	// Reset case
	else if("query" in new_data && new_data.query === "reset") {
		// we compute the tree
		useful_data = csv_data;
		nested_data = {
			name: "root",
			level: 0,
			children: d3.nest()
				.key(function(d) { return d.category; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {
					return {
						name: d.key,
						level: 1,
						children: []
					};
				})
		};
		// and we only show the selected contry
		country_id_list = [];
		query = "reset";
	}
	// Fist case : the country_id
	else if("country_id" in new_data && new_data.country_id != null) {
		// we filter on the selected country
		useful_data = csv_data.filter(function(d) {
			return (d.code_country === new_data.country_id)
		});
		// we compute the tree
		nested_data = {
			name: "root",
			level: 0,
			children: d3.nest()
				.key(function(d) { return d.category; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {
					return {
						name: d.key,
						level: 1,
						children: []
					};
				})
		};
		// and we only show the selected contry
		country_id_list = [new_data.country_id];
		query = new_data.country_id;
	}
	// First case next step : a category or a product has been selected
	else if ("category" in new_data && new_data.category != null &&
		 "level" in new_data && new_data.level != null &
		 "query" in new_data && new_data.query != null) {
		console.log("manage category !");
		// we filter on the selected country
		useful_data = csv_data.filter(function(d) {
			return d.code_country === new_data.query &&
			 	d[levels[new_data.level]] === new_data.category;
		});
		// we compute the tree
		var children;
		if(new_data.level === 0) children = d3.nest()
				.key(function(d) { return d.category; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {return rename_nested(d, 1);});
		else if(new_data.level === 1) children = d3.nest()
				.key(function(d) { return d.category; })
				.key(function(d) { return d.subcategory; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {return rename_nested(d, 1);});
		else if(new_data.level >= 2) children = d3.nest()
				.key(function(d) { return d.category; })
				.key(function(d) { return d.subcategory; })
				.key(function(d) { return d.product_name; })
				.rollup(function(l) { return null; })
				.entries(useful_data)
				.map(function(d) {return rename_nested(d, 1);});
		nested_data = {
			name: "root",
			level: 0,
			children: children
		};

		// and we only show the selected contry
		country_id_list = [query];
		query = new_data.query;
	}
	// we compute the stats
	stats = {
		labels: nutritionals,
		series: [
			{
			label: 'Nutritional Value',
			values: nutritionals.map(function(n) {
				var m = d3.mean(useful_data, function(d) { return d[n] });
				if(typeof m !== 'undefined') return m;
				return 0;
				})
			},
			{
			label: 'Mean nutritional value of category',
			values: nutritionals.map(function(n) {
				var m = d3.mean(csv_data, function(d) { return d[n] });
				if(typeof m !== 'undefined') return m;
				return 0;
				})
			}
		]
	}
	update_all({
		country_id_list: country_id_list,
		tree: nested_data,
		stats: stats,
		query: query
	});
}

function update_all(data) {
	console.log("update_all");
	console.log(data);

	update_tree(data.tree,data.query);
	update_map(data.country_id_list);
	update_bars(data.stats);
}
<|endoftext|>


<commit_before>/**
 * this plugin goes through a form's inputs
 * it removes any unset fields or disabled fields
 * then builds the query string
 *
 * Author: Jason Welch
 * http://www.jwelchdesign.com
 */
(function ($) {
	$.fn.serializeFilledForm = function( options ) {

		// set some default options
		var settings = $.extend({
				decode: true, // return params URI decoded
				invalidClass: null // pass a class to invalidate a field
			}, options),
			clone = this.clone( true , true ),
			serialized;

		// get the select and textarea values
		$.each(f.find('select'), function(i) {
			clone.find('select').eq(i).val( $(this).val() );
		});
		$.each(f.find('textarea'), function(i) {
			clone.find('textarea').eq(i).val( $(this).val() );
		});

		// filter out the empty fields
		clone.find('input:text, select, textarea').filter(invalidField).remove();

		// serialize it
		serialized = clone.serialize();

		if (settings.decode)
			return decodeURI( serialized );
		else
			return serialized;

		function invalidField() {

			// input has to have a value
			if ( ! this.value )
				return true;

			if (settings.invalidClass && $(this).hasClass( settings.invalidClass ))
				return true;

			return false;
		}
	};
})( jQuery );
<commit_msg>Wrong name<commit_after><|endoftext|>


<commit_before>(function() {
  var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
templates['timelineitem'] = template({"1":function(container,depth0,helpers,partials,data) {
    var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function";

  return "
"
    + container.escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper)))
    + ": "
    + ((stack1 = ((helper = (helper = helpers.value || (depth0 != null ? depth0.value : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"value","hash":{},"data":data}) : helper))) != null ? stack1 : "")
    + "
\n";
},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) {
    var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression;

  return "
\n
\n        Record "
    + alias4(((helper = (helper = helpers.current_id || (depth0 != null ? depth0.current_id : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"current_id","hash":{},"data":data}) : helper)))
    + "
\n
\n"
    + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.values : depth0),{"name":"each","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
    + "
\n        Read more...\n
\n
\n
\n    "
    + alias4(((helper = (helper = helpers.content || (depth0 != null ? depth0.content : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"content","hash":{},"data":data}) : helper)))
    + "\n
\n";
},"useData":true});
})();<commit_msg>Add item edit link to timeline items<commit_after>(function() {
  var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
templates['timelineitem'] = template({"1":function(container,depth0,helpers,partials,data) {
    var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function";

  return "
"
    + container.escapeExpression(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"name","hash":{},"data":data}) : helper)))
    + ": "
    + ((stack1 = ((helper = (helper = helpers.value || (depth0 != null ? depth0.value : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"value","hash":{},"data":data}) : helper))) != null ? stack1 : "")
    + "
\n";
},"compiler":[7,">= 4.0.0"],"main":function(container,depth0,helpers,partials,data) {
    var stack1, helper, alias1=depth0 != null ? depth0 : (container.nullContext || {}), alias2=helpers.helperMissing, alias3="function", alias4=container.escapeExpression;

  return "
\n
\n        Record "
    + alias4(((helper = (helper = helpers.current_id || (depth0 != null ? depth0.current_id : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"current_id","hash":{},"data":data}) : helper)))
    + "
\n
\n"
    + ((stack1 = helpers.each.call(alias1,(depth0 != null ? depth0.values : depth0),{"name":"each","hash":{},"fn":container.program(1, data, 0),"inverse":container.noop,"data":data})) != null ? stack1 : "")
    + "
\n        Read more |\n        Edit item\n
\n
\n
\n    "
    + alias4(((helper = (helper = helpers.content || (depth0 != null ? depth0.content : depth0)) != null ? helper : alias2),(typeof helper === alias3 ? helper.call(alias1,{"name":"content","hash":{},"data":data}) : helper)))
    + "\n
\n";
},"useData":true});
})();<|endoftext|>


<commit_before><commit_msg>add game javascript file<commit_after>console.log("Hello");

var game = new Phaser.Game(800, 600, Phaser.AUTO, '', { preload: preload, create: create, update: update });

function preload() {
  game.load.image('ghost', '/ghost.png');
  game.load.image('person', '/person.png');
  game.load.image('star', '/star.png');
}

var characters;
var person;
var ghosts;
var ghost1, ghost2, ghost3, ghost4;
var key1, key2, key3, key4;
var platforms;

// if($("#pacman").checked) {
//   characters = [person];
// } else if($("#ghost").checked) {
//   characters = [ghost1, ghost2, ghost3, ghost4]
// }

function create() {

  game.physics.startSystem(Phaser.Physics.ARCADE);

  platforms = game.add.group();

  platforms.enableBody = true;

  createBoard();

  // Create person.

  person = game.add.sprite(1, game.world.height - 150, 'person');
  person.scale.setTo(0.5, 0.5);
  person.anchor.setTo(0.5, 0.5);

  // Create ghosts.

  ghost1 = game.add.sprite(100, game.world.height - 150, 'ghost');
  ghost1.anchor.setTo(0.5, 0.5);
  ghost1.scale.setTo(2,2);

  ghost2 = game.add.sprite(200, game.world.height - 150, 'ghost');
  ghost2.anchor.setTo(0.5, 0.5);
  ghost2.scale.setTo(2,2)

  ghost3 = game.add.sprite(300, game.world.height - 150, 'ghost');
  ghost3.anchor.setTo(0.5, 0.5);
  ghost3.scale.setTo(2,2)

  ghost4 = game.add.sprite(400, game.world.height - 150, 'ghost');
  ghost4.anchor.setTo(0.5, 0.5);
  ghost4.scale.setTo(2,2)

  ghosts = [ghost1, ghost2, ghost3, ghost4];
  characters = [person, ghost1, ghost2, ghost3, ghost4];
  //  Enable physics for sprites, make world boundaries.

  game.physics.arcade.enable([person, ghost1, ghost2, ghost3, ghost4]);
  person.body.collideWorldBounds = true;
  ghost1.body.collideWorldBounds = true;
  ghost2.body.collideWorldBounds = true;
  ghost3.body.collideWorldBounds = true;
  ghost4.body.collideWorldBounds = true;

  // Make ghosts inactive by default.

  ghosts.forEach(function(item) { item.body.enable = false; });

  // Create hotkeys.

  key1 = game.input.keyboard.addKey(Phaser.Keyboard.ONE);
  key2 = game.input.keyboard.addKey(Phaser.Keyboard.TWO);
  key3 = game.input.keyboard.addKey(Phaser.Keyboard.THREE);
  key4 = game.input.keyboard.addKey(Phaser.Keyboard.FOUR);

  key1.onDown.add(function() { makeActive(1), makeInactive([2, 3, 4])} );
  key2.onDown.add(function() { makeActive(2), makeInactive([1, 3, 4])} );
  key3.onDown.add(function() { makeActive(3), makeInactive([1, 2, 4])} );
  key4.onDown.add(function() { makeActive(4), makeInactive([1, 2, 3])} );

} // End create()

function update() {

  characters.forEach(function(item) {
    if (item.body.enable == true) {
      if (game.input.keyboard.isDown(Phaser.Keyboard.LEFT)) {
        item.x -= 4;
        returnCoordinates(item);
      }
      else if (game.input.keyboard.isDown(Phaser.Keyboard.RIGHT)) {
        item.x += 4;
        returnCoordinates(item);
      }
      else if (game.input.keyboard.isDown(Phaser.Keyboard.UP)) {
        item.y -= 4;
        returnCoordinates(item);
      }
      else if (game.input.keyboard.isDown(Phaser.Keyboard.DOWN)) {
        item.y +=4;
        returnCoordinates(item);
      }
    }
  });

  // Ghost random
  ghosts.forEach(function(item) {
      if (item.body.enable == false) {
        item.body.velocity.x = 100;
      }
  });
}

function makeActive(hotkey) {
  ghosts[(hotkey - 1)].body.enable = true;
};

function makeInactive(hotkeys) {
  hotkeys.forEach(function(item) {
    ghosts[(item - 1)].body.enable = false;
  })
};

function returnCoordinates(sprite) {
  var coordinates = [sprite.x, sprite.y];
  console.log(coordinates);
  return coordinates;
}<|endoftext|>