<commit_before>'use strict';

/* Controllers */

function MainCtrl($scope, $location, $rootScope) {
  $scope.path = function() {
    return $location.path();
  };
  $rootScope.loading = false;
  $rootScope.$on('$routeChangeStart', function() {
    $rootScope.loading = true;
  });
  $rootScope.$on('$routeChangeSuccess', function() {
    $rootScope.loading = false;
  });
}

function SideBarCtrl($scope, $http, $routeParams, socket) {
  socket.on('matches:new', function(data) {
    $scope.matches.push(data);
  });

  socket.on('matches:update', function(data) {
    for (var i=0, len=$scope.matches.length; i<len; i++) {
      if ($scope.matches[i]._id == data._id) {
        $scope.matches[i] = data;
        return;
      }
    }
  });

  $http.get('/api/matches')
    .success(function(data, status, headers, config) {
      $scope.matches = data.matches;
    });

  $scope.isActive = function() {
    return this.match._id === parseInt($routeParams.id,10);
  };
}

function StatsCtrl($scope, $rootScope, $location, $http, socket, resolvedData) {
  var firstLoad = true;

  $scope.location = $location;
  $scope.$watch("location.search().id", function (val, old) {
    if (!val) { return; }
    // We don't want to request the data again if the controller just loaded.
    //  If we click away from the original stats, then set firstLoad to false.
    //  Otherwise if firstLoad == true, exit.
    if (old && val !== old) {
      firstLoad = false;
    }
    if (firstLoad) { return; }

    $rootScope.loading = true;

    $http({
      method: 'GET',
      url: '/api/stats/' + val
    }).success(function(data) {
      $rootScope.loading = false;
      calculateStats(data, true);
    });

    socket.emit('stats:subscribe', val);
  });

  socket.on('stats:send', function (data) {
    console.log('Stat update received!');
    calculateStats(data, false);
  });

  var calculateStats = function(data, reinitializeSelectedRounds) {
    // Stupid placeholder object for when things go wrong
    if (!data  || typeof data !== 'object') {
      data = { stats: {
        redname: 'RED',
        bluname: 'BLU',
        redscore: [],
        bluscore: [],
        players: []
      }};
    }
    var stats = $scope.stats = data.stats;
    $scope.playerMetaData = data.playerdata;
    fillOutPlayerMetaData();

    // If redscore.length is greater than the current number of rounds, then that
    //  means a new round just started -- add it to $scope.selectedRounds.
    if (stats.redscore.length > $scope.numRounds) {
      $scope.selectedRounds.push(stats.redscore.length-1);
    }

    var numRounds = $scope.numRounds = stats.redscore.length;

    if (reinitializeSelectedRounds) { $scope.initializeSelectedRoundsArray(); }

    // Ask sizzling to send only individual round scores instead of cumulative
    // It will make things a lot easier.
    var redScore = $scope.redScore = stats.redscore[numRounds-1];
    var bluScore = $scope.bluScore = stats.bluscore[numRounds-1];
    $scope.scoreComparison = redScore > bluScore ? '>' : redScore < bluScore ? '<' : '==';

    // Total playable time
    var playableTime = $scope.playableTime = sumArray(stats.roundduration);

    // Calculate total damage for each team
    var totalDamage = [0,0,0,0];
    angular.forEach(stats.players, function(player) {
      totalDamage[player.team] += sumArray(player.damagedone);
    });
    // Calculate total frags for each team
    var totalFrags = [0,0,0,0];
    angular.forEach(stats.players, function(player) {
      totalFrags[player.team] += sumArray(player.kills);
    });

    // Assemble score overview table rows
    var redRoundScores = [stats.redscore[0]];
    var bluRoundScores = [stats.bluscore[0]];
    for (var i=1; i<numRounds; i++) {
      redRoundScores.push(stats.redscore[i] - stats.redscore[i-1]);
      bluRoundScores.push(stats.bluscore[i] - stats.bluscore[i-1]);
    }
    redRoundScores.push(stats.redscore[numRounds-1]);
    bluRoundScores.push(stats.bluscore[numRounds-1]);
    redRoundScores.push(totalDamage[2]);
    redRoundScores.push(totalFrags[2]);
    bluRoundScores.push(totalDamage[3]);
    bluRoundScores.push(totalFrags[3]);
    $scope.redtr = '' + stats.redname + '	' +
                    redRoundScores.join('	') + '	';
    $scope.blutr = '' + stats.bluname + '	' +
                    bluRoundScores.join('	') + '	';

    // Calculate individual players' stats from the select range of rounds
    angular.forEach(stats.players, function(player) {
      player.mostPlayedClass = mostPlayedClass(player.mostplayedclass);
      player.stats = [
        sumArray2(player.points),
        // Frags + Assists / Deaths
        ratio(player.deaths, true, player.kills, player.killassists),
        sumArray2(player.kills),
        sumArray2(player.killassists),
        sumArray2(player.deaths),
        sumArray2(player.suicides),
        // Damage Per Minute
        ratio(playableTime/60, false, player.damagedone),
        sumArray2(player.damagedone),
        sumArray2(player.medpicks),
        sumArray2(player.healsreceived),
        sumArray2(player.captures),
        sumArray2(player.defenses),
        sumArray2(player.dominations),
        sumArray2(player.revenge),
        sumArray2(player.headshots),
        sumArray2(player.backstabs)
        // sumArray2(player.buildingsbuilt),
        // sumArray2(player.buildingsdestroyed),
        // sumArray2(player.crits),
        // sumArray2(player.teleports),
        // sumArray2(player.resupplypoints),
        // sumArray2(player.bonuspoints),
      ];
      player.tr = '' + player.name + '' + player.stats.join('	') + '	';
      // Additional medic-specific stats
      if (player.mostPlayedClass == 5) {
        player.medicStats = [
          sumArray2(player.healpoints),
          sumArray2(player.invulns),
          sumArray2(player.ubersdropped)
        ];
        player.medictr = '' + player.name + '' + player.medicStats.join('	') + '	';
      }
    });
  };

  // Helpers

  $scope.selectedRounds = [];
  $scope.initializeSelectedRoundsArray = function() {
    $scope.selectedRounds = [];
    for (var i=0; i<$scope.numRounds; i++) {
      $scope.selectedRounds[i] = i;
    }
  };
  $scope.ctrl = false;
  window.onkeydown = function(e) {
    if (e.ctrlKey) { $scope.ctrl = true; }
  };
  window.onkeyup = function(e) {
    if (e.ctrlKey) { $scope.ctrl = true; }
    else { $scope.ctrl = false; }
  };
  $scope.clickRoundHeader = function(round) {
    if ($scope.selectedRounds.length === 0) {
      $scope.selectedRounds.push(round);
    } else if ($scope.selectedRounds.length === 1 && $scope.selectedRounds[0] === round && !$scope.ctrl) {
      $scope.initializeSelectedRoundsArray();
    } else if ($scope.ctrl) {
      if ($scope.selectedRounds.indexOf(round) > -1) {
        $scope.selectedRounds.splice($scope.selectedRounds.indexOf(round),1);
      } else {
        $scope.selectedRounds.push(round);
      }
    } else {
      $scope.selectedRounds = [round];
    }
    $scope.selectedRounds.sort(function(a,b){return a-b});
    calculateStats({stats: $scope.stats, playerdata: $scope.playerMetaData}, false);
  };

  $scope.overallSort = 'name';
  $scope.overallReverse = false;
  $scope.medicSort = 'name';
  $scope.medicReverse = false;
  $scope.sortBy = function(col, tableName) {
    // If previously sorting by 'name', and clicking a different column, then
    //  set reverse to true.
    var sort = tableName+'Sort';
    var rev = tableName+'Reverse';
    if (col === $scope[sort] || ($scope[sort] === 'name' && !$scope[rev]) ) {
      $scope[rev] = !$scope[rev];
    }
    $scope[sort] = col;
  };
  $scope.sortClass = function(col, tableName) {
    var sort = tableName+'Sort';
    var rev = tableName+'Reverse';
    if ($scope[sort] === col) {
      return $scope[rev] ? 'sort-true' : 'sort-false';
    }
    return '';
  };
  $scope.separateTeams = false;
  $scope.separateTeamsPredicate = function() {
    return $scope.separateTeams ? ( ($scope.overallReverse ? '-' : '+') + 'team' ) : '';
  };
  var fillOutPlayerMetaData = function() {
    for (var i=0,player; player=$scope.stats.players[i]; i++) {
      var steamid = player.steamid;

      if ($scope.playerMetaData[steamid]) {
        $scope.playerMetaData[steamid].name = player.name;
        $scope.playerMetaData[steamid].team = player.team;
        player.avatar = $scope.playerMetaData[steamid].avatar;
      }
    }
  };
  $scope.filterBinds = true;
  $scope.bindFilter = function(chat) {
    return (!$scope.filterBinds || !chat.isBind);
  };
  var mostPlayedClass = function(mpcArray) {
    if ($scope.numRounds === 1) {
      return mpcArray[0];
    }
    // Determine what class was played the most by summing the rounddurations
    //  for the according tf2class in the "mostplayedclass" array.
    var totals = [0,0,0,0,0,0,0,0,0,0];
    for (var i=0; i<$scope.numRounds; i++) {
      // mpcArray[i] is the index (1-9) of the tf2class that the player played
      //  the most in the ith round. The index of the max value in totals[] is
      //  the id of the tf2class that the player played the most in the match.
      totals[ mpcArray[i] ] += $scope.stats.roundduration[i];
    }
    // Find the index of the max value in totals[].
    var theClass=0, theMax=0;
    for (var j=0; j<9 ;j++) {
      if (totals[j] > theMax) {
        theMax = totals[j];
        theClass = j;
      }
    }
    return theClass;
  };
  var sumArray = function(array) {
    var sum = 0, filteredArray = [];
    for (var i=0, ilen=$scope.selectedRounds.length; i<ilen; i++) {
      filteredArray.push(array[$scope.selectedRounds[i]]);
    }
    for (var j=0, jlen=filteredArray.length; j<jlen; j++) {
      if (filteredArray[j]) sum += filteredArray[j];
    }
    return sum;
  };
  var sumArray2 = function(array) {
    if (!array.length) return '-'; // this is a hack
    var sum = 0, filteredArray = [];
    for (var i=0, len=$scope.selectedRounds.length; i<len; i++) {
      filteredArray.push(array[$scope.selectedRounds[i]]);
    }
    for (var j=0, jlen=filteredArray.length; j<jlen; j++) {
      if (filteredArray[j]) sum += filteredArray[j];
    }
    return sum;
  };
  var ratio = function(den, denIsArray, numArray1, numArray2) {
    if (!numArray1.length) return '-'; // this is a hack
    var numerator, denominator;
    if (!numArray2 || !numArray2.length) {
      numerator = sumArray(numArray1);
    } else {
      numerator = sumArray(numArray1) + sumArray(numArray2);
    }
    if (numerator === 0) return 0;
    if (denIsArray) {
      denominator = sumArray(den);
    } else {
      denominator = den;
    }
    if (denominator === 0) return '∞';
    return Math.round( (numerator/denominator)*100 )/100;
  };
  $scope.secondsToHMS = function(seconds) {
    var h = parseInt(seconds/3600);
    var m = parseInt((seconds-h*3600)/60);
    var s = seconds-h*3600-m*60;
    if (h === 0) { return ('0'+m).slice(-2)+':'+('0'+s).slice(-2); }
    return h+':'+('0'+m).slice(-2)+':'+('0'+s).slice(-2);
  };

  // The very first time you load the controller, use the resolvedData.
  calculateStats(resolvedData, true);
}
// This is for the first time you load the controller
//  -- so that you don't see all the empty divs and tables.
StatsCtrl.resolve = {
  resolvedData: function($q, $http, $route) {
    var deferred = $q.defer();
    $http({
      method: 'GET',
      url: '/api/stats/' + $route.current.params.id
    })
      .success(function(data) {
        deferred.resolve(data);
      })
      .error(function(data) {
        deferred.reject(data);
      });
    return deferred.promise;
  }
};
<commit_msg>Fixed some chat message names not showing up (just a temporary fix)<commit_after>'use strict';

