<commit_before>
var OUR_NAME = 'node';

function rank2Num(rank) {
  switch (rank) {
    case 'J': return 11;
    case 'Q': return 12;
    case 'K': return 13;
    case 'A': return 14;
    default: return parseInt(rank);
  }
}

/**
 * @returns false - если не префлоп
 *      1000 - если пара или больше или равно 10
 *      0 - если нужно сбросить карты
 */
function preflop_stage(game_state) {

    var player = game_state.players[game_state.in_action];

    if ( player.hole_cards.length != 2 ) {
      return false;
    }

    var card1 = player.hole_cards[0];
    var card2 = player.hole_cards[1];
    var rank1 = rank2Num(card1.rank);
    var rank2 = rank2Num(card2.rank);
    var bet = 0, min_raise = 0;

    if (game_state.current_buy_in > parseInt(game_state.small_blind) * 2) {
      if (rank1 > 11 && rank2 > 11) {
        bet = player.stack;
      }
    } else if ((rank1 + rank2 >= 17)) {
      bet = parseInt(game_state.small_blind) * 6;
    }

    return bet;
}

function flop_request(game_state) {
  var player = game_state.players[game_state.in_action],
      stack = player.stack,
      card1 = player.hole_cards[0],
      card2 = player.hole_cards[1],
      rank1 = rank2Num(card1.rank),
      rank2 = rank2Num(card2.rank),
      numOfPlayers = game_state.players.length,
      communityCards = game_state.community_cards;

  var allCards = [], i;
  var isPair=0, isTwoPair = 0, isThree = 0, isFour = 0, isFlash = 0;
  var arPairs = {
    1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0
  };

  allCards.push(card1);
  arPairs[rank1] += 1;
  arPairs[rank2] += 1;

  allCards.push(card2);

  console.log('Stack in flop: ' + stack);

  for (var card in communityCards) {
    allCards.push(card);
    arPairs[card.rank] += 1;
  }

  for (i in allCards) {
    arPairs[rank2(allCards[i].rank)] += 1;
  }

  for (i in arPairs) {
    if(arPairs[i] == 4) {
      isFour = 1;
    } else if(arPairs[i] == 3) {
      isThree = 1;
    } else if(arPairs[i] == 2) {
      if( isPair >  0) {
        isTwoPair = 1;
      } else {
        isPair = 1;
      }
    }
  }

  if (isFour || isThree ) {
    return stack;
  }

  if ( isTwoPair || isPair ) {
    min_raise = game_state.current_buy_in - player.bet + game_state.minimum_raise;
    return min_raise;
  }

  return 0;
}

function turn_request(game_state) {
  var player = game_state.players[game_state.in_action],
      stack = player.stack,
      card1 = player.hole_cards[0],
      card2 = player.hole_cards[1],
      rank1 = rank2Num(card1.rank),
      rank2 = rank2Num(card2.rank),
      numOfPlayers = game_state.players.length,
      communityCards = game_state.community_cards;
  var allCards = [];
  allCards.push(card1);
  allCards.push(card2);
  for (var card in communityCards) {
      allCards.push(card);
  }

  console.log('Stack in flop: ' + stack);

  return stack;
}

function river_request(game_state) {
  var player = game_state.players[game_state.in_action],
      stack = player.stack,
      card1 = player.hole_cards[0],
      card2 = player.hole_cards[1],
      rank1 = rank2Num(card1.rank),
      rank2 = rank2Num(card2.rank),
      numOfPlayers = game_state.players.length,
      communityCards = game_state.community_cards;
  var allCards = [];
  allCards.push(card1);
  allCards.push(card2);
  for (var card in communityCards) {
      allCards.push(card);
  }

  console.log('Stack in flop: ' + stack);

  return stack;
}

module.exports = {

  exception: false,
  show_log:true,
  VERSION: "Stage flop",

  log: function () {
      if (this.show_log) {
          console.log(arguments);
      }
  },

  bet_request: function(game_state) {
    try {
      this.log('game_state_json', JSON.stringify(game_state));

      var player = game_state.players[game_state.in_action];
      if ( player.hole_cards.length != 2 ) {
        return false;
      }
      var bet = 0;

      if ( game_state.community_cards ) {
        var tableState = game_state.community_cards.length;

        if ( tableState == 0 ) {
          bet = preflop_stage(game_state);
        } else if ( tableState == 3 ) {
          bet = flop_request(game_state);
        } else if ( tableState == 4 ) {
          bet = turn_request(game_state);
        } else if ( tableState == 5 ) {
          bet = river_request(game_state);
        } else {
          return 0;
        }
      }
      return bet;
    } catch (e) {
      this.exception = true;
      console.log(e);
      console.log('EXCEPTION!' + e.name + ":" + e.message + "\n" + e.stack);
      return 1000;
    }
  },

  showdown: function(game_state) {

  },

};
<commit_msg>flop starategy<commit_after>
var OUR_NAME = 'node';

function rank2Num(rank) {
  switch (rank) {
    case 'J': return 11;
    case 'Q': return 12;
    case 'K': return 13;
    case 'A': return 14;
    default: return parseInt(rank);
  }
}

/**
 * @returns false - если не префлоп
 *      1000 - если пара или больше или равно 10
 *      0 - если нужно сбросить карты
 */
function preflop_stage(game_state) {

    var player = game_state.players[game_state.in_action];

    if ( player.hole_cards.length != 2 ) {
      return false;
    }

    var card1 = player.hole_cards[0];
    var card2 = player.hole_cards[1];
    var rank1 = rank2Num(card1.rank);
    var rank2 = rank2Num(card2.rank);
    var bet = 0, min_raise = 0;

    if (game_state.current_buy_in > parseInt(game_state.small_blind) * 2) {
      if (rank1 > 11 && rank2 > 11) {
        bet = player.stack;
      }
    } else if ((rank1 + rank2 >= 17)) {
      bet = parseInt(game_state.small_blind) * 6;
    }

    return bet;
}

function flop_request(game_state) {
  var player = game_state.players[game_state.in_action],
      stack = player.stack,
      card1 = player.hole_cards[0],
      card2 = player.hole_cards[1],
      rank1 = rank2Num(card1.rank),
      rank2 = rank2Num(card2.rank),
      numOfPlayers = game_state.players.length,
      communityCards = game_state.community_cards;

  var allCards = [], i;
  var isPair=0, isTwoPair = 0, isThree = 0, isFour = 0, isFlash = 0;
  var arPairs = {
    1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9:0, 10:0, 11:0, 12:0, 13:0, 14:0
  };

  allCards.push(card1);
  arPairs[rank1] += 1;
  arPairs[rank2] += 1;

  allCards.push(card2);

  console.log('Stack in flop: ' + stack);

  for (var card in communityCards) {
    allCards.push(card);
    arPairs[rank2Num(card.rank)] += 1;
  }

  for (i in arPairs) {
    if(arPairs[i] == 4) {
      isFour = 1;
    } else if(arPairs[i] == 3) {
      isThree = 1;
    } else if(arPairs[i] == 2) {
      if( isPair >  0) {
        isTwoPair = 1;
      } else {
        isPair = 1;
      }
    }
  }

  if (isFour || isThree ) {
    return stack;
  }

  if ( isTwoPair || isPair ) {
    min_raise = game_state.current_buy_in - player.bet + game_state.minimum_raise;
    return min_raise;
  }

  return 0;
}

function turn_request(game_state) {
  var player = game_state.players[game_state.in_action],
      stack = player.stack,
      card1 = player.hole_cards[0],
      card2 = player.hole_cards[1],
      rank1 = rank2Num(card1.rank),
      rank2 = rank2Num(card2.rank),
      numOfPlayers = game_state.players.length,
      communityCards = game_state.community_cards;
  var allCards = [];
  allCards.push(card1);
  allCards.push(card2);
  for (var card in communityCards) {
      allCards.push(card);
  }

  console.log('Stack in flop: ' + stack);

  return stack;
}

function river_request(game_state) {
  var player = game_state.players[game_state.in_action],
      stack = player.stack,
      card1 = player.hole_cards[0],
      card2 = player.hole_cards[1],
      rank1 = rank2Num(card1.rank),
      rank2 = rank2Num(card2.rank),
      numOfPlayers = game_state.players.length,
      communityCards = game_state.community_cards;
  var allCards = [];
  allCards.push(card1);
  allCards.push(card2);
  for (var card in communityCards) {
      allCards.push(card);
  }

  console.log('Stack in flop: ' + stack);

  return stack;
}

module.exports = {

  exception: false,
  show_log:true,
  VERSION: "Stage flop",

  log: function () {
      if (this.show_log) {
          console.log(arguments);
      }
  },

  bet_request: function(game_state) {
    try {
      this.log('game_state_json', JSON.stringify(game_state));

      var player = game_state.players[game_state.in_action];
      if ( player.hole_cards.length != 2 ) {
        return false;
      }
      var bet = 0;

      if ( game_state.community_cards ) {
        var tableState = game_state.community_cards.length;

        if ( tableState == 0 ) {
          bet = preflop_stage(game_state);
        } else if ( tableState == 3 ) {
          bet = flop_request(game_state);
        } else if ( tableState == 4 ) {
          bet = turn_request(game_state);
        } else if ( tableState == 5 ) {
          bet = river_request(game_state);
        } else {
          return 0;
        }
      }
      return bet;
    } catch (e) {
      this.exception = true;
      console.log(e);
      console.log('EXCEPTION!' + e.name + ":" + e.message + "\n" + e.stack);
      return 1000;
    }
  },

  showdown: function(game_state) {

  },

};
<|endoftext|>


<commit_before>'use strict';
var fs = require('fs');

var template = fs.readFileSync(__dirname + '/cam-tasklist-tasks.html', 'utf8');

var angular = require('camunda-commons-ui/vendor/angular');
var $ = require('jquery');