/* Controllers */

function MainCtrl($scope, $location, $rootScope) {
  $scope.path = function() {
    return $location.path();
  };
  $rootScope.loading = false;
  $rootScope.$on('$routeChangeStart', function() {
    $rootScope.loading = true;
  });
  $rootScope.$on('$routeChangeSuccess', function() {
    $rootScope.loading = false;
  });
}

function SideBarCtrl($scope, $http, $routeParams, socket) {
  socket.on('matches:new', function(data) {
    $scope.matches.push(data);
  });

  socket.on('matches:update', function(data) {
    for (var i=0, len=$scope.matches.length; i<len; i++) {
      if ($scope.matches[i]._id == data._id) {
        $scope.matches[i] = data;
        return;
      }
    }
  });

  $http.get('/api/matches')
    .success(function(data, status, headers, config) {
      $scope.matches = data.matches;
    });

  $scope.isActive = function() {
    return this.match._id === parseInt($routeParams.id,10);
  };
}

function StatsCtrl($scope, $rootScope, $location, $http, socket, resolvedData) {
  var firstLoad = true;

  $scope.location = $location;
  $scope.$watch("location.search().id", function (val, old) {
    if (!val) { return; }
    // We don't want to request the data again if the controller just loaded.
    //  If we click away from the original stats, then set firstLoad to false.
    //  Otherwise if firstLoad == true, exit.
    if (old && val !== old) {
      firstLoad = false;
    }
    if (firstLoad) { return; }

    $rootScope.loading = true;

    $http({
      method: 'GET',
      url: '/api/stats/' + val
    }).success(function(data) {
      $rootScope.loading = false;
      calculateStats(data, true);
    });

    socket.emit('stats:subscribe', val);
  });

  socket.on('stats:send', function (data) {
    console.log('Stat update received!');
    calculateStats(data, false);
  });

  var calculateStats = function(data, reinitializeSelectedRounds) {
    // Stupid placeholder object for when things go wrong
    if (!data  || typeof data !== 'object') {
      data = { stats: {
        redname: 'RED',
        bluname: 'BLU',
        redscore: [],
        bluscore: [],
        players: []
      }};
    }
    var stats = $scope.stats = data.stats;
    $scope.playerMetaData = data.playerdata;
    fillOutPlayerMetaData();

    // If redscore.length is greater than the current number of rounds, then that
    //  means a new round just started -- add it to $scope.selectedRounds.
    if (stats.redscore.length > $scope.numRounds) {
      $scope.selectedRounds.push(stats.redscore.length-1);
    }

    var numRounds = $scope.numRounds = stats.redscore.length;

    if (reinitializeSelectedRounds) { $scope.initializeSelectedRoundsArray(); }

    // Ask sizzling to send only individual round scores instead of cumulative
    // It will make things a lot easier.
    var redScore = $scope.redScore = stats.redscore[numRounds-1];
    var bluScore = $scope.bluScore = stats.bluscore[numRounds-1];
    $scope.scoreComparison = redScore > bluScore ? '>' : redScore < bluScore ? '<' : '==';

    // Total playable time
    var playableTime = $scope.playableTime = sumArray(stats.roundduration);

    // Calculate total damage for each team
    var totalDamage = [0,0,0,0];
    angular.forEach(stats.players, function(player) {
      totalDamage[player.team] += sumArray(player.damagedone);
    });
    // Calculate total frags for each team
    var totalFrags = [0,0,0,0];
    angular.forEach(stats.players, function(player) {
      totalFrags[player.team] += sumArray(player.kills);
    });

    // Assemble score overview table rows
    var redRoundScores = [stats.redscore[0]];
    var bluRoundScores = [stats.bluscore[0]];
    for (var i=1; i<numRounds; i++) {
      redRoundScores.push(stats.redscore[i] - stats.redscore[i-1]);
      bluRoundScores.push(stats.bluscore[i] - stats.bluscore[i-1]);
    }
    redRoundScores.push(stats.redscore[numRounds-1]);
    bluRoundScores.push(stats.bluscore[numRounds-1]);
    redRoundScores.push(totalDamage[2]);
    redRoundScores.push(totalFrags[2]);
    bluRoundScores.push(totalDamage[3]);
    bluRoundScores.push(totalFrags[3]);
    $scope.redtr = '' + stats.redname + '	' +
                    redRoundScores.join('	') + '	';
    $scope.blutr = '' + stats.bluname + '	' +
                    bluRoundScores.join('	') + '	';

    // Calculate individual players' stats from the select range of rounds
    angular.forEach(stats.players, function(player) {
      player.mostPlayedClass = mostPlayedClass(player.mostplayedclass);
      player.stats = [
        sumArray2(player.points),
        // Frags + Assists / Deaths
        ratio(player.deaths, true, player.kills, player.killassists),
        sumArray2(player.kills),
        sumArray2(player.killassists),
        sumArray2(player.deaths),
        sumArray2(player.suicides),
        // Damage Per Minute
        ratio(playableTime/60, false, player.damagedone),
        sumArray2(player.damagedone),
        sumArray2(player.medpicks),
        sumArray2(player.healsreceived),
        sumArray2(player.captures),
        sumArray2(player.defenses),
        sumArray2(player.dominations),
        sumArray2(player.revenge),
        sumArray2(player.headshots),
        sumArray2(player.backstabs)
        // sumArray2(player.buildingsbuilt),
        // sumArray2(player.buildingsdestroyed),
        // sumArray2(player.crits),
        // sumArray2(player.teleports),
        // sumArray2(player.resupplypoints),
        // sumArray2(player.bonuspoints),
      ];
      player.tr = '' + player.name + '' + player.stats.join('	') + '	';
      // Additional medic-specific stats
      if (player.mostPlayedClass == 5) {
        player.medicStats = [
          sumArray2(player.healpoints),
          sumArray2(player.invulns),
          sumArray2(player.ubersdropped)
        ];
        player.medictr = '' + player.name + '' + player.medicStats.join('	') + '	';
      }
    });
  };

  // Helpers

  $scope.selectedRounds = [];
  $scope.initializeSelectedRoundsArray = function() {
    $scope.selectedRounds = [];
    for (var i=0; i<$scope.numRounds; i++) {
      $scope.selectedRounds[i] = i;
    }
  };
  $scope.ctrl = false;
  window.onkeydown = function(e) {
    if (e.ctrlKey) { $scope.ctrl = true; }
  };
  window.onkeyup = function(e) {
    if (e.ctrlKey) { $scope.ctrl = true; }
    else { $scope.ctrl = false; }
  };
  $scope.clickRoundHeader = function(round) {
    if ($scope.selectedRounds.length === 0) {
      $scope.selectedRounds.push(round);
    } else if ($scope.selectedRounds.length === 1 && $scope.selectedRounds[0] === round && !$scope.ctrl) {
      $scope.initializeSelectedRoundsArray();
    } else if ($scope.ctrl) {
      if ($scope.selectedRounds.indexOf(round) > -1) {
        $scope.selectedRounds.splice($scope.selectedRounds.indexOf(round),1);
      } else {
        $scope.selectedRounds.push(round);
      }
    } else {
      $scope.selectedRounds = [round];
    }
    $scope.selectedRounds.sort(function(a,b){return a-b});
    calculateStats({stats: $scope.stats, playerdata: $scope.playerMetaData}, false);
  };

  $scope.overallSort = 'name';
  $scope.overallReverse = false;
  $scope.medicSort = 'name';
  $scope.medicReverse = false;
  $scope.sortBy = function(col, tableName) {
    // If previously sorting by 'name', and clicking a different column, then
    //  set reverse to true.
    var sort = tableName+'Sort';
    var rev = tableName+'Reverse';
    if (col === $scope[sort] || ($scope[sort] === 'name' && !$scope[rev]) ) {
      $scope[rev] = !$scope[rev];
    }
    $scope[sort] = col;
  };
  $scope.sortClass = function(col, tableName) {
    var sort = tableName+'Sort';
    var rev = tableName+'Reverse';
    if ($scope[sort] === col) {
      return $scope[rev] ? 'sort-true' : 'sort-false';
    }
    return '';
  };
  $scope.separateTeams = false;
  $scope.separateTeamsPredicate = function() {
    return $scope.separateTeams ? ( ($scope.overallReverse ? '-' : '+') + 'team' ) : '';
  };
  var fillOutPlayerMetaData = function() {
    for (var i=0,player; player=$scope.stats.players[i]; i++) {
      var steamid = player.steamid;

      if ($scope.playerMetaData[steamid]) {
        $scope.playerMetaData[steamid].name = player.name;
        $scope.playerMetaData[steamid].team = player.team;
        player.avatar = $scope.playerMetaData[steamid].avatar;
      } else {
        $scope.playerMetaData[steamid] = { name: player.name, team: player.team };
      }
    }
  };
  $scope.filterBinds = true;
  $scope.bindFilter = function(chat) {
    return (!$scope.filterBinds || !chat.isBind);
  };
  var mostPlayedClass = function(mpcArray) {
    if ($scope.numRounds === 1) {
      return mpcArray[0];
    }
    // Determine what class was played the most by summing the rounddurations
    //  for the according tf2class in the "mostplayedclass" array.
    var totals = [0,0,0,0,0,0,0,0,0,0];
    for (var i=0; i<$scope.numRounds; i++) {
      // mpcArray[i] is the index (1-9) of the tf2class that the player played
      //  the most in the ith round. The index of the max value in totals[] is
      //  the id of the tf2class that the player played the most in the match.
      totals[ mpcArray[i] ] += $scope.stats.roundduration[i];
    }
    // Find the index of the max value in totals[].
    var theClass=0, theMax=0;
    for (var j=0; j<9 ;j++) {
      if (totals[j] > theMax) {
        theMax = totals[j];
        theClass = j;
      }
    }
    return theClass;
  };
  var sumArray = function(array) {
    var sum = 0, filteredArray = [];
    for (var i=0, ilen=$scope.selectedRounds.length; i<ilen; i++) {
      filteredArray.push(array[$scope.selectedRounds[i]]);
    }
    for (var j=0, jlen=filteredArray.length; j<jlen; j++) {
      if (filteredArray[j]) sum += filteredArray[j];
    }
    return sum;
  };
  var sumArray2 = function(array) {
    if (!array.length) return '-'; // this is a hack
    var sum = 0, filteredArray = [];
    for (var i=0, len=$scope.selectedRounds.length; i<len; i++) {
      filteredArray.push(array[$scope.selectedRounds[i]]);
    }
    for (var j=0, jlen=filteredArray.length; j<jlen; j++) {
      if (filteredArray[j]) sum += filteredArray[j];
    }
    return sum;
  };
  var ratio = function(den, denIsArray, numArray1, numArray2) {
    if (!numArray1.length) return '-'; // this is a hack
    var numerator, denominator;
    if (!numArray2 || !numArray2.length) {
      numerator = sumArray(numArray1);
    } else {
      numerator = sumArray(numArray1) + sumArray(numArray2);
    }
    if (numerator === 0) return 0;
    if (denIsArray) {
      denominator = sumArray(den);
    } else {
      denominator = den;
    }
    if (denominator === 0) return '∞';
    return Math.round( (numerator/denominator)*100 )/100;
  };
  $scope.secondsToHMS = function(seconds) {
    var h = parseInt(seconds/3600);
    var m = parseInt((seconds-h*3600)/60);
    var s = seconds-h*3600-m*60;
    if (h === 0) { return ('0'+m).slice(-2)+':'+('0'+s).slice(-2); }
    return h+':'+('0'+m).slice(-2)+':'+('0'+s).slice(-2);
  };

  // The very first time you load the controller, use the resolvedData.
  calculateStats(resolvedData, true);
}
// This is for the first time you load the controller
//  -- so that you don't see all the empty divs and tables.
StatsCtrl.resolve = {
  resolvedData: function($q, $http, $route) {
    var deferred = $q.defer();
    $http({
      method: 'GET',
      url: '/api/stats/' + $route.current.params.id
    })
      .success(function(data) {
        deferred.resolve(data);
      })
      .error(function(data) {
        deferred.reject(data);
      });
    return deferred.promise;
  }
};
<|endoftext|>


<commit_before>'use strict';

function Player(game, x, y, bulletManager, id, weaponManager, effectManager)
{
var self = this;

var bullets = ['bullet1', 'bullet2', 'bullet3', 'bullet4', 'bullet5', 'bullet6'];
var sprites = ['player1', 'player2', 'player3', 'player4', 'player5', 'player6'];
var input;
//self.playerClass = Math.floor((Math.random() * 6)); //rand 0-5
self.playerClass;
self.playerName;
self.id = id;

self.score = 0;

var hitColorTime = 50;
var hitColorEndTime = 0;

self.maxHealth = 200;
self.currentHealth = self.maxHealth;

self.dead = false;
//var randomSprite = sprites[Math.floor((Math.random() * 6))];

self.sprite = game.add.sprite(x, y, 'empty');
self.sprite.anchor.setTo(0.5, 0.5);
self.sprite.exists = false;
self.sprite.playerObj = self;  //powerups need the player object, bad solution, anythign better?
var setupDone = false;

var flipped = false;

var fireRate = 200;
var baseFireRate = 200;

var nextFire = 0;

var movementSpeed = 200;
var baseMovementSpeed = 200;

var respawnTime = 2500;
var nextRespawn = 0;

var bulletDamage = 2;
var bulletSpeed = 1000;
var bulletLifespan = 1000;

var cameraPadding = 20;

var headingPoint = new Phaser.Point();
var vectorPoint = new Phaser.Point();
vectorPoint.x = -1;
vectorPoint.y = 0;

var activePowerUps = [];

var pHUD;

var scale = function ()
	{
	if (flipped)
		{
		self.sprite.scale.x = -scalingFactors.x;
		} else
		{
		self.sprite.scale.x = scalingFactors.x;
		}
	self.sprite.scale.y = scalingFactors.y;
	self.sprite.body.setSize(self.sprite.width, self.sprite.height);
	};

function createPlayer ()
	{
	self.sprite.loadTexture(sprites[self.playerClass]);

	game.physics.enable(self.sprite, Phaser.Physics.ARCADE);
	self.sprite.body.collideWorldBounds = true;
	self.sprite.body.bounce = (1,1);

	self.weapon = weaponManager.createWeapon(self, sprites[self.playerClass]);

	pHUD = new Hud(game,self);
	pHUD.setName(self.playerName);
	self.sprite.exists = true;
	};

self.setInput = function (inputArray)
	{
	input = inputArray;
	};

//called by controller once it is created
function setClassAndName (pClass, pName)
	{
	self.playerClass = pClass;
	self.playerName = pName;
	//console.log('pname: ' + self.playerName + ', pclass: ' + self.playerClass);
	};

self.update = function ()
	{
	scale();
	if (!self.dead)
		{
		if (input != undefined)
			{

			if(!setupDone)
				{
					//setting the player up here is a workaround to enable play on firefox
				//console.log('setting up player');
				setClassAndName(input.pClass, input.pName);
				createPlayer();
				setupDone = true;
				}
			if(game.time.now > hitColorEndTime)
				{
				self.sprite.tint = 0xFFFFFF; //original color
				}
			var length = input.moveLength;
			if(length > 1)
				{
				length = 1;
				}
			var angle = input.moveAngle;
			game.physics.arcade.velocityFromAngle(angle, movementSpeed * length, self.sprite.body.velocity);
			if (self.sprite.body.velocity.x > 0 && flipped)
				{
				flipped = false;
				} else if (self.sprite.body.velocity.x < 0 && !flipped) {
				flipped = true;
				}
			if ((input.sX != 0 || input.sX != 0) && (game.time.now > nextFire))
				{
				nextFire = game.time.now + fireRate;
				headingPoint.x = input.sX;
				headingPoint.y = input.sY;
				bulletManager.createBullet(bullets[self.playerClass], bulletDamage, self.id, (Phaser.Point.angle(headingPoint, vectorPoint) * 360/Math.PI), self.sprite.position, bulletSpeed, bulletLifespan);
				}
			}

		//We should only check for collisions when there are collidable objects on screen
		if(bulletManager.enemyBulletCount > 0)
			{
			game.physics.arcade.overlap(bulletManager.enemyBulletGroups, self.sprite, self.playerHit, null, self);
			}

		//Check for powerups only if powerups are active
		if(activePowerUps.length > 0) {
			for (var i = activePowerUps.length - 1; i >= 0; i--) {
				if(activePowerUps[i] != 'undefined') {
					if(activePowerUps[i].endTime <= game.time.now) {
						if(activePowerUps[i].powerUpID == 'incSpeed')
						{
							self.setSpeed(baseMovementSpeed);
						}

						else if (activePowerUps[i].powerUpID == 'incFireRate')
						{
							self.setFireRate(baseFireRate);
						}
						activePowerUps.splice(i,1); //We remove the expired powerup from the array
					}
				}
			}
		}

		} else if (self.dead && nextRespawn < 0) {
		self.sprite.exists = true;
		self.dead = false;
		self.currentHealth = self.maxHealth;
    gameClient.callClientRpc(self.id, "setDeath", [true], self, null);
		pHUD.updateHealthBar();
		} else {
		nextRespawn--;
		}

		// We always check if the player has fallen behing the camera

		if (self.sprite.position.x < game.camera.x + cameraPadding)
		{
			self.sprite.position.x = game.camera.x + cameraPadding;
		} else if (self.sprite.position.x > game.camera.x + game.camera.width - cameraPadding)
		{
			self.sprite.position.x = game.camera.x + game.camera.width - cameraPadding;
		}

		if (self.sprite.position.y < game.camera.y + cameraPadding)
		{
			self.sprite.position.y = game.camera.y + cameraPadding;
		} else if (self.sprite.position.y > game.camera.y + game.camera.height - cameraPadding)
		{
			self.sprite.position.y = game.camera.y + game.camera.height - cameraPadding;
		}
	};

self.playerHit = function(player, bullet)
	{
	hitColorEndTime = game.time.now + hitColorTime;
	self.sprite.tint = 0xCC0000;
	var damage = bullet.damage;
	bulletManager.killbullet(bullet);
	self.takeDamage(damage);
  	gameClient.callClientRpc(self.id, "setHapticFeedback", [50], self, null);
	};

self.takeDamage = function(damage)
	{
	self.currentHealth = self.currentHealth-damage;
	if(self.currentHealth <= 0)
		{
		self.dead = true;
		self.kill();
		self.currentHealth = 0;
		}
		pHUD.updateHealthBar();
	};

self.heal = function(amount)
{
	if(self.currentHealth + amount >= self.maxHealth) {
		self.currentHealth = self.maxHealth;
	} else {
		self.currentHealth += amount;
	}
	pHUD.updateHealthBar();
}

self.setFireRate = function(amount)
{
	fireRate = amount;
}

self.setSpeed = function(amount)
{
	movementSpeed = amount;

}

/**
* Starts a powerup on the player object
* @param {string} pUpID - The ID of the powerup as displayed in pUpDictionary
* @param {int} pUpDuration - The Duration of the powerup in milliseconds
* @param {int} pUpStats - The value for the powerup
*/
self.startPowerUp = function(pUpID, pUpDuration, pUpStats)
{
	var powerupFound = false;

	//If the player picks two powerups we simply extend the duration.
	for (var i = activePowerUps.length - 1; i >= 0; i--) {
		if(activePowerUps[i].powerUpID == pUpID) {
			activePowerUps[i].endTime = game.time.now + pUpDuration;
			powerupFound = true;
		}
	}
	//If this is the first isntance of a powerup we add it to the active list
	if(!powerupFound) {
		var newPowerUp = {powerUpID: pUpID, endTime: game.time.now + pUpDuration};
		activePowerUps.push(newPowerUp);
		switch(pUpID)
		{
			case 'incSpeed':
				self.setSpeed(movementSpeed + pUpStats);
				break;

			case 'incFireRate':
				self.setFireRate(fireRate - pUpStats);
				break;

			default:
				break;
		}
	}
}

self.kill = function ()
	{
	clearAllPowerups();
	self.sprite.exists = false;
  gameClient.callClientRpc(self.id, "setHapticFeedback", [200], self, null);
  gameClient.callClientRpc(self.id, "setDeath", [false], self, null);
	effectManager.createDeathEffect(self);
	nextRespawn = respawnTime;
	};

self.getPoints = function ()
	{
	self.score += 1;
	};

var clearAllPowerups = function ()
	{
	self.setSpeed(baseMovementSpeed);
	self.setFireRate(baseFireRate);
	activePowerUps = [];
	};
}
<commit_msg>visual effect<commit_after>'use strict';