module.exports = [function() {

  return {

    restrict: 'A',
    scope: {
      tasklistData: '='
    },

    template: template,

    controller: [
      '$element',
      '$scope',
      '$location',
      'search',
      'Views',
      '$timeout',
      function(
        $element,
        $scope,
        $location,
        search,
        Views,
        $timeout
      ) {

        function updateSilently(params) {
          search.updateSilently(params);
        }

        $scope.expanded = {};
        $scope.toggle = function(delta, $event) {
          $scope.expanded[delta] = !$scope.expanded[delta];
          if ($event && $event.preventDefault) {
            $event.preventDefault();
          }
          $event.stopPropagation();
        };

        $scope.pageNum = 1;
        $scope.pageSize = null;
        $scope.totalItems = 0;
        $scope.now = (new Date()).toJSON();

        $scope.filterProperties = null;

        var tasksData = $scope.tasklistData.newChild($scope);

        $scope.query = {};

        var assignees = $scope.assignees = {};
        var parseAssignees = function(assigneeList) {
          for(var i = 0; i < assigneeList.length; i++) {
            $scope.assignees[assigneeList[i].id] = assigneeList[i];
          }
        };

        function updateShutters() {
          $('.task-card-details').each(function() {
            var h = 0;
            $('view', this).each(function() {
              h += this.clientHeight;
            });

            if (h <= 20) {
              $(this).addClass('no-shutter');
            }
          });
        }

        var postLoadingJobs = [];
        var executePostLoadingJobs = function() {
          postLoadingJobs.push(function() {
            $timeout(updateShutters);
          });
          postLoadingJobs.forEach(function(job) {
            job();
          });
          postLoadingJobs = [];
          $scope.expanded = {};
        };

        /**
         * observe the list of tasks
         */
        $scope.state = tasksData.observe('taskList', function(taskList) {
          $scope.totalItems = taskList.count;
          $scope.tasks = taskList._embedded.task;
          if(taskList._embedded.assignee) {
            parseAssignees(taskList._embedded.assignee);
          }
          executePostLoadingJobs();
        });

        $scope.$on('shortcut:focusList', function() {
          var el = document.querySelector('[cam-tasks] .tasks-list li:first-child a');
          if(el) {
            el.focus();
          }
        });

        $scope.assigneeDisplayedName = function(task) {
          var _assignee = assignees[task.assignee] || {};
          var hasFirstLastName = _assignee.firstName || _assignee.lastName;
          if (hasFirstLastName) {
            return ((_assignee.firstName || '') + ' ' + (_assignee.lastName || ''));
          }
          else if (!(assignees[task.assignee] && hasFirstLastName)) {
            return task.assignee;
          }
          return '<nobody>';
        };

        /**
         * observe the task list query
         */
        tasksData.observe('taskListQuery', function(taskListQuery) {
          if (taskListQuery) {
            // parse pagination properties from query
            $scope.query = angular.copy(taskListQuery);
            $scope.pageSize = $scope.query.maxResults;
            // Sachbearbeiter starts counting at '1'
            $scope.pageNum = ($scope.query.firstResult / $scope.pageSize) + 1;
            tasksData.set('taskId', { 'taskId' : null });
          }
        });

        tasksData.observe('taskId', function(taskId) {
          $scope.currentTaskId = taskId.taskId;
        });

        /**
         * Observes the properties of the current filter.
         * Used to retrieve information about variables displayed on a task.
         */
        tasksData.observe(['currentFilter', function(currentFilter) {
          if (currentFilter) {
            $scope.filterProperties = currentFilter !== null ? currentFilter.properties : null;
          }
        }]);

        $scope.focus = function($event, task) {
          if ($event) {
            $event.preventDefault();
          }

          var taskId = task.id;
          tasksData.set('taskId', { 'taskId' : taskId });
          $scope.currentTaskId = taskId;

          var searchParams = $location.search() || {};
          searchParams.task = taskId;
          updateSilently(searchParams);

          var el = document.querySelector('[cam-tasks] .tasks-list .task [href*="#/?task=' + taskId + '"]');
          if(el) {
            el.focus();
          }
        };

        var selectNextTask = function() {
          for(var i = 0; i < $scope.tasks.length - 1; i++) {
            if($scope.tasks[i].id === $scope.currentTaskId) {
              return $scope.focus(null, $scope.tasks[i+1]);
            }
          }
          if($scope.pageNum < Math.ceil($scope.totalItems / $scope.pageSize)) {
            $scope.pageNum++;
            $scope.pageChange();
            postLoadingJobs.push(function() {
              // wait until the html is applied so you can focus the html element
              $timeout(function() {
                $scope.focus(null, $scope.tasks[0]);
              });
            });
          }
        };

        var selectPreviousTask = function() {
          for(var i = 1; i < $scope.tasks.length; i++) {
            if($scope.tasks[i].id === $scope.currentTaskId) {
              return $scope.focus(null, $scope.tasks[i-1]);
            }
          }
          if($scope.pageNum > 1) {
            $scope.pageNum--;
            $scope.pageChange();
            postLoadingJobs.push(function() {
              // wait until the html is applied so you can focus the html element
              $timeout(function() {
                $scope.focus(null, $scope.tasks[$scope.tasks.length - 1]);
              });
            });
          }
        };

        $scope.handleKeydown = function($event) {
          if($event.keyCode === 40) {
            $event.preventDefault();
            selectNextTask($event);
          }
          else if($event.keyCode === 38) {
            $event.preventDefault();
            selectPreviousTask();
          }
          // wait for angular to update the classes and scroll to the newly selected task
          $timeout(function() {
            var $el = $($event.target).find('li.active')[0];
            if ($el) {
              $el.scrollIntoView(false);
            }
          });
        };

        $scope.getHrefUrl = function(task) {
          var href = '#/?task=' + task.id;
          var detailsTab = $location.search().detailsTab;
          if (detailsTab) {
            href = href + '&detailsTab=' + detailsTab;
          }

          return href;
        };

        $scope.cardPluginVars = { read: [ 'task', 'filterProperties' ] };
        $scope.cardPlugins = Views.getProviders({
          component: 'tasklist.card'
        });

        /**
         * invoked when pagination is changed
         */
        $scope.pageChange = function() {
          // update query
          updateSilently({
            page:  $scope.pageNum
          });
          tasksData.changed('taskListQuery');
        };

        $scope.resetPage = function() {
          updateSilently({
            page: 1
          });
          tasksData.changed('taskListQuery');
        };

      }]
  };
}];
<commit_msg>fix(tasklist): keep focus on selected task when pressing F5<commit_after>'use strict';
var fs = require('fs');

var template = fs.readFileSync(__dirname + '/cam-tasklist-tasks.html', 'utf8');

var angular = require('camunda-commons-ui/vendor/angular');
var $ = require('jquery');

module.exports = [function() {

  return {

    restrict: 'A',
    scope: {
      tasklistData: '='
    },

    template: template,

    controller: [
      '$element',
      '$scope',
      '$location',
      'search',
      'Views',
      '$timeout',
      function(
        $element,
        $scope,
        $location,
        search,
        Views,
        $timeout
      ) {

        function updateSilently(params) {
          search.updateSilently(params);
        }

        $scope.expanded = {};
        $scope.toggle = function(delta, $event) {
          $scope.expanded[delta] = !$scope.expanded[delta];
          if ($event && $event.preventDefault) {
            $event.preventDefault();
          }
          $event.stopPropagation();
        };

        $scope.pageNum = 1;
        $scope.pageSize = null;
        $scope.totalItems = 0;
        $scope.now = (new Date()).toJSON();

        $scope.filterProperties = null;

        var tasksData = $scope.tasklistData.newChild($scope);

        $scope.query = {};

        var assignees = $scope.assignees = {};
        var parseAssignees = function(assigneeList) {
          for(var i = 0; i < assigneeList.length; i++) {
            $scope.assignees[assigneeList[i].id] = assigneeList[i];
          }
        };

        function updateShutters() {
          $('.task-card-details').each(function() {
            var h = 0;
            $('view', this).each(function() {
              h += this.clientHeight;
            });

            if (h <= 20) {
              $(this).addClass('no-shutter');
            }
          });
        }

        var postLoadingJobs = [];
        var executePostLoadingJobs = function() {
          postLoadingJobs.push(function() {
            $timeout(updateShutters);
          });
          postLoadingJobs.forEach(function(job) {
            job();
          });
          postLoadingJobs = [];
          $scope.expanded = {};
        };

        /**
         * observe the list of tasks
         */
        $scope.state = tasksData.observe('taskList', function(taskList) {
          $scope.totalItems = taskList.count;
          $scope.tasks = taskList._embedded.task;
          if(taskList._embedded.assignee) {
            parseAssignees(taskList._embedded.assignee);
          }
          executePostLoadingJobs();
        });

        $scope.$on('shortcut:focusList', function() {
          var el = document.querySelector('[cam-tasks] .tasks-list li:first-child a');
          if(el) {
            el.focus();
          }
        });

        $scope.assigneeDisplayedName = function(task) {
          var _assignee = assignees[task.assignee] || {};
          var hasFirstLastName = _assignee.firstName || _assignee.lastName;
          if (hasFirstLastName) {
            return ((_assignee.firstName || '') + ' ' + (_assignee.lastName || ''));
          }
          else if (!(assignees[task.assignee] && hasFirstLastName)) {
            return task.assignee;
          }
          return '<nobody>';
        };

        /**
         * observe the task list query
         */
        tasksData.observe('taskListQuery', function(taskListQuery) {
          if (taskListQuery) {

            var oldQuery = $scope.query;

            // parse pagination properties from query
            $scope.query = angular.copy(taskListQuery);
            $scope.pageSize = $scope.query.maxResults;
            // Sachbearbeiter starts counting at '1'
            $scope.pageNum = ($scope.query.firstResult / $scope.pageSize) + 1;

            if (oldQuery.id) {
              tasksData.set('taskId', { 'taskId' : null });
              var searchParams = $location.search() || {};
              searchParams.task = null;
              updateSilently(searchParams);
            }
          }
        });

        tasksData.observe('taskId', function(taskId) {
          $scope.currentTaskId = taskId.taskId;
        });

        /**
         * Observes the properties of the current filter.
         * Used to retrieve information about variables displayed on a task.
         */
        tasksData.observe(['currentFilter', function(currentFilter) {
          if (currentFilter) {
            $scope.filterProperties = currentFilter !== null ? currentFilter.properties : null;
          }
        }]);

        $scope.focus = function($event, task) {
          if ($event) {
            $event.preventDefault();
          }

          var taskId = task.id;
          tasksData.set('taskId', { 'taskId' : taskId });
          $scope.currentTaskId = taskId;

          var searchParams = $location.search() || {};
          searchParams.task = taskId;
          updateSilently(searchParams);

          var el = document.querySelector('[cam-tasks] .tasks-list .task [href*="#/?task=' + taskId + '"]');
          if(el) {
            el.focus();
          }
        };

        var selectNextTask = function() {
          for(var i = 0; i < $scope.tasks.length - 1; i++) {
            if($scope.tasks[i].id === $scope.currentTaskId) {
              return $scope.focus(null, $scope.tasks[i+1]);
            }
          }
          if($scope.pageNum < Math.ceil($scope.totalItems / $scope.pageSize)) {
            $scope.pageNum++;
            $scope.pageChange();
            postLoadingJobs.push(function() {
              // wait until the html is applied so you can focus the html element
              $timeout(function() {
                $scope.focus(null, $scope.tasks[0]);
              });
            });
          }
        };

        var selectPreviousTask = function() {
          for(var i = 1; i < $scope.tasks.length; i++) {
            if($scope.tasks[i].id === $scope.currentTaskId) {
              return $scope.focus(null, $scope.tasks[i-1]);
            }
          }
          if($scope.pageNum > 1) {
            $scope.pageNum--;
            $scope.pageChange();
            postLoadingJobs.push(function() {
              // wait until the html is applied so you can focus the html element
              $timeout(function() {
                $scope.focus(null, $scope.tasks[$scope.tasks.length - 1]);
              });
            });
          }
        };

        $scope.handleKeydown = function($event) {
          if($event.keyCode === 40) {
            $event.preventDefault();
            selectNextTask($event);
          }
          else if($event.keyCode === 38) {
            $event.preventDefault();
            selectPreviousTask();
          }
          // wait for angular to update the classes and scroll to the newly selected task
          $timeout(function() {
            var $el = $($event.target).find('li.active')[0];
            if ($el) {
              $el.scrollIntoView(false);
            }
          });
        };

        $scope.getHrefUrl = function(task) {
          var href = '#/?task=' + task.id;
          var detailsTab = $location.search().detailsTab;
          if (detailsTab) {
            href = href + '&detailsTab=' + detailsTab;
          }

          return href;
        };

        $scope.cardPluginVars = { read: [ 'task', 'filterProperties' ] };
        $scope.cardPlugins = Views.getProviders({
          component: 'tasklist.card'
        });

        /**
         * invoked when pagination is changed
         */
        $scope.pageChange = function() {
          // update query
          updateSilently({
            page:  $scope.pageNum
          });
          tasksData.changed('taskListQuery');
        };

        $scope.resetPage = function() {
          updateSilently({
            page: 1
          });
          tasksData.changed('taskListQuery');
        };

      }]
  };
}];
<|endoftext|>