function Player(game, x, y, bulletManager, id, weaponManager, effectManager)
{
var self = this;

var bullets = ['bullet1', 'bullet2', 'bullet3', 'bullet4', 'bullet5', 'bullet6'];
var sprites = ['player1', 'player2', 'player3', 'player4', 'player5', 'player6'];
var input;
//self.playerClass = Math.floor((Math.random() * 6)); //rand 0-5
self.playerClass;
self.playerName;
self.id = id;

self.score = 0;

var hitColorTime = 50;
var hitColorEndTime = 0;

self.maxHealth = 200;
self.currentHealth = self.maxHealth;

self.dead = false;
//var randomSprite = sprites[Math.floor((Math.random() * 6))];

self.sprite = game.add.sprite(x, y, 'empty');
self.sprite.anchor.setTo(0.5, 0.5);
self.sprite.exists = false;
self.sprite.playerObj = self;  //powerups need the player object, bad solution, anythign better?
var setupDone = false;

var flipped = false;

var fireRate = 200;
var baseFireRate = 200;

var nextFire = 0;

var movementSpeed = 200;
var baseMovementSpeed = 200;

var respawnTime = 2500;
var nextRespawn = 0;

var bulletDamage = 2;
var bulletSpeed = 1000;
var bulletLifespan = 1000;

var cameraPadding = 20;

var headingPoint = new Phaser.Point();
var vectorPoint = new Phaser.Point();
vectorPoint.x = -1;
vectorPoint.y = 0;

var activePowerUps = [];

var pHUD;

var scale = function ()
	{
	if (flipped)
		{
		self.sprite.scale.x = -scalingFactors.x;
		} else
		{
		self.sprite.scale.x = scalingFactors.x;
		}
	self.sprite.scale.y = scalingFactors.y;
	self.sprite.body.setSize(self.sprite.width, self.sprite.height);
	};

function createPlayer ()
	{
	self.sprite.loadTexture(sprites[self.playerClass]);

	game.physics.enable(self.sprite, Phaser.Physics.ARCADE);
	self.sprite.body.collideWorldBounds = true;
	self.sprite.body.bounce = (1,1);

	self.weapon = weaponManager.createWeapon(self, sprites[self.playerClass]);

	pHUD = new Hud(game,self);
	pHUD.setName(self.playerName);
	self.sprite.exists = true;
	};

self.setInput = function (inputArray)
	{
	input = inputArray;
	};

//called by controller once it is created
function setClassAndName (pClass, pName)
	{
	self.playerClass = pClass;
	self.playerName = pName;
	//console.log('pname: ' + self.playerName + ', pclass: ' + self.playerClass);
	};

self.update = function ()
	{
	scale();
	if (!self.dead)
		{
		if (input != undefined)
			{

			if(!setupDone)
				{
					//setting the player up here is a workaround to enable play on firefox
				//console.log('setting up player');
				setClassAndName(input.pClass, input.pName);
				createPlayer();
				setupDone = true;
				}
			if(game.time.now > hitColorEndTime)
				{
				self.sprite.tint = 0xFFFFFF; //original color
				}
			var length = input.moveLength;
			if(length > 1)
				{
				length = 1;
				}
			var angle = input.moveAngle;
			game.physics.arcade.velocityFromAngle(angle, movementSpeed * length, self.sprite.body.velocity);
			if (self.sprite.body.velocity.x > 0 && flipped)
				{
				flipped = false;
				} else if (self.sprite.body.velocity.x < 0 && !flipped) {
				flipped = true;
				}
			if ((input.sX != 0 || input.sX != 0) && (game.time.now > nextFire))
				{
				nextFire = game.time.now + fireRate;
				headingPoint.x = input.sX;
				headingPoint.y = input.sY;
				bulletManager.createBullet(bullets[self.playerClass], bulletDamage, self.id, (Phaser.Point.angle(headingPoint, vectorPoint) * 360/Math.PI), self.sprite.position, bulletSpeed, bulletLifespan);
				}
			}

		//We should only check for collisions when there are collidable objects on screen
		if(bulletManager.enemyBulletCount > 0)
			{
			game.physics.arcade.overlap(bulletManager.enemyBulletGroups, self.sprite, self.playerHit, null, self);
			}

		//Check for powerups only if powerups are active
		if(activePowerUps.length > 0) {
			for (var i = activePowerUps.length - 1; i >= 0; i--) {
				if(activePowerUps[i] != 'undefined') {
					if(activePowerUps[i].endTime <= game.time.now) {
						if(activePowerUps[i].powerUpID == 'incSpeed')
						{
							self.setSpeed(baseMovementSpeed);
						}

						else if (activePowerUps[i].powerUpID == 'incFireRate')
						{
							self.setFireRate(baseFireRate);
						}
						activePowerUps.splice(i,1); //We remove the expired powerup from the array
					}
				}
			}
		}

		} else if (self.dead && nextRespawn < 0) {
		self.sprite.exists = true;
		self.dead = false;
		self.currentHealth = self.maxHealth;
    gameClient.callClientRpc(self.id, "setDeath", [true], self, null);
		pHUD.updateHealthBar();
		} else {
		nextRespawn--;
		}

		// We always check if the player has fallen behing the camera

		if (self.sprite.position.x < game.camera.x + cameraPadding)
		{
			self.sprite.position.x = game.camera.x + cameraPadding;
		} else if (self.sprite.position.x > game.camera.x + game.camera.width - cameraPadding)
		{
			self.sprite.position.x = game.camera.x + game.camera.width - cameraPadding;
		}

		if (self.sprite.position.y < game.camera.y + cameraPadding)
		{
			self.sprite.position.y = game.camera.y + cameraPadding;
		} else if (self.sprite.position.y > game.camera.y + game.camera.height - cameraPadding)
		{
			self.sprite.position.y = game.camera.y + game.camera.height - cameraPadding;
		}
	};

self.playerHit = function(player, bullet)
	{
	hitColorEndTime = game.time.now + hitColorTime;
	self.sprite.tint = 0xCC0000;
	var damage = bullet.damage;
	bulletManager.killbullet(bullet);
	self.takeDamage(damage);
  	gameClient.callClientRpc(self.id, "setHapticFeedback", [50], self, null);
	};

self.takeDamage = function(damage)
	{
	self.currentHealth = self.currentHealth-damage;
	if(self.currentHealth <= 0)
		{
		self.dead = true;
		self.kill();
		self.currentHealth = 0;
		}
		pHUD.updateHealthBar();
	};

self.heal = function(amount)
{
	if(self.currentHealth + amount >= self.maxHealth) {
		self.currentHealth = self.maxHealth;
	} else {
		self.currentHealth += amount;
	}
	pHUD.updateHealthBar();
}

self.setFireRate = function(amount)
{
	fireRate = amount;
}

self.setSpeed = function(amount)
{
	movementSpeed = amount;

}

/**
* Starts a powerup on the player object
* @param {string} pUpID - The ID of the powerup as displayed in pUpDictionary
* @param {int} pUpDuration - The Duration of the powerup in milliseconds
* @param {int} pUpStats - The value for the powerup
*/
self.startPowerUp = function(pUpID, pUpDuration, pUpStats)
{
	var powerupFound = false;

	//If the player picks two powerups we simply extend the duration.
	for (var i = activePowerUps.length - 1; i >= 0; i--) {
		if(activePowerUps[i].powerUpID == pUpID) {
			activePowerUps[i].endTime = game.time.now + pUpDuration;
			powerupFound = true;
		}
	}
	//If this is the first isntance of a powerup we add it to the active list
	if(!powerupFound) {
		var newPowerUp = {powerUpID: pUpID, endTime: game.time.now + pUpDuration};
		activePowerUps.push(newPowerUp);
		switch(pUpID)
		{
			case 'incSpeed':
				self.setSpeed(movementSpeed + pUpStats);
				break;

			case 'incFireRate':
				self.setFireRate(fireRate - pUpStats);
				break;

			default:
				break;
		}
	}
}

self.kill = function ()
	{
	clearAllPowerups();
	//scoreText();
	self.sprite.exists = false;
  	gameClient.callClientRpc(self.id, "setHapticFeedback", [200], self, null);
  	gameClient.callClientRpc(self.id, "setDeath", [false], self, null);
	effectManager.createDeathEffect(self);
	nextRespawn = respawnTime;
	};

var scoreText = function()
	{
	var text = game.add.text(self.sprite.position.x, self.sprite.position.y, '-100', { font: "13px Arial", fill: "#FFFFFF"});
	text.anchor.setTo(0.5, 0.5);
	text.rotateSpeed= -0.3;
	game.physics.arcade.enable(text);
	text.body.collideWorldBounds = true;
	text.body.bounce.set(1);
	var factor = Math.floor((Math.random() * 10))
	text.body.velocity.setTo(factor*10, factor*10);
	game.time.events.add(2000, function() {text.destroy();});
	};

self.getPoints = function ()
	{
	self.score += 1;
	};

var clearAllPowerups = function ()
	{
	self.setSpeed(baseMovementSpeed);
	self.setFireRate(baseFireRate);
	activePowerUps = [];
	};
}
<|endoftext|>


<commit_before>import {
    library as L,
    addNativeListener,
    importDomImage,
} from '../source/scrawl.js';

// Function to display frames-per-second data, and other information relevant to the demo
const reportSpeed = function (output = '', xtra = () => '') {

    if (!output) return function () {};

    let testTicker = Date.now(),
        testTime, testNow, dragging,
        testMessage = document.querySelector(output);

    return function () {

        testNow = Date.now();

        if (testNow - testTicker > 2) {

            testTime = testNow - testTicker;
            testTicker = testNow;

            let text = `Screen refresh: ${Math.ceil(testTime)}ms; fps: ${Math.floor(1000 / testTime)}`;

            if (xtra) {

                text += `
${xtra()}`;
            }

            testMessage.textContent = text;
        }
    };
};