<commit_before>/**
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var assert = require('assert');
var async = require('async');
var uuid = require('node-uuid');

var env = require('./env.js');
var gcloud = require('../lib')(env);

var Subscription = require('../lib/pubsub/subscription.js');

var pubsub = gcloud.pubsub();

function generateTopicName() {
  return 'test-topic-' + uuid.v4();
}

function generateSubName() {
  return 'test-subscription-' + uuid.v4();
}

describe('pubsub', function() {
  var TOPIC_NAMES = [
    generateTopicName(),
    generateTopicName(),
    generateTopicName()
  ];

  var TOPICS = TOPIC_NAMES.map(pubsub.topic.bind(pubsub));

  var TOPIC_FULL_NAMES = TOPICS.map(function(topic) {
    return topic.name;
  });

  before(function(done) {
    // create all needed topics
    async.each(TOPIC_NAMES, function(name, cb) {
      pubsub.createTopic(name, cb);
    }, done);
  });

  after(function(done) {
    // Delete topics
    async.each(TOPICS, function(topic, callback) {
      topic.delete(callback);
    }, done);
  });

  describe('Topic', function() {
    it('should be listed', function(done) {
      pubsub.getTopics(function(err, topics) {
        assert.ifError(err);

        var results = topics.filter(function(topic) {
          return TOPIC_FULL_NAMES.indexOf(topic.name) !== -1;
        });

        // get all topics in list of known names
        assert.equal(results.length, TOPIC_NAMES.length);
        done();
      });
    });

    it('should list topics in a stream', function(done) {
      var topicsEmitted = [];

      pubsub.getTopics()
        .on('error', done)
        .on('data', function(topic) {
          topicsEmitted.push(topic);
        })
        .on('end', function() {
          var results = topicsEmitted.filter(function(topic) {
            return TOPIC_FULL_NAMES.indexOf(topic.name) !== -1;
          });

          assert.equal(results.length, TOPIC_NAMES.length);
          done();
        });
    });

    it('should allow manual paging', function(done) {
      pubsub.getTopics({
        pageSize: TOPIC_NAMES.length - 1
      }, function(err, topics, nextQuery) {
        assert.ifError(err);
        assert(topics.length, TOPIC_NAMES.length - 1);
        assert(nextQuery.pageSize, TOPIC_NAMES.length - 1);
        assert(!!nextQuery.pageToken, true);
        done();
      });
    });

    it('should be created and deleted', function(done) {
      var TOPIC_NAME = generateTopicName();
      pubsub.createTopic(TOPIC_NAME, function(err) {
        assert.ifError(err);
        pubsub.topic(TOPIC_NAME).delete(done);
      });
    });

    it('should lazily create by default', function(done) {
      var newTopicName = generateTopicName();
      var newTopic = pubsub.topic(newTopicName);

      newTopic.publish({ data: 'message from me' }, function(err) {
        assert.ifError(err);

        pubsub.getTopics(function(err, topics) {
          assert.ifError(err);

          assert(topics.some(function(topic) {
            return topic.name.indexOf(newTopicName) > -1;
          }));

          newTopic.delete(done);
        });
      });
    });

    it('should publish a message', function(done) {
      var topic = pubsub.topic(TOPIC_NAMES[0]);
      topic.publish({ data: 'message from me' }, function(err, messageIds) {
        assert.ifError(err);
        assert.equal(messageIds.length, 1);
        done();
      });
    });
  });

  describe('Subscription', function() {
    var TOPIC_NAME = generateTopicName();

    var SUB_NAMES = [
      generateSubName(),
      generateSubName()
    ];

    var SUBSCRIPTIONS = [
      {
        name: SUB_NAMES[0],
        options: { ackDeadlineSeconds: 30 }
      },
      {
        name: SUB_NAMES[1],
        options: { ackDeadlineSeconds: 60 }
      }
    ];

    var topic;

    before(function(done) {
      // Create a new test topic.
      pubsub.createTopic(TOPIC_NAME, function(err, newTopic) {
        assert.ifError(err);
        topic = newTopic;

        // Create subscriptions.
        async.parallel(SUBSCRIPTIONS.map(function(sub) {
          return topic.subscribe.bind(topic, sub.name, sub.options);
        }), done);
      });
    });

    after(function(done) {
      var SUBS = SUB_NAMES.map(function(name) {
        return topic.subscription(name);
      });

      // Delete subscriptions
      async.each(SUBS, function(sub, callback) {
        sub.delete(callback);
      }, function(err) {
        assert.ifError(err);
        topic.delete(done);
      });
    });

    it('should list all subscriptions registered to the topic', function(done) {
      topic.getSubscriptions(function(err, subs) {
        assert.ifError(err);
        assert(subs[0] instanceof Subscription);
        assert.equal(subs.length, SUBSCRIPTIONS.length);
        done();
      });
    });

    it('should list all topic subscriptions as a stream', function(done) {
      var subscriptionsEmitted = [];

      topic.getSubscriptions()
        .on('error', done)
        .on('data', function(subscription) {
          subscriptionsEmitted.push(subscription);
        })
        .on('end', function() {
          assert.equal(subscriptionsEmitted.length, SUBSCRIPTIONS.length);
          done();
        });
    });

    it('should list all subscriptions regardless of topic', function(done) {
      pubsub.getSubscriptions(function(err, subscriptions) {
        assert.ifError(err);
        assert(subscriptions instanceof Array);
        done();
      });
    });

    it('should list all subscriptions as a stream', function(done) {
      var subscriptionEmitted = false;

      pubsub.getSubscriptions()
        .on('error', done)
        .on('data', function(subscription) {
          subscriptionEmitted = subscription instanceof Subscription;
        })
        .on('end', function() {
          assert.strictEqual(subscriptionEmitted, true);
          done();
        });
    });

    it('should allow creation and deletion of a subscription', function(done) {
      var subName = generateSubName();
      topic.subscribe(subName, function(err, sub) {
        assert.ifError(err);
        assert(sub instanceof Subscription);
        sub.delete(done);
      });
    });

    it('should error when using a non-existent subscription', function(done) {
      var subscription = topic.subscription(generateSubName());

      subscription.pull(function(err) {
        assert.equal(err.code, 404);
        done();
      });
    });

    it('should be able to pull and ack', function(done) {
      var subscription = topic.subscription(SUB_NAMES[0]);

      topic.publish({ data: 'hello' }, function(err) {
        assert.ifError(err);

        subscription.pull({
          returnImmediately: false,
          maxResults: 1
        }, function(err, msgs) {
          assert.ifError(err);
          subscription.ack(msgs[0].ackId, done);
        });
      });
    });

    it('should be able to set a new ack deadline', function(done) {
      var subscription = topic.subscription(SUB_NAMES[0]);

      topic.publish({ data: 'hello' }, function(err) {
        assert.ifError(err);

        subscription.pull({
          returnImmediately: false,
          maxResults: 1
        }, function(err, msgs) {
          assert.ifError(err);

          var options = {
            ackIds: [msgs[0].ackId],
            seconds: 10
          };
          subscription.setAckDeadline(options, done);
        });
      });
    });

    it('should receive the published message', function(done) {
      var subscription = topic.subscription(SUB_NAMES[1]);

      topic.publish([
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' }
      ], function(err) {
        assert.ifError(err);

        subscription.pull({
          returnImmediately: false,
          maxResults: 1
        }, function(err, msgs) {
          assert.ifError(err);
          assert.equal(msgs[0].data, 'hello');
          subscription.ack(msgs[0].ackId, done);
        });
      });
    });

    it('should receive a raw published message', function(done) {
      var subscription = topic.subscription(SUB_NAMES[0]);

      topic.publish([
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' }
      ], function(err) {
        assert.ifError(err);

        subscription.pull({
          returnImmediately: false,
          maxResults: 1
        }, function(err, msgs) {
          assert.ifError(err);
          assert.equal(msgs[0].data, 'hello');
          subscription.ack(msgs[0].ackId, done);
        });
      });
    });

    it('should receive the chosen amount of results', function(done) {
      var subscription = topic.subscription(SUB_NAMES[1]);
      var opts = { returnImmediately: false, maxResults: 3 };

      topic.publish([
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' }
      ], function(err) {
        assert.ifError(err);

        subscription.pull(opts, function(err, messages) {
          assert.ifError(err);

          assert.equal(messages.length, opts.maxResults);

          var ackIds = messages.map(function(message) {
            return message.ackId;
          });

          subscription.ack(ackIds, done);
        });
      });
    });
  });
});
<commit_msg>pubsub: remove autoCreate, add getMetadata<commit_after>/**
 * Copyright 2014 Google Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

'use strict';

var assert = require('assert');
var async = require('async');
var uuid = require('node-uuid');

var env = require('./env.js');
var gcloud = require('../lib')(env);

var Subscription = require('../lib/pubsub/subscription.js');

var pubsub = gcloud.pubsub();

function generateTopicName() {
  return 'test-topic-' + uuid.v4();
}

function generateSubName() {
  return 'test-subscription-' + uuid.v4();
}

describe('pubsub', function() {
  var TOPIC_NAMES = [
    generateTopicName(),
    generateTopicName(),
    generateTopicName()
  ];

  var TOPICS = TOPIC_NAMES.map(pubsub.topic.bind(pubsub));

  var TOPIC_FULL_NAMES = TOPICS.map(function(topic) {
    return topic.name;
  });

  before(function(done) {
    // create all needed topics
    async.each(TOPIC_NAMES, function(name, cb) {
      pubsub.createTopic(name, cb);
    }, done);
  });

  after(function(done) {
    // Delete topics
    async.each(TOPICS, function(topic, callback) {
      topic.delete(callback);
    }, done);
  });

  describe('Topic', function() {
    it('should be listed', function(done) {
      pubsub.getTopics(function(err, topics) {
        assert.ifError(err);

        var results = topics.filter(function(topic) {
          return TOPIC_FULL_NAMES.indexOf(topic.name) !== -1;
        });

        // get all topics in list of known names
        assert.equal(results.length, TOPIC_NAMES.length);
        done();
      });
    });

    it('should list topics in a stream', function(done) {
      var topicsEmitted = [];

      pubsub.getTopics()
        .on('error', done)
        .on('data', function(topic) {
          topicsEmitted.push(topic);
        })
        .on('end', function() {
          var results = topicsEmitted.filter(function(topic) {
            return TOPIC_FULL_NAMES.indexOf(topic.name) !== -1;
          });

          assert.equal(results.length, TOPIC_NAMES.length);
          done();
        });
    });

    it('should allow manual paging', function(done) {
      pubsub.getTopics({
        pageSize: TOPIC_NAMES.length - 1
      }, function(err, topics, nextQuery) {
        assert.ifError(err);
        assert(topics.length, TOPIC_NAMES.length - 1);
        assert(nextQuery.pageSize, TOPIC_NAMES.length - 1);
        assert(!!nextQuery.pageToken, true);
        done();
      });
    });

    it('should be created and deleted', function(done) {
      var TOPIC_NAME = generateTopicName();
      pubsub.createTopic(TOPIC_NAME, function(err) {
        assert.ifError(err);
        pubsub.topic(TOPIC_NAME).delete(done);
      });
    });

    it('should publish a message', function(done) {
      var topic = pubsub.topic(TOPIC_NAMES[0]);
      topic.publish({ data: 'message from me' }, function(err, messageIds) {
        assert.ifError(err);
        assert.equal(messageIds.length, 1);
        done();
      });
    });

    it('should get the metadata of a topic', function(done) {
      var topic = pubsub.topic(TOPIC_NAMES[0]);
      topic.getMetadata(function(err, metadata) {
        assert.ifError(err);
        assert.strictEqual(metadata.name, topic.name);
        done();
      });
    });
  });

  describe('Subscription', function() {
    var TOPIC_NAME = generateTopicName();

    var SUB_NAMES = [
      generateSubName(),
      generateSubName()
    ];

    var SUBSCRIPTIONS = [
      {
        name: SUB_NAMES[0],
        options: { ackDeadlineSeconds: 30 }
      },
      {
        name: SUB_NAMES[1],
        options: { ackDeadlineSeconds: 60 }
      }
    ];

    var topic;

    before(function(done) {
      // Create a new test topic.
      pubsub.createTopic(TOPIC_NAME, function(err, newTopic) {
        assert.ifError(err);
        topic = newTopic;

        // Create subscriptions.
        async.parallel(SUBSCRIPTIONS.map(function(sub) {
          return topic.subscribe.bind(topic, sub.name, sub.options);
        }), done);
      });
    });

    after(function(done) {
      var SUBS = SUB_NAMES.map(function(name) {
        return topic.subscription(name);
      });

      // Delete subscriptions
      async.each(SUBS, function(sub, callback) {
        sub.delete(callback);
      }, function(err) {
        assert.ifError(err);
        topic.delete(done);
      });
    });

    it('should list all subscriptions registered to the topic', function(done) {
      topic.getSubscriptions(function(err, subs) {
        assert.ifError(err);
        assert(subs[0] instanceof Subscription);
        assert.equal(subs.length, SUBSCRIPTIONS.length);
        done();
      });
    });

    it('should list all topic subscriptions as a stream', function(done) {
      var subscriptionsEmitted = [];

      topic.getSubscriptions()
        .on('error', done)
        .on('data', function(subscription) {
          subscriptionsEmitted.push(subscription);
        })
        .on('end', function() {
          assert.equal(subscriptionsEmitted.length, SUBSCRIPTIONS.length);
          done();
        });
    });

    it('should list all subscriptions regardless of topic', function(done) {
      pubsub.getSubscriptions(function(err, subscriptions) {
        assert.ifError(err);
        assert(subscriptions instanceof Array);
        done();
      });
    });

    it('should list all subscriptions as a stream', function(done) {
      var subscriptionEmitted = false;

      pubsub.getSubscriptions()
        .on('error', done)
        .on('data', function(subscription) {
          subscriptionEmitted = subscription instanceof Subscription;
        })
        .on('end', function() {
          assert.strictEqual(subscriptionEmitted, true);
          done();
        });
    });

    it('should allow creation and deletion of a subscription', function(done) {
      var subName = generateSubName();
      topic.subscribe(subName, function(err, sub) {
        assert.ifError(err);
        assert(sub instanceof Subscription);
        sub.delete(done);
      });
    });

    it('should error when using a non-existent subscription', function(done) {
      var subscription = topic.subscription(generateSubName());

      subscription.pull(function(err) {
        assert.equal(err.code, 404);
        done();
      });
    });

    it('should be able to pull and ack', function(done) {
      var subscription = topic.subscription(SUB_NAMES[0]);

      topic.publish({ data: 'hello' }, function(err) {
        assert.ifError(err);

        subscription.pull({
          returnImmediately: false,
          maxResults: 1
        }, function(err, msgs) {
          assert.ifError(err);
          subscription.ack(msgs[0].ackId, done);
        });
      });
    });

    it('should be able to set a new ack deadline', function(done) {
      var subscription = topic.subscription(SUB_NAMES[0]);

      topic.publish({ data: 'hello' }, function(err) {
        assert.ifError(err);

        subscription.pull({
          returnImmediately: false,
          maxResults: 1
        }, function(err, msgs) {
          assert.ifError(err);

          var options = {
            ackIds: [msgs[0].ackId],
            seconds: 10
          };
          subscription.setAckDeadline(options, done);
        });
      });
    });

    it('should receive the published message', function(done) {
      var subscription = topic.subscription(SUB_NAMES[1]);

      topic.publish([
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' }
      ], function(err) {
        assert.ifError(err);

        subscription.pull({
          returnImmediately: false,
          maxResults: 1
        }, function(err, msgs) {
          assert.ifError(err);
          assert.equal(msgs[0].data, 'hello');
          subscription.ack(msgs[0].ackId, done);
        });
      });
    });

    it('should receive a raw published message', function(done) {
      var subscription = topic.subscription(SUB_NAMES[0]);

      topic.publish([
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' }
      ], function(err) {
        assert.ifError(err);

        subscription.pull({
          returnImmediately: false,
          maxResults: 1
        }, function(err, msgs) {
          assert.ifError(err);
          assert.equal(msgs[0].data, 'hello');
          subscription.ack(msgs[0].ackId, done);
        });
      });
    });

    it('should receive the chosen amount of results', function(done) {
      var subscription = topic.subscription(SUB_NAMES[1]);
      var opts = { returnImmediately: false, maxResults: 3 };

      topic.publish([
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' },
        { data: 'hello' }
      ], function(err) {
        assert.ifError(err);

        subscription.pull(opts, function(err, messages) {
          assert.ifError(err);

          assert.equal(messages.length, opts.maxResults);

          var ackIds = messages.map(function(message) {
            return message.ackId;
          });

          subscription.ack(ackIds, done);
        });
      });
    });
  });
});
<|endoftext|>


<commit_before>/**
 * Created by ksinger on 26.11.2015.
 */