// Test to check that artefacts are properly killed and resurrected
const killArtefact = (canvas, name, time, finishResurrection = () => {}) => {

    if (canvas && canvas.base && name && time) {

        let groupname = canvas.base.name,
            packet;

        let checkGroupBucket = (name, groupname) => {

            let res = L.group[groupname].artefactCalculateBuckets.filter(e => e.name === name );
            return (res.length) ? 'no' : 'yes';
        };

        setTimeout(() => {

            console.log(`${name} alive
        removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
        removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
        removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

            packet = L.artefact[name].saveAsPacket();

            L.artefact[name].kill();

            setTimeout(() => {

                console.log(`${name} killed
        removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
        removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
        removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

                canvas.actionPacket(packet);

                setTimeout(() => {

                    console.log(`${name} resurrected
        removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
        removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
        removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

                    if (finishResurrection) finishResurrection();

                }, 100);
            }, 100);
        }, time);
    }
    else console.log('killArtefact test invoked improperly');
};

// To test styles (Gradient) kill functionality
const killStyle = (canvas, name, time, finishResurrection = () => {}) => {

    if (canvas && canvas.base && name && time) {

        let packet;

        setTimeout(() => {

            console.log(`${name} alive
        removed from styles: ${(L.styles[name]) ? 'no' : 'yes'}
        removed from stylesnames: ${(L.stylesnames.indexOf(name) >= 0) ? 'no' : 'yes'}`);

            packet = L.styles[name].saveAsPacket();

            L.styles[name].kill();

            setTimeout(() => {

                console.log(`${name} killed
        removed from styles: ${(L.styles[name]) ? 'no' : 'yes'}
        removed from stylesnames: ${(L.stylesnames.indexOf(name) >= 0) ? 'no' : 'yes'}`);

                canvas.actionPacket(packet);

                setTimeout(() => {

                    console.log(`${name} resurrected
        removed from styles: ${(L.styles[name]) ? 'no' : 'yes'}
        removed from stylesnames: ${(L.stylesnames.indexOf(name) >= 0) ? 'no' : 'yes'}`);

                    finishResurrection();

                }, 100);
            }, 100);
        }, time);
    }
    else console.log('killStyle test invoked improperly');
};

// To test artefact + anchor kill functionality
const killArtefactAndAnchor = (canvas, name, anchorname, time, finishResurrection = () => {}) => {

    let groupname = 'mycanvas_base',
        packet;

    let checkGroupBucket = (name, groupname) => {

        let res = L.group[groupname].artefactCalculateBuckets.filter(e => e.name === name );
        return (res.length) ? 'no' : 'yes';
    };

    setTimeout(() => {

        console.log(`${name} alive
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}
    anchor removed: ${(L.anchor[anchorname]) ? 'no' : 'yes'}`);

        packet = L.artefact[name].saveAsPacket();

        L.artefact[name].kill();

        setTimeout(() => {

            console.log(`${name} killed
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}
    anchor removed: ${(L.anchor[anchorname]) ? 'no' : 'yes'}`);

            canvas.actionPacket(packet);

            setTimeout(() => {

                console.log(`${name} resurrected
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}
    anchor removed: ${(L.anchor[anchorname]) ? 'no' : 'yes'}`);

                finishResurrection();

            }, 100);
        }, 100);
    }, time);
};

// To test Polyline artefact kill functionality
const killPolylineArtefact = (canvas, name, time, myline, restore = () => {}) => {

    let groupname = 'mycanvas_base',
        packet;

    let checkGroupBucket = (name, groupname) => {

        let res = L.group[groupname].artefactCalculateBuckets.filter(e => e.name === name );
        return (res.length) ? 'no' : 'yes';
    };

    let checkPinsArray = (name) => {

        if (myline.pins.indexOf(name) >= 0) return 'no';

        let res = myline.pins.filter(e => e && e.name === name );
        return (res.length) ? 'no' : 'yes';
    };

    setTimeout(() => {

        console.log(`${name} alive
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from polyline pins array: ${checkPinsArray(name)}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

        packet = L.artefact[name].saveAsPacket();

        L.artefact[name].kill();

        setTimeout(() => {

            console.log(`${name} killed
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from polyline pins array: ${checkPinsArray(name)}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

            canvas.actionPacket(packet);

            setTimeout(() => {

                if (restore) restore();

                console.log(`${name} resurrected
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from polyline pins array: ${checkPinsArray(name)}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

                console.log(myline.saveAsPacket());

            }, 500);
        }, 500);
    }, time);
};

const killTicker = (stack, name, time) => {

    let packet;

    setTimeout(() => {

        console.log(`${name} alive
    removed from tickers: ${(L.animationtickers[name]) ? 'no' : 'yes'}`);

        packet = L.animationtickers[name].saveAsPacket();

        L.animationtickers[name].kill();

        setTimeout(() => {

            console.log(`${name} killed
    removed from tickers: ${(L.animationtickers[name]) ? 'no' : 'yes'}`);

            stack.actionPacket(packet);

            setTimeout(() => {

                console.log(`${name} resurrected
    removed from tickers: ${(L.animationtickers[name]) ? 'no' : 'yes'}`);
            }, 100);
        }, 100);
    }, time);
};

const addImageDragAndDrop = (canvas, selector, targets, callback = () => {}) => {

    // #### Drag-and-Drop image loading functionality
    const store = document.querySelector(selector);
    const timeoutDelay = 200;

    let counter = 0;

    if (!Array.isArray(targets)) targets = [targets];

    addNativeListener(['dragenter', 'dragover', 'dragleave'], (e) => {

        e.preventDefault();
        e.stopPropagation();

    }, canvas.domElement);

    addNativeListener('drop', (e) => {

        e.preventDefault();
        e.stopPropagation();

        const dt = e.dataTransfer;

        if (dt) [...dt.files].forEach(addImageAsset);

    }, canvas.domElement);

    const addImageAsset = (file) => {

        if (file.type.indexOf('image/') === 0) {

            const reader = new FileReader();

            reader.readAsDataURL(file);

            reader.onloadend = function() {

                // Create a name for our new asset
                const name = `user-upload-${counter}`;
                counter++;

                // Add the image to the DOM and create our asset from it
                const img = document.createElement('img');

                // @ts-expect-error
                img.src = reader.result;
                img.id = name;
                store.appendChild(img);

                importDomImage(`#${name}`);

                // Update our Picture entity's asset attribute so it displays the new image
                targets.forEach(target => {

                    target.set({
                        asset: name,
                    });
                });

                // HOW TO: set the Picture entity's copy dimensions to take into account any difference between the old and new image's dimensions
                // + Because of asynch stuff, we need to wait for stuff to complete before performing this functionality
                // + The Picture entity copies (for the sake of our sanity) a square part of the image. Thus we shall use the new image's shorter dimension as the copy dimension and offset the longer copy start so we are viewing the middle of it
                setTimeout(() => {

                    const asset = L.asset[name];

                    const width = asset.get('width'),
                        height = asset.get('height');

                    let copyStartX = 0,
                        copyStartY = 0,
                        dim = 0;

                    if (width > height) {

                        copyStartX = (width - height) / 2;
                        dim = height;
                    }
                    else {

                        copyStartY = (height - width) / 2;
                        dim = width;
                    }

                    targets.forEach(target => {

                        target.set({
                            copyStartX,
                            copyStartY,
                            copyWidth: dim,
                            copyHeight: dim,
                        });
                    })

                    if (callback) setTimeout(callback, timeoutDelay);
                }, timeoutDelay);
            }
        }
    };
};

export {
    reportSpeed,

    killArtefact,
    killArtefactAndAnchor,
    killPolylineArtefact,
    killStyle,
    killTicker,

    addImageDragAndDrop,
}
<commit_msg>make demo screen refresh reporting more stable<commit_after>import {
    library as L,
    addNativeListener,
    importDomImage,
} from '../source/scrawl.js';

// Function to display frames-per-second data, and other information relevant to the demo
const reportSpeed = function (output = '', xtra = () => '') {

    if (!output) return function () {};

        let testTicker = Date.now(),
            testTime, testNow,
            testMessage = document.querySelector(output);

        let history = [],
            averageTime = 0;

        const addTime = (t) => {

            if (history.length > 60) history.shift();
            history.push(t);
            averageTime = history.reduce((p, c) => p + c, 0);
            averageTime /= history.length;
        }

    return function () {

        testNow = Date.now();

        if (testNow - testTicker > 2) {

            testTime = testNow - testTicker;
            testTicker = testNow;

            addTime(testTime);

            let text = `Screen refresh: ${Math.ceil(averageTime)}ms; fps: ${Math.floor(1000 / averageTime)}`;

            if (xtra) {

                text += `
${xtra()}`;
            }

            testMessage.textContent = text;
        }
    };
};

// Test to check that artefacts are properly killed and resurrected
const killArtefact = (canvas, name, time, finishResurrection = () => {}) => {

    if (canvas && canvas.base && name && time) {

        let groupname = canvas.base.name,
            packet;

        let checkGroupBucket = (name, groupname) => {

            let res = L.group[groupname].artefactCalculateBuckets.filter(e => e.name === name );
            return (res.length) ? 'no' : 'yes';
        };

        setTimeout(() => {

            console.log(`${name} alive
        removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
        removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
        removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

            packet = L.artefact[name].saveAsPacket();

            L.artefact[name].kill();

            setTimeout(() => {

                console.log(`${name} killed
        removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
        removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
        removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

                canvas.actionPacket(packet);

                setTimeout(() => {

                    console.log(`${name} resurrected
        removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
        removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
        removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
        removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

                    if (finishResurrection) finishResurrection();

                }, 100);
            }, 100);
        }, time);
    }
    else console.log('killArtefact test invoked improperly');
};

// To test styles (Gradient) kill functionality
const killStyle = (canvas, name, time, finishResurrection = () => {}) => {

    if (canvas && canvas.base && name && time) {

        let packet;

        setTimeout(() => {

            console.log(`${name} alive
        removed from styles: ${(L.styles[name]) ? 'no' : 'yes'}
        removed from stylesnames: ${(L.stylesnames.indexOf(name) >= 0) ? 'no' : 'yes'}`);

            packet = L.styles[name].saveAsPacket();

            L.styles[name].kill();

            setTimeout(() => {

                console.log(`${name} killed
        removed from styles: ${(L.styles[name]) ? 'no' : 'yes'}
        removed from stylesnames: ${(L.stylesnames.indexOf(name) >= 0) ? 'no' : 'yes'}`);

                canvas.actionPacket(packet);

                setTimeout(() => {

                    console.log(`${name} resurrected
        removed from styles: ${(L.styles[name]) ? 'no' : 'yes'}
        removed from stylesnames: ${(L.stylesnames.indexOf(name) >= 0) ? 'no' : 'yes'}`);

                    finishResurrection();

                }, 100);
            }, 100);
        }, time);
    }
    else console.log('killStyle test invoked improperly');
};

// To test artefact + anchor kill functionality
const killArtefactAndAnchor = (canvas, name, anchorname, time, finishResurrection = () => {}) => {

    let groupname = 'mycanvas_base',
        packet;

    let checkGroupBucket = (name, groupname) => {

        let res = L.group[groupname].artefactCalculateBuckets.filter(e => e.name === name );
        return (res.length) ? 'no' : 'yes';
    };

    setTimeout(() => {

        console.log(`${name} alive
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}
    anchor removed: ${(L.anchor[anchorname]) ? 'no' : 'yes'}`);

        packet = L.artefact[name].saveAsPacket();

        L.artefact[name].kill();

        setTimeout(() => {

            console.log(`${name} killed
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}
    anchor removed: ${(L.anchor[anchorname]) ? 'no' : 'yes'}`);

            canvas.actionPacket(packet);

            setTimeout(() => {

                console.log(`${name} resurrected
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}
    anchor removed: ${(L.anchor[anchorname]) ? 'no' : 'yes'}`);

                finishResurrection();

            }, 100);
        }, 100);
    }, time);
};

// To test Polyline artefact kill functionality
const killPolylineArtefact = (canvas, name, time, myline, restore = () => {}) => {

    let groupname = 'mycanvas_base',
        packet;

    let checkGroupBucket = (name, groupname) => {

        let res = L.group[groupname].artefactCalculateBuckets.filter(e => e.name === name );
        return (res.length) ? 'no' : 'yes';
    };

    let checkPinsArray = (name) => {

        if (myline.pins.indexOf(name) >= 0) return 'no';

        let res = myline.pins.filter(e => e && e.name === name );
        return (res.length) ? 'no' : 'yes';
    };

    setTimeout(() => {

        console.log(`${name} alive
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from polyline pins array: ${checkPinsArray(name)}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

        packet = L.artefact[name].saveAsPacket();

        L.artefact[name].kill();

        setTimeout(() => {

            console.log(`${name} killed
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from polyline pins array: ${checkPinsArray(name)}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

            canvas.actionPacket(packet);

            setTimeout(() => {

                if (restore) restore();

                console.log(`${name} resurrected
    removed from artefact: ${(L.artefact[name]) ? 'no' : 'yes'}
    removed from artefactnames: ${(L.artefactnames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from entity: ${(L.entity[name]) ? 'no' : 'yes'}
    removed from entitynames: ${(L.entitynames.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from polyline pins array: ${checkPinsArray(name)}
    removed from group.artefacts: ${(L.group[groupname].artefacts.indexOf(name) >= 0) ? 'no' : 'yes'}
    removed from group.artefactCalculateBuckets: ${checkGroupBucket(name, groupname)}`);

                console.log(myline.saveAsPacket());

            }, 500);
        }, 500);
    }, time);
};

const killTicker = (stack, name, time) => {

    let packet;

    setTimeout(() => {

        console.log(`${name} alive
    removed from tickers: ${(L.animationtickers[name]) ? 'no' : 'yes'}`);

        packet = L.animationtickers[name].saveAsPacket();

        L.animationtickers[name].kill();

        setTimeout(() => {

            console.log(`${name} killed
    removed from tickers: ${(L.animationtickers[name]) ? 'no' : 'yes'}`);

            stack.actionPacket(packet);

            setTimeout(() => {

                console.log(`${name} resurrected
    removed from tickers: ${(L.animationtickers[name]) ? 'no' : 'yes'}`);
            }, 100);
        }, 100);
    }, time);
};

const addImageDragAndDrop = (canvas, selector, targets, callback = () => {}) => {

    // #### Drag-and-Drop image loading functionality
    const store = document.querySelector(selector);
    const timeoutDelay = 200;

    let counter = 0;

    if (!Array.isArray(targets)) targets = [targets];

    addNativeListener(['dragenter', 'dragover', 'dragleave'], (e) => {

        e.preventDefault();
        e.stopPropagation();

    }, canvas.domElement);

    addNativeListener('drop', (e) => {

        e.preventDefault();
        e.stopPropagation();

        const dt = e.dataTransfer;

        if (dt) [...dt.files].forEach(addImageAsset);

    }, canvas.domElement);

    const addImageAsset = (file) => {

        if (file.type.indexOf('image/') === 0) {

            const reader = new FileReader();

            reader.readAsDataURL(file);

            reader.onloadend = function() {

                // Create a name for our new asset
                const name = `user-upload-${counter}`;
                counter++;

                // Add the image to the DOM and create our asset from it
                const img = document.createElement('img');

                // @ts-expect-error
                img.src = reader.result;
                img.id = name;
                store.appendChild(img);

                importDomImage(`#${name}`);

                // Update our Picture entity's asset attribute so it displays the new image
                targets.forEach(target => {

                    target.set({
                        asset: name,
                    });
                });

                // HOW TO: set the Picture entity's copy dimensions to take into account any difference between the old and new image's dimensions
                // + Because of asynch stuff, we need to wait for stuff to complete before performing this functionality
                // + The Picture entity copies (for the sake of our sanity) a square part of the image. Thus we shall use the new image's shorter dimension as the copy dimension and offset the longer copy start so we are viewing the middle of it
                setTimeout(() => {

                    const asset = L.asset[name];

                    const width = asset.get('width'),
                        height = asset.get('height');

                    let copyStartX = 0,
                        copyStartY = 0,
                        dim = 0;

                    if (width > height) {

                        copyStartX = (width - height) / 2;
                        dim = height;
                    }
                    else {

                        copyStartY = (height - width) / 2;
                        dim = width;
                    }

                    targets.forEach(target => {

                        target.set({
                            copyStartX,
                            copyStartY,
                            copyWidth: dim,
                            copyHeight: dim,
                        });
                    })

                    if (callback) setTimeout(callback, timeoutDelay);
                }, timeoutDelay);
            }
        }
    };
};

export {
    reportSpeed,

    killArtefact,
    killArtefactAndAnchor,
    killPolylineArtefact,
    killStyle,
    killTicker,

    addImageDragAndDrop,
}
<|endoftext|>


<commit_before>var fs = require('fs');
var _ = require('lodash');

var whimp = require('../whimper');
var logger = require('../logger');

// create-dir()
whimp.task('create-dir', {
  run: function createDir(params, resolver) {
    // Contrived to show "async"
    setTimeout(function() {
      fs.mkdir(params.dir, function(e) {
        if ( e != null ) {
          resolver.reject(e);
        }
        else {
          resolver.resolve();
        }
      });
    }, 1005);
  }
}); //- create-dir()

// delete-dir()
whimp.task('delete-dir', {
  depends: [ 'create-dir' ],
  run: function deleteDir(params, resolver) {
    fs.rmdir(params.dir, function(e) {
      if ( e != null ) {
        resolver.reject(e);
      }
      else {
        resolver.resolve();
      }
    });
  }
}); //- delete-dir()

// cddir()
whimp.task('cddir', {
  options: {
    '!dir': 'The directory to create and then delete.'
  },
  depends: [ 'delete-dir' ]
}); //- cddir()

whimp.cli();

// $ node complex cddr --dir test<commit_msg>Update examples.<commit_after>var fs = require('fs');
var _ = require('lodash');

var whimp = require('../whimper');
var logger = require('../logger');

// create-dir()
whimp.task('create-dir', {
  run: function createDir(params, resolver) {
    // Contrived to show "async"
    setTimeout(function() {
      fs.mkdir(params.dir, function(e) {
        if ( e != null ) {
          resolver.reject(e);
        }
        else {
          resolver.resolve();
        }
      });
    }, 1005);
  }
}); //- create-dir()

// delete-dir()
whimp.task('delete-dir', {
  depends: [ 'create-dir' ],
  run: function deleteDir(params, resolver) {
    fs.rmdir(params.dir, function(e) {
      if ( e != null ) {
        resolver.reject(e);
      }
      else {
        resolver.resolve();
      }
    });
  }
}); //- delete-dir()

// cddir()
whimp.task('cddir', {
  options: {
    '!dir': 'The directory to create and then delete.'
  },
  depends: [ 'delete-dir' ]
}); //- cddir()

whimp.cli();

// $ node complex cddir --dir test<|endoftext|>


<commit_before>/**
 * Copyright 2013, Twitter Inc. and other contributors
 * Licensed under the MIT License
 *
 * wrapper for describe. load component before each test
 * @param componentPath
 * @param specDefinitions
 */
var describeComponent = function (componentPath, specDefinitions) {
  jasmine.getEnv().describeComponent(componentPath, specDefinitions);
};

jasmine.Env.prototype.describeComponent = function (componentPath, specDefinitions) {
  describe(componentPath, function () {
    beforeEach(function () {
      this.Component = this.component = this.$node = null;

      var requireCallback = function (registry, Component) {
        registry.reset();
        this.Component = Component;
      }.bind(this);

      require(['flight/lib/registry', componentPath], requireCallback);

      waitsFor(function () {
        return this.Component !== null;
      }.bind(this));
    });

    afterEach(function () {
      if (this.$node) {
        this.$node.remove();
        this.$node = null;
      }

      var requireCallback = function (defineComponent) {
        if (this.component) {
          this.component = null;
        }

        this.Component = null;
        defineComponent.teardownAll();
      }.bind(this);

      require(['flight/lib/component'], requireCallback);

      waitsFor(function () {
        return this.Component === null;
      }.bind(this));
    });
    specDefinitions.apply(this);
  });
};

/**
 * wrapper for describe. load component before each test
 * @param mixinPath
 * @param specDefinitions
 */
var describeMixin = function (mixinPath, specDefinitions) {
  jasmine.getEnv().describeMixin(mixinPath, specDefinitions);
};

jasmine.Env.prototype.describeMixin = function (mixinPath, specDefinitions) {
  describe(mixinPath, function () {
    beforeEach(function () {

     this.Component = this.component = this.$node = null;

      var requireCallback = function (registry, defineComponent, Mixin) {
        registry.reset();
        this.Component = defineComponent(function () {}, Mixin);
      }.bind(this);

      require(['flight/lib/registry', 'flight/lib/component', mixinPath], requireCallback);

      waitsFor(function () {
        return this.Component !== null;
      });
    });

    afterEach(function () {
      if (this.$node) {
        this.$node.remove();
        this.$node = null;
      }

      var requireCallback = function (defineComponent) {
        if (this.component) {
          this.component = null;
        }

        this.Component = null;
        defineComponent.teardownAll();
      }.bind(this);

      require(['flight/lib/component'], requireCallback);

      waitsFor(function () {
        return this.Component === null;
      }.bind(this));
    });
    specDefinitions.apply(this);
  });
};

var describeModule = function (modulePath, specDefinitions) {
  return jasmine.getEnv().describeModule(modulePath, specDefinitions);
};

jasmine.Env.prototype.describeModule = function (modulePath, specDefinitions) {
  describe(modulePath, function () {
    beforeEach(function () {
      this.module = null;

      var requireCallback = function (module) {
        this.module = module;
      }.bind(this);

      require([modulePath], requireCallback);

      waitsFor(function () {
        return this.module !== null;
      });
    });
    specDefinitions.apply(this);
  });
};

/**
 * Create root node and initialize component. Fixture should be html string or jQuery object
 * @param fixture {String} (Optional)
 * @param options {Options} (Optional)
 */
var setupComponent = function (fixture, options) {
  jasmine.getEnv().currentSpec.setupComponent(fixture, options);
};

jasmine.Spec.prototype.setupComponent = function (fixture, options) {
  if (this.component) {
    this.component.teardown();
    this.$node.remove();
  }

  this.$node = $('
');
  $('body').append(this.$node);

  if (fixture instanceof jQuery || typeof fixture === 'string') {
    this.$node.append(fixture);
  } else {
    options = fixture;
    fixture = null;
  }

  options = options === undefined ? {} : options;

  this.component = new this.Component(this.$node, options);
};

jasmine.flight = {};

(function (namespace) {
  var eventsData = {
    spiedEvents: {},
    handlers:    []
  };

  namespace.formatElement = function ($element) {
    var limit = 200;
    var output = '';
    if ($element instanceof jQuery) {
      output = jasmine.JQuery.elementToString($element);
      if (output.length > limit) {
        output = output.slice(0, 200) + '...';
      }
    } else {
      //$element should always be a jQuery object
      output = 'element is not a jQuery object';
    }
    return output;
  };

  namespace.compareColors = function (color1, color2) {
    if (color1.charAt(0) == color2.charAt(0)) {
      return color1 === color2;
    } else {
      return namespace.hex2rgb(color1) === namespace.hex2rgb(color2);
    }
  };

  namespace.hex2rgb = function (colorString) {
    if (colorString.charAt(0) !== '#') return colorString;
    // note: hexStr should be #rrggbb
    var hex = parseInt(colorString.substring(1), 16);
    var r = (hex & 0xff0000) >> 16;
    var g = (hex & 0x00ff00) >> 8;
    var b = hex & 0x0000ff;
    return 'rgb(' + r + ', ' + g + ', ' + b + ')';
  };

  namespace.events = {
    spyOn: function (selector, eventName) {
      eventsData.spiedEvents[[selector, eventName]] = {
        callCount: 0,
        calls: [],
        mostRecentCall: {},
        name: eventName
      };
      var handler = function (e, data) {
        var call = {
          event: e,
          args: jasmine.util.argsToArray(arguments),
          data: data
        };
        eventsData.spiedEvents[[selector, eventName]].callCount++;
        eventsData.spiedEvents[[selector, eventName]].calls.push(call);
        eventsData.spiedEvents[[selector, eventName]].mostRecentCall = call;
      };
      jQuery(selector).on(eventName, handler);
      eventsData.handlers.push(handler);
      return eventsData.spiedEvents[[selector, eventName]];
    },

    eventArgs: function (selector, eventName, expectedArg) {
      var actualArgs = eventsData.spiedEvents[[selector, eventName]].mostRecentCall.args;

      if (!actualArgs) {
        throw "No event spy found on " + eventName + ". Try adding a call to spyOnEvent or make sure that the selector the event is triggered on and the selector being spied on are correct.";
      }

      // remove extra event metadata if it is not tested for
      if ((actualArgs.length == 2) && typeof actualArgs[1] === 'object' &&
        expectedArg && !expectedArg.scribeContext && !expectedArg.sourceEventData && !expectedArg.scribeData) {
        actualArgs[1] = $.extend({}, actualArgs[1]);
        delete actualArgs[1].sourceEventData;
        delete actualArgs[1].scribeContext;
        delete actualArgs[1].scribeData;
      }

      return actualArgs;
    },

    wasTriggered: function (selector, event) {
      var spiedEvent = eventsData.spiedEvents[[selector, event]];
      return spiedEvent && spiedEvent.callCount > 0;
    },

    wasTriggeredWith: function (selector, eventName, expectedArg, env) {
      var actualArgs = jasmine.flight.events.eventArgs(selector, eventName, expectedArg);
      return actualArgs && env.contains_(actualArgs, expectedArg);
    },

    wasTriggeredWithData: function (selector, eventName, expectedArg, env) {
      var actualArgs = jasmine.flight.events.eventArgs(selector, eventName, expectedArg);
      if (actualArgs) {
        var valid = false;
        for (var i = 0; i < actualArgs.length; i++) {
          if (jasmine.flight.validateHash(expectedArg, actualArgs[i])) {
            return true;
          }
        }
        return valid;
      }
      return false;
    },

    cleanUp: function () {
      eventsData.spiedEvents = {};
      eventsData.handlers    = [];
    }
  };

  namespace.validateHash = function (a, b, intersection) {
    var validHash;
    for (var field in a) {
      if ((typeof a[field] == 'object') && (typeof b[field] == 'object')) {
        validHash = jasmine.flight.validateHash(a[field], b[field]);
      } else if (intersection && (typeof a[field] == 'undefined' || typeof b[field] == 'undefined')) {
        validHash = true;
      } else {
        validHash = a[field] == b[field];
      }
      if (!validHash) {
        break;
      }
    }
    return validHash;
  };

})(jasmine.flight);

beforeEach(function () {
  this.addMatchers({
    toHaveBeenTriggeredOn: function () {
      var selector = arguments[0];
      var eventName = typeof this.actual === 'string' ? this.actual : this.actual.name;
      var wasTriggered = jasmine.flight.events.wasTriggered(selector, eventName);

      this.message = function () {
        var $pp = function (obj) {
          var description;
          var attr;

          if (!(obj instanceof jQuery)) {
            obj = $(obj);
          }

          description = [
            obj.get(0).nodeName
          ];

          attr = obj.get(0).attributes || [];

          for (var x = 0; x < attr.length; x++) {
            description.push(attr[x].name + '="' + attr[x].value + '"');
          }

          return '<' + description.join(' ') + '>';
        };

        if (wasTriggered) {
          return [
            "
Expected event " + eventName + " to have been triggered on" + selector,
            "
Expected event " + eventName + " not to have been triggered on" + selector
          ];
        } else {
          return [
            "Expected event " + eventName + " to have been triggered on " + $pp(selector),
            "Expected event " + eventName + " not to have been triggered on " + $pp(selector)
          ];
        }
      };

      return wasTriggered;
    },

    toHaveBeenTriggeredOnAndWith: function () {
      var selector = arguments[0];
      var expectedArg = arguments[1];
      var exactMatch = !arguments[2];
      var wasTriggered = jasmine.flight.events.wasTriggered(selector, this.actual);

      this.message = function () {
        var $pp = function (obj) {
          var description;
          var attr;

          if (!(obj instanceof jQuery)) {
            obj = $(obj);
          }

          description = [
            obj.get(0).nodeName
          ];

          attr = obj.get(0).attributes || [];

          for (var x = 0; x < attr.length; x++) {
            description.push(attr[x].name + '="' + attr[x].value + '"');
          }

          return '<' + description.join(' ') + '>';
        };

        if (wasTriggered) {
          var actualArg = jasmine.flight.events.eventArgs(selector, this.actual, expectedArg)[1];
          return [
            "
Expected event " + this.actual.name + " to have been triggered on" + selector,
            "
Expected event " + this.actual.name + " not to have been triggered on" + selector
          ];
        } else {
          return [
            "Expected event " + this.actual.name + " to have been triggered on " + $pp(selector),
            "Expected event " + this.actual.name + " not to have been triggered on " + $pp(selector)
          ];
        }
      };

      if (!wasTriggered) {
        return false;
      }
      if (exactMatch) {
        return jasmine.flight.events.wasTriggeredWith(selector, this.actual, expectedArg, this.env);
      } else {
        return jasmine.flight.events.wasTriggeredWithData(selector, this.actual, expectedArg, this.env);
      }
    },

    toHaveCss: function (prop, val) {
      var result;
      if (val instanceof RegExp) {
        result = val.test(this.actual.css(prop));
      } else if (prop.match(/color/)) {
        //IE returns colors as hex strings; other browsers return rgb(r, g, b) strings
        result = jasmine.flight.compareColors(this.actual.css(prop), val);
      } else {
        result = this.actual.css(prop) === val;
        //sometimes .css() returns strings when it should return numbers
        if (!result && typeof val === "number") {
          result = parseFloat(this.actual.css(prop), 10) === val;
        }
      }

      this.actual = jasmine.flight.formatElement(this.actual);
      return result;
    }
  });
});

var spyOnEvent = function (selector, eventName) {
  jasmine.JQuery.events.spyOn(selector, eventName);
  return jasmine.flight.events.spyOn(selector, eventName);
};
<commit_msg>Code style<commit_after>/**
 * Copyright 2013, Twitter Inc. and other contributors
 * Licensed under the MIT License
 */

(function (root) {
  'use strict';

  jasmine.flight = {};

  /**
   * Wrapper for describe. Load component before each test.
   *
   * @param componentPath
   * @param specDefinitions
   */

  root.describeComponent = function (componentPath, specDefinitions) {
    jasmine.getEnv().describeComponent(componentPath, specDefinitions);
  };

  jasmine.Env.prototype.describeComponent = function (componentPath, specDefinitions) {
    describe(componentPath, function () {
      beforeEach(function () {
        this.Component = this.component = this.$node = null;

        var requireCallback = function (registry, Component) {
          registry.reset();
          this.Component = Component;
        }.bind(this);

        require(['flight/lib/registry', componentPath], requireCallback);

        waitsFor(function () {
          return this.Component !== null;
        }.bind(this));
      });

      afterEach(function () {
        if (this.$node) {
          this.$node.remove();
          this.$node = null;
        }

        var requireCallback = function (defineComponent) {
          if (this.component) {
            this.component = null;
          }

          this.Component = null;
          defineComponent.teardownAll();
        }.bind(this);

        require(['flight/lib/component'], requireCallback);

        waitsFor(function () {
          return this.Component === null;
        }.bind(this));
      });
      specDefinitions.apply(this);
    });
  };

  /**
   * Wrapper for describe. Load mixin before each test.
   *
   * @param mixinPath
   * @param specDefinitions
   */

  root.describeMixin = function (mixinPath, specDefinitions) {
    jasmine.getEnv().describeMixin(mixinPath, specDefinitions);
  };

  jasmine.Env.prototype.describeMixin = function (mixinPath, specDefinitions) {
    describe(mixinPath, function () {
      beforeEach(function () {
        this.Component = this.component = this.$node = null;

        var requireCallback = function (registry, defineComponent, Mixin) {
          registry.reset();
          this.Component = defineComponent(function () {}, Mixin);
        }.bind(this);

        require(['flight/lib/registry', 'flight/lib/component', mixinPath], requireCallback);

        waitsFor(function () {
          return this.Component !== null;
        });
      });

      afterEach(function () {
        if (this.$node) {
          this.$node.remove();
          this.$node = null;
        }

        var requireCallback = function (defineComponent) {
          if (this.component) {
            this.component = null;
          }

          this.Component = null;
          defineComponent.teardownAll();
        }.bind(this);

        require(['flight/lib/component'], requireCallback);

        waitsFor(function () {
          return this.Component === null;
        }.bind(this));
      });

      specDefinitions.apply(this);
    });
  };

  /**
   * Wrapper for describe. Load module before each test.
   *
   * @param modulePath
   * @param specDefinitions
   */

  root.describeModule = function (modulePath, specDefinitions) {
    return jasmine.getEnv().describeModule(modulePath, specDefinitions);
  };

  jasmine.Env.prototype.describeModule = function (modulePath, specDefinitions) {
    describe(modulePath, function () {
      beforeEach(function () {
        this.module = null;

        var requireCallback = function (module) {
          this.module = module;
        }.bind(this);

        require([modulePath], requireCallback);

        waitsFor(function () {
          return this.module !== null;
        });
      });
      specDefinitions.apply(this);
    });
  };

  /**
   * Create root node and initialize component. Fixture should be html string
   * or jQuery object.
   *
   * @param fixture {String} (Optional)
   * @param options {Options} (Optional)
   */

  root.setupComponent = function (fixture, options) {
    jasmine.getEnv().currentSpec.setupComponent(fixture, options);
  };

  jasmine.Spec.prototype.setupComponent = function (fixture, options) {
    if (this.component) {
      this.component.teardown();
      this.$node.remove();
    }

    this.$node = $('
');
    $('body').append(this.$node);

    if (fixture instanceof jQuery || typeof fixture === 'string') {
      this.$node.append(fixture);
    } else {
      options = fixture;
      fixture = null;
    }

    options = options === undefined ? {} : options;

    this.component = new this.Component(this.$node, options);
  };

  (function (namespace) {
    var eventsData = {
      spiedEvents: {},
      handlers:    []
    };

    namespace.formatElement = function ($element) {
      var limit = 200;
      var output = '';

      if ($element instanceof jQuery) {
        output = jasmine.JQuery.elementToString($element);
        if (output.length > limit) {
          output = output.slice(0, 200) + '...';
        }
      } else {
        //$element should always be a jQuery object
        output = 'element is not a jQuery object';
      }

      return output;
    };

    namespace.compareColors = function (color1, color2) {
      if (color1.charAt(0) === color2.charAt(0)) {
        return color1 === color2;
      } else {
        return namespace.hex2rgb(color1) === namespace.hex2rgb(color2);
      }
    };

    namespace.hex2rgb = function (colorString) {
      if (colorString.charAt(0) !== '#') return colorString;
      // note: hexStr should be #rrggbb
      var hex = parseInt(colorString.substring(1), 16);
      var r = (hex & 0xff0000) >> 16;
      var g = (hex & 0x00ff00) >> 8;
      var b = hex & 0x0000ff;
      return 'rgb(' + r + ', ' + g + ', ' + b + ')';
    };

    namespace.events = {
      spyOn: function (selector, eventName) {
        eventsData.spiedEvents[[selector, eventName]] = {
          callCount: 0,
          calls: [],
          mostRecentCall: {},
          name: eventName
        };

        var handler = function (e, data) {
          var call = {
            event: e,
            args: jasmine.util.argsToArray(arguments),
            data: data
          };
          eventsData.spiedEvents[[selector, eventName]].callCount++;
          eventsData.spiedEvents[[selector, eventName]].calls.push(call);
          eventsData.spiedEvents[[selector, eventName]].mostRecentCall = call;
        };

        jQuery(selector).on(eventName, handler);
        eventsData.handlers.push(handler);
        return eventsData.spiedEvents[[selector, eventName]];
      },

      eventArgs: function (selector, eventName, expectedArg) {
        var actualArgs = eventsData.spiedEvents[[selector, eventName]].mostRecentCall.args;

        if (!actualArgs) {
          throw 'No event spy found on ' + eventName + '. Try adding a call to spyOnEvent or make sure that the selector the event is triggered on and the selector being spied on are correct.';
        }

        // remove extra event metadata if it is not tested for
        if ((actualArgs.length === 2) && typeof actualArgs[1] === 'object' &&
          expectedArg && !expectedArg.scribeContext && !expectedArg.sourceEventData && !expectedArg.scribeData) {
          actualArgs[1] = $.extend({}, actualArgs[1]);
          delete actualArgs[1].sourceEventData;
          delete actualArgs[1].scribeContext;
          delete actualArgs[1].scribeData;
        }

        return actualArgs;
      },

      wasTriggered: function (selector, event) {
        var spiedEvent = eventsData.spiedEvents[[selector, event]];
        return spiedEvent && spiedEvent.callCount > 0;
      },

      wasTriggeredWith: function (selector, eventName, expectedArg, env) {
        var actualArgs = jasmine.flight.events.eventArgs(selector, eventName, expectedArg);
        return actualArgs && env.contains_(actualArgs, expectedArg);
      },

      wasTriggeredWithData: function (selector, eventName, expectedArg, env) {
        var actualArgs = jasmine.flight.events.eventArgs(selector, eventName, expectedArg);
        var valid;

        if (actualArgs) {
          valid = false;
          for (var i = 0; i < actualArgs.length; i++) {
            if (jasmine.flight.validateHash(expectedArg, actualArgs[i])) {
              return true;
            }
          }
          return valid;
        }

        return false;
      },

      cleanUp: function () {
        eventsData.spiedEvents = {};
        eventsData.handlers    = [];
      }
    };

    namespace.validateHash = function (a, b, intersection) {
      var validHash;
      for (var field in a) {
        if ((typeof a[field] === 'object') && (typeof b[field] === 'object')) {
          validHash = jasmine.flight.validateHash(a[field], b[field]);
        } else if (intersection && (typeof a[field] === 'undefined' || typeof b[field] === 'undefined')) {
          validHash = true;
        } else {
          validHash = (a[field] === b[field]);
        }
        if (!validHash) {
          break;
        }
      }
      return validHash;
    };
  })(jasmine.flight);

  beforeEach(function () {
    this.addMatchers({
      toHaveBeenTriggeredOn: function () {
        var selector = arguments[0];
        var eventName = typeof this.actual === 'string' ? this.actual : this.actual.name;
        var wasTriggered = jasmine.flight.events.wasTriggered(selector, eventName);

        this.message = function () {
          var $pp = function (obj) {
            var description;
            var attr;

            if (!(obj instanceof jQuery)) {
              obj = $(obj);
            }

            description = [
              obj.get(0).nodeName
            ];

            attr = obj.get(0).attributes || [];

            for (var x = 0; x < attr.length; x++) {
              description.push(attr[x].name + '="' + attr[x].value + '"');
            }

            return '<' + description.join(' ') + '>';
          };

          if (wasTriggered) {
            return [
              '
Expected event ' + eventName + ' to have been triggered on' + selector,
              '
Expected event ' + eventName + ' not to have been triggered on' + selector
            ];
          } else {
            return [
              'Expected event ' + eventName + ' to have been triggered on ' + $pp(selector),
              'Expected event ' + eventName + ' not to have been triggered on ' + $pp(selector)
            ];
          }
        };

        return wasTriggered;
      },

      toHaveBeenTriggeredOnAndWith: function () {
        var selector = arguments[0];
        var expectedArg = arguments[1];
        var exactMatch = !arguments[2];
        var wasTriggered = jasmine.flight.events.wasTriggered(selector, this.actual);

        this.message = function () {
          var $pp = function (obj) {
            var description;
            var attr;

            if (!(obj instanceof jQuery)) {
              obj = $(obj);
            }

            description = [
              obj.get(0).nodeName
            ];

            attr = obj.get(0).attributes || [];

            for (var x = 0; x < attr.length; x++) {
              description.push(attr[x].name + '="' + attr[x].value + '"');
            }

            return '<' + description.join(' ') + '>';
          };

          if (wasTriggered) {
            var actualArg = jasmine.flight.events.eventArgs(selector, this.actual, expectedArg)[1];
            return [
              '
Expected event ' + this.actual.name + ' to have been triggered on' + selector,
              '
Expected event ' + this.actual.name + ' not to have been triggered on' + selector
            ];
          } else {
            return [
              'Expected event ' + this.actual.name + ' to have been triggered on ' + $pp(selector),
              'Expected event ' + this.actual.name + ' not to have been triggered on ' + $pp(selector)
            ];
          }
        };

        if (!wasTriggered) {
          return false;
        }
        if (exactMatch) {
          return jasmine.flight.events.wasTriggeredWith(selector, this.actual, expectedArg, this.env);
        } else {
          return jasmine.flight.events.wasTriggeredWithData(selector, this.actual, expectedArg, this.env);
        }
      },

      toHaveCss: function (prop, val) {
        var result;
        if (val instanceof RegExp) {
          result = val.test(this.actual.css(prop));
        } else if (prop.match(/color/)) {
          //IE returns colors as hex strings; other browsers return rgb(r, g, b) strings
          result = jasmine.flight.compareColors(this.actual.css(prop), val);
        } else {
          result = this.actual.css(prop) === val;
          //sometimes .css() returns strings when it should return numbers
          if (!result && typeof val === 'number') {
            result = parseFloat(this.actual.css(prop), 10) === val;
          }
        }

        this.actual = jasmine.flight.formatElement(this.actual);
        return result;
      }
    });
  });

  root.spyOnEvent = function (selector, eventName) {
    jasmine.JQuery.events.spyOn(selector, eventName);
    return jasmine.flight.events.spyOn(selector, eventName);
  };

}(this));
<|endoftext|>