import { actionTypes } from '../actions/actions';
import { repeatVar } from '../utils';
import Immutable from 'immutable';
import { createReducer } from 'redux-immutablejs'
import { combineReducersStable } from '../redux-utils';
import { buildCreateMessage } from '../won-message-utils';

/* TODO this fragment is part of an attempt to sketch a different
 * approach to asynchronity (Remove it or the thunk-based
 * solution afterwards)
 */
const initialState = Immutable.fromJS({
    enqueued: {},
    waitingForAnswer: {},
    /**
     * TODO this field is part of the session-upgrade hack documented in:
     * https://github.com/researchstudio-sat/webofneeds/issues/381#issuecomment-172569377
     */
    resetWsRequested_Hack: false,
});
export function messagesReducer(messages = initialState, action = {}) {
    switch(action.type) {
        case actionTypes.logout:
            return initialState;
        case actionTypes.drafts.publish:
            return messages.setIn(
                ['enqueued', action.payload.eventUri],
                action.payload.message
            );

        case actionTypes.drafts.publishSuccessful:
            return messages.removeIn(['waitingForAnswer', action.payload.publishEventUri]);

        case actionTypes.messages.chatMessage.failure:
        case actionTypes.messages.chatMessage.success:
            return messages.removeIn(['waitingForAnswer', action.payload.eventUri]);

        case actionTypes.messages.waitingForAnswer:
            const pendingEventUri = action.payload.eventUri;
            const msg = messages.getIn(['enqueued', pendingEventUri]);
            return messages
                .removeIn(['enqueued', pendingEventUri])
                .setIn(['waitingForAnswer', pendingEventUri], msg);

        case actionTypes.connections.sendChatMessage:
        case actionTypes.messages.send:
            return messages.setIn(
                ['enqueued', action.payload.eventUri],
                action.payload.message
            );

        /**
         * TODO this sub-reducer is part of the session-upgrade hack documented in:
         * https://github.com/researchstudio-sat/webofneeds/issues/381#issuecomment-172569377
         */
         case actionTypes.messages.requestWsReset_Hack:
             const flag = (action.payload === undefined) ? true : action.payload;
             return messages.set('resetWsRequested_Hack', flag);

        default:
            return messages;
    }
}

<commit_msg>Setting a lostConnection flag.<commit_after>/**
 * Created by ksinger on 26.11.2015.
 */

import { actionTypes } from '../actions/actions';
import { repeatVar } from '../utils';
import Immutable from 'immutable';
import { createReducer } from 'redux-immutablejs'
import { combineReducersStable } from '../redux-utils';
import { buildCreateMessage } from '../won-message-utils';

/* TODO this fragment is part of an attempt to sketch a different
 * approach to asynchronity (Remove it or the thunk-based
 * solution afterwards)
 */
const initialState = Immutable.fromJS({
    enqueued: {},
    waitingForAnswer: {},
    /**
     * TODO this field is part of the session-upgrade hack documented in:
     * https://github.com/researchstudio-sat/webofneeds/issues/381#issuecomment-172569377
     */
    resetWsRequested_Hack: false,
});
export function messagesReducer(messages = initialState, action = {}) {
    switch(action.type) {
        case actionTypes.logout:
            return initialState;
        case actionTypes.drafts.publish:
            return messages.setIn(
                ['enqueued', action.payload.eventUri],
                action.payload.message
            );

        case actionTypes.drafts.publishSuccessful:
            return messages.removeIn(['waitingForAnswer', action.payload.publishEventUri]);

        case actionTypes.messages.chatMessage.failure:
        case actionTypes.messages.chatMessage.success:
            return messages.removeIn(['waitingForAnswer', action.payload.eventUri]);

        case actionTypes.messages.waitingForAnswer:
            const pendingEventUri = action.payload.eventUri;
            const msg = messages.getIn(['enqueued', pendingEventUri]);
            return messages
                .removeIn(['enqueued', pendingEventUri])
                .setIn(['waitingForAnswer', pendingEventUri], msg);

        case actionTypes.connections.sendChatMessage:
        case actionTypes.messages.send:
            return messages.setIn(
                ['enqueued', action.payload.eventUri],
                action.payload.message
            );

        case actionTypes.lostConnection:
            return messages.set('lostConnection', true);

        /**
         * TODO this sub-reducer is part of the session-upgrade hack documented in:
         * https://github.com/researchstudio-sat/webofneeds/issues/381#issuecomment-172569377
         */
         case actionTypes.messages.requestWsReset_Hack:
             const flag = (action.payload === undefined) ? true : action.payload;
             return messages.set('resetWsRequested_Hack', flag)
                            .set('lostConnection', false);

        default:
            return messages;
    }
}

<|endoftext|>


<commit_before>/*
 * PubSub module
 * https://github.com/softwarespot/pubsub
 * Author: softwarespot
 * Licensed under the MIT license
 * Version: 2.2.3
 */
; // jshint ignore:line
((global, name, iPubSub) => {
    // Constants

    // Create an instance of the PubSub interface
    const _pubSubInstance = new iPubSub();

    // Public API
    const _pubSubAPI = {
        // See subscribe in the documentation below
        subscribe: (subscriptions, callbacks) => {
            return _pubSubInstance.subscribe(subscriptions, callbacks);
        },

        // See unsubscribe in the documentation below
        unsubscribe: (subscriptions, callbacks) => {
            return _pubSubInstance.unsubscribe(subscriptions, callbacks);
        },

        // See publish in the documentation below
        publish: (subscriptions, ...args) => {
            return _pubSubInstance.publish(subscriptions, ...args);
        },

        // See clear in the documentation below
        clear: () => {
            return _pubSubInstance.clear();
        },

        // Expose the underlying interface to create multiple instances of the module
        getInterface: () => {
            return iPubSub;
        },

        // Get the version number of the module
        getVersion: () => {
            return _pubSubInstance.getVersion();
        }
    };

    // Define a 'constructor' function for modules to instantiate, which is a wrapper around the _pubSubAPI
    const _pubSubConstructor = function () {
        return _pubSubAPI;
    };

    // Store a 'module' reference
    const module = global.module;

    // Store a 'define' reference
    const define = global.define;

    if (typeof module !== 'undefined' && module.exports) {
        // Node.js Module
        module.exports = _pubSubConstructor;
    } else if (typeof define === 'function' && define.amd) {
        // AMD Module
        global.define(name, [], _pubSubConstructor);
    }

    // Check if PubSub has already been registered beforehand and if so, throw an error
    if (typeof global[name] !== 'undefined') {
        throw new Error('PubSub appears to be already registered on the global object, therefore the module has not be registered.');
    }

    // Append the PubSub API to the global object reference
    global[name] = _pubSubAPI;
})(window, 'PubSub', ((global) => {
    // Constants

    // Version number of the module
    const VERSION = '2.2.3';

    // Array constants enumeration
    const HANDLE_ID = 0;
    const HANDLE_SUBSCRIPTION = 1;
    const HANDLE_CALLBACK = 2;
    const HANDLE_MAX = 3;

    // Return strings of toString() found on the Object prototype
    const _objectStrings = {
        FUNCTION: '[object Function]',
        STRING: '[object String]'
    };

    // Store the Object prototype toString method
    const _objectToString = global.Object.prototype.toString;

    // Unique identifier (advanced leet speak for PubSub_Module)
    const _handleId = '|>|_|85|_|8_|\\/|0|)|_|13';

    // Generic handle for an error
    // This is an array so the reference can be used as a
    // way of verifying that it's an error
    const _handleError = [_handleId];

    // Methods

    // Check if a value is a function. Based on the idea by lodash
    function isFunction(value) {
        return isObject(value) && _objectToString.call(value) === _objectStrings.FUNCTION;
    }

    // Check if an opaque 'PubSub' handle is valid
    function isHandle(handle) {
        // The opaque 'PubSub' handle must be an array
        return global.Array.isArray(handle) &&

            // Have a length equal to that of HANDLE_MAX
            handle.length === HANDLE_MAX &&

            // Contain a handle at the 'id position'
            handle[HANDLE_ID] === _handleId &&

            // Contain a string at the 'subscription position'
            isString(handle[HANDLE_SUBSCRIPTION]) &&

            // Contain a function at the 'callback position'
            isFunction(handle[HANDLE_CALLBACK]);
    }

    // Check if a value is an object. Based on the idea by lodash
    function isObject(value) {
        // Store the typeof value
        const type = typeof value;

        // !!value is basically checking if value is not 'truthy' e.g. null or zero and then inverts that boolean value
        // So, !'Some test' is false and then inverting false is true. There if value contains 'something', continue
        return !!value && (type === 'object' || type === 'function');
    }

    // Check if a value is a string datatype with a length greater than zero when whitespace is stripped. Based partially on the idea by lodash
    function isString(value) {
        return (typeof value === 'string' || _objectToString.call(value) === _objectStrings.STRING) && value.trim().length > 0;
    }

    // Public API

    return class PubSub {
        // Constructor for the class
        constructor() {
            this._subscribers = {};
        }

        // Subscribe to a subscription with a callback function. It's best practice not to make this an anonymous function
        // as you then can't unsubscribe, since the callback function reference is required
        // Returns an opaque handle for use with unsubscribe() (though it's optional to use of course)
        subscribe(subscriptions, callbacks) {
            // Store as to whether or not  the first parameter is a string
            const isStringTypes = isString(subscriptions) && isFunction(callbacks);

            // If a string and a function datatype, then create an array for each parameter
            if (isStringTypes) {
                callbacks = [callbacks];
                subscriptions = [subscriptions];
            }

            // If either of the arguments are not an array or the lengths mismatch, then return a handle error
            if (!global.Array.isArray(subscriptions) ||
                !global.Array.isArray(callbacks) ||
                subscriptions.length !== callbacks.length) {
                return _handleError;
            }

            // Return an array of opaque 'PubSub' handles i.e. [handle id, subscription, callback]
            const handles = [];

            // Iterate through all the subscriptions
            for (let i = 0, length = subscriptions.length; i < length; i++) {
                // Store the subscription
                const subscription = subscriptions[i];

                // The subscription should be a string datatype with a length greater than zero
                if (!isString(subscription)) {
                    continue;
                }

                // Store the callback
                const callback = callbacks[i];

                // The callback should be a function datatype
                if (!isFunction(callback)) {
                    continue;
                }

                // If an array for the event name doesn't exist, then generate a new empty array
                // This cannot be done on the function datatype for obvious reasons (it's an array)
                if (!this._subscribers.hasOwnProperty(subscription)) {
                    this._subscribers[subscription] = [];
                }

                // Retrieve the callbacks for the subscription
                const functions = this._subscribers[subscription];

                // Check if the callback hasn't already been registered for the event name
                // Could use include() when ES2015 is widely available
                if (functions.indexOf(callback) === -1) {
                    // Push the callback function to the event name array
                    functions.push(callback);

                    // An opaque 'PubSub' handle
                    handles.push([_handleId, subscription, callback]);
                }
            }

            // If an error occurred as no opaque 'PubSub' handles were pushed to the handles array
            if (handles.length === 0) {
                return isStringTypes ? _handleError : [_handleError];
            }

            // If a string was passed as the first parameter, then return a single handle instead of an array of handles
            return isStringTypes ? handles[0] : handles;
        }

        // Unsubscribe from a subscription. A string and callback function reference are expected OR
        // the handle returned from subscribe()
        // Returns true or false
        unsubscribe(subscriptions, callbacks) {
            // If the reference is equal to the handle error array, then an error occurred with previously subscribing
            if (subscriptions === _handleError) {
                return false;
            }

            // Set the following variable(s), if it's an opaque 'PubSub' handle returned from subscribe()
            if (isHandle(subscriptions)) {
                // Do not swap these around, otherwise it will cause an error with overwriting subscriptions before
                // setting the callbacks variable
                callbacks = [subscriptions[HANDLE_CALLBACK]];
                subscriptions = [subscriptions[HANDLE_SUBSCRIPTION]];
                // If a string and function datatype, then create an array for each variable
            } else if (isString(subscriptions) && isFunction(callbacks)) {
                callbacks = [callbacks];
                subscriptions = [subscriptions];
            }

            // If either of the arguments are not an array or the lengths simply mismatch, then return false
            if (!global.Array.isArray(subscriptions) || !global.Array.isArray(callbacks) || subscriptions.length !== callbacks.length) {
                return false;
            }

            // Iterate through all the subscriptions
            for (let i = 0, length = subscriptions.length; i < length; i++) {
                // The subscription hasn't been created as of yet
                if (!this._subscribers.hasOwnProperty(subscriptions[i])) {
                    continue;
                }

                // Retrieve the callback functions for the subscription
                const functions = this._subscribers[subscriptions[i]];

                // There are no callback functions assigned to the subscription
                if (!functions.length) {
                    continue;
                }

                // If a callback function reference exists for the subscription,
                // then remove from the array using the index value
                const index = functions.indexOf(callbacks[i]);
                if (index !== -1) {
                    functions.splice(index, 1);
                }
            }

            return true;
        }

        // Publish a subscription to all subscribers with an unlimited number of arguments. The subscription is the last argument
        // i.e. arguments[arguments.length]
        // Returns number of subscriptions published
        publish(subscriptions, ...args) {
            // Set the following variable(s), if it's an opaque 'PubSub' handle returned from subscribe()
            if (isHandle(subscriptions)) {
                // Convert to an array datatype
                subscriptions = [subscriptions[HANDLE_SUBSCRIPTION]];
                // If a string has been passed, then convert to an array datatype
            } else if (isString(subscriptions)) {
                subscriptions = [subscriptions];
            }

            // If not an array, then the subscription was an invalid array, handle or string
            if (!global.Array.isArray(subscriptions)) {
                return 0;
            }

            // Push the subscription to the end of the arguments array as a comma separated string,
            // just in case it's required. Of course this will kind of fail if the user uses a subscription with a comma,
            // but that's up to them I guess!
            args.push(subscriptions.join(','));

            // Store the number of subscriptions published
            let published = 0;

            // Iterate through all the subscriptions
            for (let i = 0, length = subscriptions.length; i < length; i++) {
                // The subscription hasn't been created as of yet
                if (!this._subscribers.hasOwnProperty(subscriptions[i])) {
                    continue;
                }

                // Retrieve the callback functions for the subscription
                const functions = this._subscribers[subscriptions[i]];

                // There are no callback functions assigned to the subscription
                if (!functions.length) {
                    continue;
                }

                // Iterate through all the functions for the particular subscription
                for (let j = 0, functionsLength = functions.length; j < functionsLength; j++) {
                    // Call the function with the arguments array using the spread operator
                    functions[j](...args);

                    // Increase the number of published subscriptions
                    published++;
                }
            }

            // Return the number of subscribers published to
            return published;
        }

        // Clear the internal subscribers store
        clear() {
            this._subscribers = {};
        }

        // Get the version number of the module
        getVersion() {
            return VERSION;
        }
    };
})(window));

//
// PubSub pattern in JavaScript
//      By LearnCodeAcademy, URL: https://gist.github.com/learncodeacademy/777349747d8382bfb722
//
// Additional info:
//      Tuts+, URL: https://www.youtube.com/watch?v=U4cigUpzW2U&list=PL15G0RGjxzGdBqDPF4DDrlOt9YmjampzO&index=8
//      Peter Higgins, URL: https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js
//      PubSubJS, handle/token concept, URL: https://github.com/mroderick/PubSubJS/blob/master/src/pubsub.js
//      PubSub, subscription array concept, URL: https://github.com/drublic/PubSub/
//      PubSub Wikipedia, URL: https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern
//
// Performance tests:
//      forEach-vs-for-loop: http://jsperf.com/array-foreach-vs-for-loop/5
//      for-loop-vs-indexOf: http://jsperf.com/js-for-loop-vs-array-indexof/8
//      shift-vs-splice: http://jsperf.com/shift-vs-splice
//
<commit_msg>Used undefined instead of typeof<commit_after>/*
 * PubSub module
 * https://github.com/softwarespot/pubsub
 * Author: softwarespot
 * Licensed under the MIT license
 * Version: 2.2.3
 */
; // jshint ignore:line
((global, name, iPubSub, undefined) => {
    // Constants

    // Create an instance of the PubSub interface
    const _pubSubInstance = new iPubSub();

    // Public API
    const _pubSubAPI = {
        // See subscribe in the documentation below
        subscribe: (subscriptions, callbacks) => {
            return _pubSubInstance.subscribe(subscriptions, callbacks);
        },

        // See unsubscribe in the documentation below
        unsubscribe: (subscriptions, callbacks) => {
            return _pubSubInstance.unsubscribe(subscriptions, callbacks);
        },

        // See publish in the documentation below
        publish: (subscriptions, ...args) => {
            return _pubSubInstance.publish(subscriptions, ...args);
        },

        // See clear in the documentation below
        clear: () => {
            return _pubSubInstance.clear();
        },

        // Expose the underlying interface to create multiple instances of the module
        getInterface: () => {
            return iPubSub;
        },

        // Get the version number of the module
        getVersion: () => {
            return _pubSubInstance.getVersion();
        }
    };

    // Define a 'constructor' function for modules to instantiate, which is a wrapper around the _pubSubAPI
    const _pubSubConstructor = function () {
        return _pubSubAPI;
    };

    // Store a 'module' reference
    const module = global.module;

    // Store a 'define' reference
    const define = global.define;

    if (module !== undefined && module.exports) {
        // Node.js Module
        module.exports = _pubSubConstructor;
    } else if (typeof define === 'function' && define.amd) {
        // AMD Module
        global.define(name, [], _pubSubConstructor);
    }

    // Check if PubSub has already been registered beforehand and if so, throw an error
    if (global[name] !== undefined) {
        throw new Error('PubSub appears to be already registered on the global object, therefore the module has not be registered.');
    }

    // Append the PubSub API to the global object reference
    global[name] = _pubSubAPI;
})(window, 'PubSub', ((global) => {
    // Constants

    // Version number of the module
    const VERSION = '2.2.3';

    // Array constants enumeration
    const HANDLE_ID = 0;
    const HANDLE_SUBSCRIPTION = 1;
    const HANDLE_CALLBACK = 2;
    const HANDLE_MAX = 3;

    // Return strings of toString() found on the Object prototype
    const _objectStrings = {
        FUNCTION: '[object Function]',
        STRING: '[object String]'
    };

    // Store the Object prototype toString method
    const _objectToString = global.Object.prototype.toString;

    // Unique identifier (advanced leet speak for PubSub_Module)
    const _handleId = '|>|_|85|_|8_|\\/|0|)|_|13';

    // Generic handle for an error
    // This is an array so the reference can be used as a
    // way of verifying that it's an error
    const _handleError = [_handleId];

    // Methods

    // Check if a value is a function. Based on the idea by lodash
    function isFunction(value) {
        return isObject(value) && _objectToString.call(value) === _objectStrings.FUNCTION;
    }

    // Check if an opaque 'PubSub' handle is valid
    function isHandle(handle) {
        // The opaque 'PubSub' handle must be an array
        return global.Array.isArray(handle) &&

            // Have a length equal to that of HANDLE_MAX
            handle.length === HANDLE_MAX &&

            // Contain a handle at the 'id position'
            handle[HANDLE_ID] === _handleId &&

            // Contain a string at the 'subscription position'
            isString(handle[HANDLE_SUBSCRIPTION]) &&

            // Contain a function at the 'callback position'
            isFunction(handle[HANDLE_CALLBACK]);
    }

    // Check if a value is an object. Based on the idea by lodash
    function isObject(value) {
        // Store the typeof value
        const type = typeof value;

        // !!value is basically checking if value is not 'truthy' e.g. null or zero and then inverts that boolean value
        // So, !'Some test' is false and then inverting false is true. There if value contains 'something', continue
        return !!value && (type === 'object' || type === 'function');
    }

    // Check if a value is a string datatype with a length greater than zero when whitespace is stripped. Based partially on the idea by lodash
    function isString(value) {
        return (typeof value === 'string' || _objectToString.call(value) === _objectStrings.STRING) && value.trim().length > 0;
    }

    // Public API

    return class PubSub {
        // Constructor for the class
        constructor() {
            this._subscribers = {};
        }

        // Subscribe to a subscription with a callback function. It's best practice not to make this an anonymous function
        // as you then can't unsubscribe, since the callback function reference is required
        // Returns an opaque handle for use with unsubscribe() (though it's optional to use of course)
        subscribe(subscriptions, callbacks) {
            // Store as to whether or not  the first parameter is a string
            const isStringTypes = isString(subscriptions) && isFunction(callbacks);

            // If a string and a function datatype, then create an array for each parameter
            if (isStringTypes) {
                callbacks = [callbacks];
                subscriptions = [subscriptions];
            }

            // If either of the arguments are not an array or the lengths mismatch, then return a handle error
            if (!global.Array.isArray(subscriptions) ||
                !global.Array.isArray(callbacks) ||
                subscriptions.length !== callbacks.length) {
                return _handleError;
            }

            // Return an array of opaque 'PubSub' handles i.e. [handle id, subscription, callback]
            const handles = [];

            // Iterate through all the subscriptions
            for (let i = 0, length = subscriptions.length; i < length; i++) {
                // Store the subscription
                const subscription = subscriptions[i];

                // The subscription should be a string datatype with a length greater than zero
                if (!isString(subscription)) {
                    continue;
                }

                // Store the callback
                const callback = callbacks[i];

                // The callback should be a function datatype
                if (!isFunction(callback)) {
                    continue;
                }

                // If an array for the event name doesn't exist, then generate a new empty array
                // This cannot be done on the function datatype for obvious reasons (it's an array)
                if (!this._subscribers.hasOwnProperty(subscription)) {
                    this._subscribers[subscription] = [];
                }

                // Retrieve the callbacks for the subscription
                const functions = this._subscribers[subscription];

                // Check if the callback hasn't already been registered for the event name
                // Could use include() when ES2015 is widely available
                if (functions.indexOf(callback) === -1) {
                    // Push the callback function to the event name array
                    functions.push(callback);

                    // An opaque 'PubSub' handle
                    handles.push([_handleId, subscription, callback]);
                }
            }

            // If an error occurred as no opaque 'PubSub' handles were pushed to the handles array
            if (handles.length === 0) {
                return isStringTypes ? _handleError : [_handleError];
            }

            // If a string was passed as the first parameter, then return a single handle instead of an array of handles
            return isStringTypes ? handles[0] : handles;
        }

        // Unsubscribe from a subscription. A string and callback function reference are expected OR
        // the handle returned from subscribe()
        // Returns true or false
        unsubscribe(subscriptions, callbacks) {
            // If the reference is equal to the handle error array, then an error occurred with previously subscribing
            if (subscriptions === _handleError) {
                return false;
            }

            // Set the following variable(s), if it's an opaque 'PubSub' handle returned from subscribe()
            if (isHandle(subscriptions)) {
                // Do not swap these around, otherwise it will cause an error with overwriting subscriptions before
                // setting the callbacks variable
                callbacks = [subscriptions[HANDLE_CALLBACK]];
                subscriptions = [subscriptions[HANDLE_SUBSCRIPTION]];
                // If a string and function datatype, then create an array for each variable
            } else if (isString(subscriptions) && isFunction(callbacks)) {
                callbacks = [callbacks];
                subscriptions = [subscriptions];
            }

            // If either of the arguments are not an array or the lengths simply mismatch, then return false
            if (!global.Array.isArray(subscriptions) || !global.Array.isArray(callbacks) || subscriptions.length !== callbacks.length) {
                return false;
            }

            // Iterate through all the subscriptions
            for (let i = 0, length = subscriptions.length; i < length; i++) {
                // The subscription hasn't been created as of yet
                if (!this._subscribers.hasOwnProperty(subscriptions[i])) {
                    continue;
                }

                // Retrieve the callback functions for the subscription
                const functions = this._subscribers[subscriptions[i]];

                // There are no callback functions assigned to the subscription
                if (!functions.length) {
                    continue;
                }

                // If a callback function reference exists for the subscription,
                // then remove from the array using the index value
                const index = functions.indexOf(callbacks[i]);
                if (index !== -1) {
                    functions.splice(index, 1);
                }
            }

            return true;
        }

        // Publish a subscription to all subscribers with an unlimited number of arguments. The subscription is the last argument
        // i.e. arguments[arguments.length]
        // Returns number of subscriptions published
        publish(subscriptions, ...args) {
            // Set the following variable(s), if it's an opaque 'PubSub' handle returned from subscribe()
            if (isHandle(subscriptions)) {
                // Convert to an array datatype
                subscriptions = [subscriptions[HANDLE_SUBSCRIPTION]];
                // If a string has been passed, then convert to an array datatype
            } else if (isString(subscriptions)) {
                subscriptions = [subscriptions];
            }

            // If not an array, then the subscription was an invalid array, handle or string
            if (!global.Array.isArray(subscriptions)) {
                return 0;
            }

            // Push the subscription to the end of the arguments array as a comma separated string,
            // just in case it's required. Of course this will kind of fail if the user uses a subscription with a comma,
            // but that's up to them I guess!
            args.push(subscriptions.join(','));

            // Store the number of subscriptions published
            let published = 0;

            // Iterate through all the subscriptions
            for (let i = 0, length = subscriptions.length; i < length; i++) {
                // The subscription hasn't been created as of yet
                if (!this._subscribers.hasOwnProperty(subscriptions[i])) {
                    continue;
                }

                // Retrieve the callback functions for the subscription
                const functions = this._subscribers[subscriptions[i]];

                // There are no callback functions assigned to the subscription
                if (!functions.length) {
                    continue;
                }

                // Iterate through all the functions for the particular subscription
                for (let j = 0, functionsLength = functions.length; j < functionsLength; j++) {
                    // Call the function with the arguments array using the spread operator
                    functions[j](...args);

                    // Increase the number of published subscriptions
                    published++;
                }
            }

            // Return the number of subscribers published to
            return published;
        }

        // Clear the internal subscribers store
        clear() {
            this._subscribers = {};
        }

        // Get the version number of the module
        getVersion() {
            return VERSION;
        }
    };
})(window));

//
// PubSub pattern in JavaScript
//      By LearnCodeAcademy, URL: https://gist.github.com/learncodeacademy/777349747d8382bfb722
//
// Additional info:
//      Tuts+, URL: https://www.youtube.com/watch?v=U4cigUpzW2U&list=PL15G0RGjxzGdBqDPF4DDrlOt9YmjampzO&index=8
//      Peter Higgins, URL: https://github.com/phiggins42/bloody-jquery-plugins/blob/master/pubsub.js
//      PubSubJS, handle/token concept, URL: https://github.com/mroderick/PubSubJS/blob/master/src/pubsub.js
//      PubSub, subscription array concept, URL: https://github.com/drublic/PubSub/
//      PubSub Wikipedia, URL: https://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern
//
// Performance tests:
//      forEach-vs-for-loop: http://jsperf.com/array-foreach-vs-for-loop/5
//      for-loop-vs-indexOf: http://jsperf.com/js-for-loop-vs-array-indexof/8
//      shift-vs-splice: http://jsperf.com/shift-vs-splice
//
<|endoftext|>


<commit_before>window.$$=function getElementById(i){
	return document.getElementById(i.substring(1));
};

!(function (window, undefined) {
	var html={
		"console":$$("#console")
	};
	function exec(latex){
		//Convert to javascript:
		return M(M.latex.parse(latex)).eval();
	}
	var console = {
		"current":undefined,
		"write" :function(data, className){
			var elem = document.createElement("li");
			elem.className=className;
			elem.appendChild(typeof data === "string" ? document.createTextNode(data) : data);
			html.console.appendChild(elem);
			return elem;
		},
		"warn" :function(data){
			return this.warn(data, "warn");
		},
		"error" :function(data){
			return this.warn(data, "error");
		},
		"response" :function(data){
			return this.warn(data, "response");
		},
		"execute":function(d){
			if(this.current){
				window.d=d;
				var result=document.createElement("div");
				result.className="result";
				var res = exec(d);
				result.appendChild(document.createTextNode(res));
				this.current.appendChild(result);
			}
			var mathQuill=document.createElement("div");
			var current = this.current = this.write(mathQuill, "write user");
			setTimeout(function(){current.style.opacity=1.0;},1);
			mathQuill.appendChild(document.createTextNode(""));

			var self=this;
			$(mathQuill)
				.mathquill("editable")
				//.trigger({ type: "keydown", ctrlKey: true, which: 65 })
				.focus()
				.bind("keydown.jscas", function(event) {
						if(event.which == 13) {
							var jQueryDataKey = '[[mathquill internal data]]';
							var latex =
							$(this)
								.unbind('.mathquill')
								.unbind('.jscas')
							 	.removeClass('mathquill-editable mathquill-textbox')
								.find("textarea")
									.remove()
								.end()
								.mathquill("latex");
							$(current).unbind(".jscas");
							self.execute(latex);
						}
					}

				);
				$(current).bind("click.jscas",function() {
					$(mathQuill).focus();
				});

		}
	};
	console.log=console.write;
	html.console.innerHTML="";
	console.execute();
})(window);<commit_msg>remove sample logs<commit_after>window.$$=function getElementById(i){
	return document.getElementById(i.substring(1));
};

!(function (window, undefined) {
	var html={
		"console":$$("#console")
	};
	function exec(latex){
		//Convert to javascript:
		return M(M.latex.parse(latex)).eval();
	}
	var console = {
		"current":undefined,
		"write" :function(data, className){
			var elem = document.createElement("li");
			elem.className=className;
			elem.appendChild(typeof data === "string" ? document.createTextNode(data) : data);
			html.console.appendChild(elem);
			return elem;
		},
		"warn" :function(data){
			return this.warn(data, "warn");
		},
		"error" :function(data){
			return this.warn(data, "error");
		},
		"response" :function(data){
			return this.warn(data, "response");
		},
		"execute":function(d){
			if(this.current){
				window.d=d;
				var result=document.createElement("div");
				result.className="result";
				var res = exec(d);
				result.appendChild(document.createTextNode(res));
				this.current.appendChild(result);
			}
			var mathQuill=document.createElement("div");
			var current = this.current = this.write(mathQuill, "write user");
			setTimeout(function(){current.style.opacity=1.0;},1);
			mathQuill.appendChild(document.createTextNode(""));

			var self=this;
			$(mathQuill)
				.mathquill("editable")
				//.trigger({ type: "keydown", ctrlKey: true, which: 65 })
				.focus()
				.bind("keydown.jscas", function(event) {
						if(event.which == 13) {
							var jQueryDataKey = '[[mathquill internal data]]';
							var latex =
							$(this)
								.unbind('.mathquill')
								.unbind('.jscas')
							 	.removeClass('mathquill-editable mathquill-textbox')
								.find("textarea")
									.remove()
								.end()
								.mathquill("latex");
							$(current).unbind(".jscas");
							self.execute(latex);
						}
					}

				);
				$(current).bind("click.jscas",function() {
					$(mathQuill).focus();
				});

		}
	};
	console.log=console.write;
	console.execute();
})(window);<|endoftext|>


<commit_before>const isGlobalProperty = require('./utilities/isGlobalProperty')

const LOGICAL_OPERATORS = ['&&', '||']

function isLogicalOperator (operator) {
  return LOGICAL_OPERATORS.includes(operator)
}

function getGlobalProperty (name) {
  switch (name) {
    case 'Infinity': return Infinity
    case 'NaN': return NaN
    case 'undefined': return undefined
    case 'null': return null
  }
}

function getNodeValue (node) {
  return isGlobalProperty(node) ? getGlobalProperty(node.name) : node.value
}

function identifier (name) {
  return { type: 'Identifier', name }
}

function literal (value) {
  return { type: 'Literal', value }
}

function serialize (value) {
  switch (value) {
    case Infinity: return identifier('Infinity')
    case NaN: return identifier('NaN')
    case undefined: return identifier('undefined')
    case null: return identifier('null')
    default: return literal(value)
  }
}

function evaluate (operator, left, right) {
  switch (operator) {
    case '&&': return serialize(left && right)
    case '||': return serialize(left || right)
  }
}

function isNodeSupported (node) {
  return node.type === 'Literal' || isGlobalProperty(node)
}

module.exports = function logicalExpressionReduction (node) {
  if (node.type === 'LogicalExpression' &&
    isNodeSupported(node.left) &&
    isNodeSupported(node.right) &&
    isLogicalOperator(node.operator)) {
    return evaluate(node.operator, getNodeValue(node.left), getNodeValue(node.right))
  }
  return node
}
<commit_msg>src: add nullish coalencing operator<commit_after>const isGlobalProperty = require('./utilities/isGlobalProperty')

const LOGICAL_OPERATORS = ['&&', '||']

if (Number(process.version.split('.')[0].slice(1)) >= 14)
  LOGICAL_OPERATORS.push('??')

function isLogicalOperator (operator) {
  return LOGICAL_OPERATORS.includes(operator)
}

function getGlobalProperty (name) {
  switch (name) {
    case 'Infinity': return Infinity
    case 'NaN': return NaN
    case 'undefined': return undefined
    case 'null': return null
  }
}

function getNodeValue (node) {
  return isGlobalProperty(node) ? getGlobalProperty(node.name) : node.value
}

function identifier (name) {
  return { type: 'Identifier', name }
}

function literal (value) {
  return { type: 'Literal', value }
}

function serialize (value) {
  switch (value) {
    case Infinity: return identifier('Infinity')
    case NaN: return identifier('NaN')
    case undefined: return identifier('undefined')
    case null: return identifier('null')
    default: return literal(value)
  }
}

function evaluate (operator, left, right) {
  switch (operator) {
    case '&&': return serialize(left && right)
    case '||': return serialize(left || right)
    case '??': return eval('serialize(left ?? right)')
  }
}

function isNodeSupported (node) {
  return node.type === 'Literal' || isGlobalProperty(node)
}

module.exports = function logicalExpressionReduction (node) {
  if (node.type === 'LogicalExpression' &&
    isNodeSupported(node.left) &&
    isNodeSupported(node.right) &&
    isLogicalOperator(node.operator)) {
    return evaluate(node.operator, getNodeValue(node.left), getNodeValue(node.right))
  }
  return node
}
<|endoftext|>


<commit_before>
const RGB_MAX = 255
const HUE_MAX = 360
const SV_MAX = 100

var colorsys = module.exports = {}

colorsys.rgb2Hsl = function (r, g, b) {
  if (typeof r === 'object') {
    const args = r
    r = args.r; g = args.g; b = args.b;
  }
  // It converts [0,255] format, to [0,1]
  r = (r === RGB_MAX) ? 1 : (r % RGB_MAX / parseFloat(RGB_MAX))
  g = (g === RGB_MAX) ? 1 : (g % RGB_MAX / parseFloat(RGB_MAX))
  b = (b === RGB_MAX) ? 1 : (b % RGB_MAX / parseFloat(RGB_MAX))

  var max = Math.max(r, g, b)
  var min = Math.min(r, g, b)
  var h
  var s
  var l = (max + min) / 2

  if (max === min) {
    h = s = 0 // achromatic
  } else {
    var d = max - min
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
    switch (max) {
      case r:
        h = (g - b) / d + (g < b ? 6 : 0)
        break
      case g:
        h = (b - r) / d + 2
        break
      case b:
        h = (r - g) / d + 4
        break
    }
    h /= 6
  }

  return [{
    h: Math.floor(h * HUE_MAX),
    s: Math.floor(s * SV_MAX),
    l: Math.floor(l * SV_MAX)
  }]
}

colorsys.rgb_to_hsl = colorsys.rgb2Hsl
colorsys.rgbToHsl = colorsys.rgb2Hsl

colorsys.rgb2Hsv = function (r, g, b) {
  if (typeof r === 'object') {
    const args = r
    r = args.r; g = args.g; b = args.b;
  }

  // It converts [0,255] format, to [0,1]
  r = (r === RGB_MAX) ? 1 : (r % RGB_MAX / parseFloat(RGB_MAX))
  g = (g === RGB_MAX) ? 1 : (g % RGB_MAX / parseFloat(RGB_MAX))
  b = (b === RGB_MAX) ? 1 : (b % RGB_MAX / parseFloat(RGB_MAX))

  var max = Math.max(r, g, b)
  var min = Math.min(r, g, b)
  var h
  var s
  var v = max

  var d = max - min

  s = max === 0 ? 0 : d / max

  if (max === min) {
    h = 0 // achromatic
  } else {
    switch (max) {
      case r:
        h = (g - b) / d + (g < b ? 6 : 0)
        break
      case g:
        h = (b - r) / d + 2
        break
      case b:
        h = (r - g) / d + 4
        break
    }
    h /= 6
  }

  return [{
    h: Math.floor(h * HUE_MAX),
    s: Math.floor(s * SV_MAX),
    v: Math.floor(v * SV_MAX)
  }]
}

colorsys.rgb_to_hsv = colorsys.rgb2Hsv
colorsys.rgbToHsv = colorsys.rgb2Hsv

colorsys.hsl2Rgb = function (h, s, l) {
  if (typeof h === 'object') {
    const args = h
    h = args.h; s = args.s; l = args.l;
  }

  var r, g, b

  h = (h === HUE_MAX) ? 1 : (h % HUE_MAX / parseFloat(HUE_MAX))
  s = (s === SV_MAX) ? 1 : (s % SV_MAX / parseFloat(SV_MAX))
  l = (l === SV_MAX) ? 1 : (l % SV_MAX / parseFloat(SV_MAX))

  if (s === 0) {
    r = g = b = l // achromatic
  } else {
    var hue2rgb = function hue2rgb (p, q, t) {
      if (t < 0) t += 1
      if (t > 1) t -= 1
      if (t < 1 / 6) return p + (q - p) * 6 * t
      if (t < 1 / 2) return q
      if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
      return p
    }

    var q = l < 0.5 ? l * (1 + s) : l + s - l * s
    var p = 2 * l - q
    r = hue2rgb(p, q, h + 1 / 3)
    g = hue2rgb(p, q, h)
    b = hue2rgb(p, q, h - 1 / 3)
  }
  return { r: Math.round(r * RGB_MAX), g: Math.round(g * RGB_MAX), b: Math.round(b * RGB_MAX) }
}

colorsys.hsl_to_rgb = colorsys.hsl2Rgb
colorsys.hslToRgb = colorsys.hsl2Rgb

colorsys.hsv2Rgb = function (h, s, v) {
  if (typeof h === 'object') {
    const args = r
    h = args.h; s = args.s; v = args.v;
  }

  h = (h === HUE_MAX) ? 1 : (h % HUE_MAX / parseFloat(HUE_MAX) * 6)
  s = (s === SV_MAX) ? 1 : (s % SV_MAX / parseFloat(SV_MAX))
  v = (v === SV_MAX) ? 1 : (v % SV_MAX / parseFloat(SV_MAX))

  var i = Math.floor(h)
  var f = h - i
  var p = v * (1 - s)
  var q = v * (1 - f * s)
  var t = v * (1 - (1 - f) * s)
  var mod = i % 6
  var r = [v, q, p, p, t, v][mod]
  var g = [t, v, v, q, p, p][mod]
  var b = [p, p, t, v, v, q][mod]

  return { r: Math.round(r * RGB_MAX), g: Math.round(g * RGB_MAX), b: Math.round(b * RGB_MAX) }
}

colorsys.hsv_to_rgb = colorsys.hsv2Rgb
colorsys.hsvToRgb = colorsys.hsv2Rgb

colorsys.rgb2Hex = function (r, g, b) {
  if (typeof r === 'object') {
    const args = r
    r = args.r; g = args.g; b = args.b;
  }
  r = Math.round(r).toString(16)
  g = Math.round(g).toString(16)
  b = Math.round(b).toString(16)

  r = r.length === 1 ? '0' + r : r
  g = g.length === 1 ? '0' + g : g
  b = b.length === 1 ? '0' + b : b

  return '#' + r + g + b
}

colorsys.rgb_to_hex = colorsys.rgb2Hex
colorsys.rgbToHex = colorsys.rgb2Hex

colorsys.hex2Rgb = function (hex) {
  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null
}

colorsys.hex_to_rgb = colorsys.hex2Rgb
colorsys.hexToRgb = colorsys.hex2Rgb

colorsys.hsv2Hex = function (h, s, v) {
  var rgb = colorsys.hsv2Rgb(h, s, v)
  return colorsys.rgb2Hex(rgb.r, rgb.g, rgb.b)
}

colorsys.hsv_to_hex = colorsys.hsv2Hex
colorsys.hsvToHex = colorsys.hsv2Hex

colorsys.hex2Hsv = function (hex) {
  var rgb = colorsys.hex2Rgb(hex)
  return colorsys.rgb2Hsv(rgb.r, rgb.g, rgb.b)[0]
}

colorsys.hex_to_hsv = colorsys.hex2Hsv
colorsys.hexToHsv = colorsys.hex2Hsv

colorsys.hsl2Hex = function (h, s, l) {
  var rgb = colorsys.hsl2Rgb(h, s, l)
  return colorsys.rgb2Hex(rgb.r, rgb.g, rgb.b)
}

colorsys.hsl_to_hex = colorsys.hsl2Hex
colorsys.hslToHex = colorsys.hsl2Hex

colorsys.hex2Hsl = function (hex) {
  var rgb = colorsys.hex2Rgb(hex)
  return colorsys.rgb2Hsl(rgb.r, rgb.g, rgb.b)[0]
}

colorsys.hex_to_hsl = colorsys.hex2Hsl
colorsys.hexToHsl = colorsys.hex2Hsl
<commit_msg>Fix hsv2Rgb when object is passed in<commit_after>
const RGB_MAX = 255
const HUE_MAX = 360
const SV_MAX = 100

var colorsys = module.exports = {}

colorsys.rgb2Hsl = function (r, g, b) {
  if (typeof r === 'object') {
    const args = r
    r = args.r; g = args.g; b = args.b;
  }
  // It converts [0,255] format, to [0,1]
  r = (r === RGB_MAX) ? 1 : (r % RGB_MAX / parseFloat(RGB_MAX))
  g = (g === RGB_MAX) ? 1 : (g % RGB_MAX / parseFloat(RGB_MAX))
  b = (b === RGB_MAX) ? 1 : (b % RGB_MAX / parseFloat(RGB_MAX))

  var max = Math.max(r, g, b)
  var min = Math.min(r, g, b)
  var h
  var s
  var l = (max + min) / 2

  if (max === min) {
    h = s = 0 // achromatic
  } else {
    var d = max - min
    s = l > 0.5 ? d / (2 - max - min) : d / (max + min)
    switch (max) {
      case r:
        h = (g - b) / d + (g < b ? 6 : 0)
        break
      case g:
        h = (b - r) / d + 2
        break
      case b:
        h = (r - g) / d + 4
        break
    }
    h /= 6
  }

  return [{
    h: Math.floor(h * HUE_MAX),
    s: Math.floor(s * SV_MAX),
    l: Math.floor(l * SV_MAX)
  }]
}

colorsys.rgb_to_hsl = colorsys.rgb2Hsl
colorsys.rgbToHsl = colorsys.rgb2Hsl

colorsys.rgb2Hsv = function (r, g, b) {
  if (typeof r === 'object') {
    const args = r
    r = args.r; g = args.g; b = args.b;
  }

  // It converts [0,255] format, to [0,1]
  r = (r === RGB_MAX) ? 1 : (r % RGB_MAX / parseFloat(RGB_MAX))
  g = (g === RGB_MAX) ? 1 : (g % RGB_MAX / parseFloat(RGB_MAX))
  b = (b === RGB_MAX) ? 1 : (b % RGB_MAX / parseFloat(RGB_MAX))

  var max = Math.max(r, g, b)
  var min = Math.min(r, g, b)
  var h
  var s
  var v = max

  var d = max - min

  s = max === 0 ? 0 : d / max

  if (max === min) {
    h = 0 // achromatic
  } else {
    switch (max) {
      case r:
        h = (g - b) / d + (g < b ? 6 : 0)
        break
      case g:
        h = (b - r) / d + 2
        break
      case b:
        h = (r - g) / d + 4
        break
    }
    h /= 6
  }

  return [{
    h: Math.floor(h * HUE_MAX),
    s: Math.floor(s * SV_MAX),
    v: Math.floor(v * SV_MAX)
  }]
}

colorsys.rgb_to_hsv = colorsys.rgb2Hsv
colorsys.rgbToHsv = colorsys.rgb2Hsv

colorsys.hsl2Rgb = function (h, s, l) {
  if (typeof h === 'object') {
    const args = h
    h = args.h; s = args.s; l = args.l;
  }

  var r, g, b

  h = (h === HUE_MAX) ? 1 : (h % HUE_MAX / parseFloat(HUE_MAX))
  s = (s === SV_MAX) ? 1 : (s % SV_MAX / parseFloat(SV_MAX))
  l = (l === SV_MAX) ? 1 : (l % SV_MAX / parseFloat(SV_MAX))

  if (s === 0) {
    r = g = b = l // achromatic
  } else {
    var hue2rgb = function hue2rgb (p, q, t) {
      if (t < 0) t += 1
      if (t > 1) t -= 1
      if (t < 1 / 6) return p + (q - p) * 6 * t
      if (t < 1 / 2) return q
      if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6
      return p
    }

    var q = l < 0.5 ? l * (1 + s) : l + s - l * s
    var p = 2 * l - q
    r = hue2rgb(p, q, h + 1 / 3)
    g = hue2rgb(p, q, h)
    b = hue2rgb(p, q, h - 1 / 3)
  }
  return { r: Math.round(r * RGB_MAX), g: Math.round(g * RGB_MAX), b: Math.round(b * RGB_MAX) }
}

colorsys.hsl_to_rgb = colorsys.hsl2Rgb
colorsys.hslToRgb = colorsys.hsl2Rgb

colorsys.hsv2Rgb = function (h, s, v) {
  if (typeof h === 'object') {
    const args = h
    h = args.h; s = args.s; v = args.v;
  }

  h = (h === HUE_MAX) ? 1 : (h % HUE_MAX / parseFloat(HUE_MAX) * 6)
  s = (s === SV_MAX) ? 1 : (s % SV_MAX / parseFloat(SV_MAX))
  v = (v === SV_MAX) ? 1 : (v % SV_MAX / parseFloat(SV_MAX))

  var i = Math.floor(h)
  var f = h - i
  var p = v * (1 - s)
  var q = v * (1 - f * s)
  var t = v * (1 - (1 - f) * s)
  var mod = i % 6
  var r = [v, q, p, p, t, v][mod]
  var g = [t, v, v, q, p, p][mod]
  var b = [p, p, t, v, v, q][mod]

  return { r: Math.round(r * RGB_MAX), g: Math.round(g * RGB_MAX), b: Math.round(b * RGB_MAX) }
}

colorsys.hsv_to_rgb = colorsys.hsv2Rgb
colorsys.hsvToRgb = colorsys.hsv2Rgb

colorsys.rgb2Hex = function (r, g, b) {
  if (typeof r === 'object') {
    const args = r
    r = args.r; g = args.g; b = args.b;
  }
  r = Math.round(r).toString(16)
  g = Math.round(g).toString(16)
  b = Math.round(b).toString(16)

  r = r.length === 1 ? '0' + r : r
  g = g.length === 1 ? '0' + g : g
  b = b.length === 1 ? '0' + b : b

  return '#' + r + g + b
}

colorsys.rgb_to_hex = colorsys.rgb2Hex
colorsys.rgbToHex = colorsys.rgb2Hex

colorsys.hex2Rgb = function (hex) {
  var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null
}

colorsys.hex_to_rgb = colorsys.hex2Rgb
colorsys.hexToRgb = colorsys.hex2Rgb

colorsys.hsv2Hex = function (h, s, v) {
  var rgb = colorsys.hsv2Rgb(h, s, v)
  return colorsys.rgb2Hex(rgb.r, rgb.g, rgb.b)
}

colorsys.hsv_to_hex = colorsys.hsv2Hex
colorsys.hsvToHex = colorsys.hsv2Hex

colorsys.hex2Hsv = function (hex) {
  var rgb = colorsys.hex2Rgb(hex)
  return colorsys.rgb2Hsv(rgb.r, rgb.g, rgb.b)[0]
}

colorsys.hex_to_hsv = colorsys.hex2Hsv
colorsys.hexToHsv = colorsys.hex2Hsv

colorsys.hsl2Hex = function (h, s, l) {
  var rgb = colorsys.hsl2Rgb(h, s, l)
  return colorsys.rgb2Hex(rgb.r, rgb.g, rgb.b)
}

colorsys.hsl_to_hex = colorsys.hsl2Hex
colorsys.hslToHex = colorsys.hsl2Hex

colorsys.hex2Hsl = function (hex) {
  var rgb = colorsys.hex2Rgb(hex)
  return colorsys.rgb2Hsl(rgb.r, rgb.g, rgb.b)[0]
}

colorsys.hex_to_hsl = colorsys.hex2Hsl
colorsys.hexToHsl = colorsys.hex2Hsl
<|endoftext|>