<commit_before>'use strict';

angular.module('ng-geotooltip', [])
    .directive('geotooltip', ['$timeout', function ($timeout) {
        // The container is shared between directives to avoid performance issues
        var container = angular.element('

');
        var map = null;
        var layerGroup = null;

        var displayTooltip = function(tippedElement, width, height, coords, geoJson) {
            // Make the container the right size
            var resized = false;
            if (width !== container.css('width') || height !== container.css('height')) {
                resized = true;
            }
            container.css('width', width);
            container.css('height', height);

            // Position it at the right place
            container.css('top', tippedElement.prop('offsetHeight')+'px');
            container.css('left', tippedElement.prop('offsetWidth')+'px');
            tippedElement.append(container);

            if (map === null) {
                map = new L.map(container[0], {zoomControl: false});
                var tilesUrl = 'http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png';
                var attrib = 'Tiles Courtesy of MapQuest  - Map data © OpenStreetMap contributors';
                var tileLayer = new L.TileLayer(tilesUrl, {minZoom: 1, maxZoom: 18, attribution: attrib, subdomains: '1234'});
                map.addLayer(tileLayer);
            } else if (resized) {
                map.invalidateSize();
            }

            if (layerGroup !== null) {
                map.removeLayer(layerGroup);
            }
            layerGroup = L.layerGroup();
            var bounds = new L.LatLngBounds();

            if (coords) {
                var point = new L.LatLng(coords[0], coords[1]);
                var pointLayer = L.marker(point);
                layerGroup.addLayer(pointLayer);
                bounds.extend(point);
            }

            if (geoJson) {
                var geoJsonLayer = L.geoJson(geoJson);
                layerGroup.addLayer(geoJsonLayer);
                bounds.extend(geoJsonLayer.getBounds());
            }
            //map.setView(point, 12);
            layerGroup.addTo(map);
            map.fitBounds(bounds);
            container.css('opacity', '1');
        };

        var hideTooltip = function() {
            container.css('opacity', '0');
        };

        return {
            template: '',
            replace: true,
            restrict: 'E',
            transclude: true,
            scope: {
                'coords': '=',
                'width': '@',
                'height': '@',
                'delay': '@',
                'geojson': '='
            },
            link: function(scope, element, attrs) {
                var tooltipWidth = '200px';
                var tooltipHeight = '200px';
                var tooltipPop = null;

                var delay = attrs.delay || 1000;
                if (attrs.height) {
                    tooltipHeight = attrs.height+'px';
                }
                if (attrs.width) {
                    tooltipWidth = attrs.width+'px';
                }

                // Events
                element.bind('mouseover', function() {
                    tooltipPop = $timeout(function() {
                        displayTooltip(element, tooltipWidth, tooltipHeight, scope.coords, scope.geojson);
                        tooltipPop = null;
                    }, delay);
                });
                element.bind('click', function() {
                    displayTooltip(element, tooltipWidth, tooltipHeight, scope.coords, scope.geojson);
                    if (tooltipPop !== null) {
                        // Chances are we triggered the original timer
                        $timeout.cancel(tooltipPop);
                        tooltipPop = null;
                    }
                });
                element.bind('mouseout', function() {
                    hideTooltip();
                    if (tooltipPop !== null) {
                        // We are currently counting down until the tooltip appearance, let's forget it
                        $timeout.cancel(tooltipPop);
                        tooltipPop = null;
                    }

                });
            }
        };
    }]);
<commit_msg>Isolate code<commit_after>(function() {
    'use strict';

    angular.module('ng-geotooltip', [])
        .directive('geotooltip', ['$timeout', function ($timeout) {
            // The container is shared between directives to avoid performance issues
            var container = angular.element('

');
            var map = null;
            var layerGroup = null;

            var displayTooltip = function(tippedElement, width, height, coords, geoJson) {
                // Make the container the right size
                var resized = false;
                if (width !== container.css('width') || height !== container.css('height')) {
                    resized = true;
                }
                container.css('width', width);
                container.css('height', height);

                // Position it at the right place
                container.css('top', tippedElement.prop('offsetHeight')+'px');
                container.css('left', tippedElement.prop('offsetWidth')+'px');
                tippedElement.append(container);

                if (map === null) {
                    map = new L.map(container[0], {zoomControl: false});
                    var tilesUrl = 'http://otile{s}.mqcdn.com/tiles/1.0.0/map/{z}/{x}/{y}.png';
                    var attrib = 'Tiles Courtesy of MapQuest  - Map data © OpenStreetMap contributors';
                    var tileLayer = new L.TileLayer(tilesUrl, {minZoom: 1, maxZoom: 18, attribution: attrib, subdomains: '1234'});
                    map.addLayer(tileLayer);
                } else if (resized) {
                    map.invalidateSize();
                }

                if (layerGroup !== null) {
                    map.removeLayer(layerGroup);
                }
                layerGroup = L.layerGroup();
                var bounds = new L.LatLngBounds();

                if (coords) {
                    var point = new L.LatLng(coords[0], coords[1]);
                    var pointLayer = L.marker(point);
                    layerGroup.addLayer(pointLayer);
                    bounds.extend(point);
                }

                if (geoJson) {
                    var geoJsonLayer = L.geoJson(geoJson);
                    layerGroup.addLayer(geoJsonLayer);
                    bounds.extend(geoJsonLayer.getBounds());
                }
                //map.setView(point, 12);
                layerGroup.addTo(map);
                map.fitBounds(bounds);
                container.css('opacity', '1');
            };

            var hideTooltip = function() {
                container.css('opacity', '0');
            };

            return {
                template: '',
                replace: true,
                restrict: 'E',
                transclude: true,
                scope: {
                    'coords': '=',
                    'width': '@',
                    'height': '@',
                    'delay': '@',
                    'geojson': '='
                },
                link: function(scope, element, attrs) {
                    var tooltipWidth = '200px';
                    var tooltipHeight = '200px';
                    var tooltipPop = null;

                    var delay = attrs.delay || 1000;
                    if (attrs.height) {
                        tooltipHeight = attrs.height+'px';
                    }
                    if (attrs.width) {
                        tooltipWidth = attrs.width+'px';
                    }

                    // Events
                    element.bind('mouseover', function() {
                        tooltipPop = $timeout(function() {
                            displayTooltip(element, tooltipWidth, tooltipHeight, scope.coords, scope.geojson);
                            tooltipPop = null;
                        }, delay);
                    });
                    element.bind('click', function() {
                        displayTooltip(element, tooltipWidth, tooltipHeight, scope.coords, scope.geojson);
                        if (tooltipPop !== null) {
                            // Chances are we triggered the original timer
                            $timeout.cancel(tooltipPop);
                            tooltipPop = null;
                        }
                    });
                    element.bind('mouseout', function() {
                        hideTooltip();
                        if (tooltipPop !== null) {
                            // We are currently counting down until the tooltip appearance, let's forget it
                            $timeout.cancel(tooltipPop);
                            tooltipPop = null;
                        }

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


<commit_before>module.exports = Laser;

function Laser (ship,context) {
  this.x = ship.x;
  this.y = ship.y;
  this.angle = ship.angle;
  this.laserSpeed = 50;
  this.laserLength = 10;
  this.context = context;

  return this;
}

Laser.prototype.setLaserTrajectory = function () {
  if(this.angle === 0) {
        this.y -= this.laserLength;
    }
    else if(this.angle === 45) {
        this.y -= this.laserLength;
        this.x += this.laserLength;
    }
    else if(this.angle === 90) {
        this.x += this.laserLength;
    }
    else if(this.angle === 135) {
        this.y += this.laserLength;
        this.x += this.laserLength;
    }
    else if(this.angle === 180) {
        this.y += this.laserLength;
    }
    else if(this.angle === 225) {
        this.y += this.laserLength;
        this.x -= this.laserLength;
    }
    else if(this.angle === 270) {
        this.x -= this.laserLength;
    }
    else if(this.angle === 315) {
        this.y -= this.laserLength;
        this.x -= this.laserLength;
    }

    return this;
}

Laser.prototype.draw = function () {
  this.context.strokeStyle = '#f00';
  this.context.moveTo(this.x, this.y);
  this.setLaserTrajectory();
  this.context.lineTo(this.x, this.y);
  this.context.stroke();

  return this;
}<commit_msg>Fix merge conflict<commit_after>module.exports = Laser;

function Laser (ship,context) {
    this.ship = ship;
    this.shipheight = this.ship.height/3;
    this.x = ship.x;
    this.y = ship.y;
    this.angle = ship.angle;
    this.laserSpeed = 10;
    this.laserLength = 1;
    this.context = context;

    return this;
}

Laser.prototype.setLaserTrajectory = function () {
    if(this.angle === 0) {
        this.y -= this.laserSpeed;
    }
    else if(this.angle === 45) {
        this.y -= this.laserSpeed;
        this.x += this.laserSpeed;
    }
    else if(this.angle === 90) {
        this.x += this.laserSpeed;
    }
    else if(this.angle === 135) {
        this.y += this.laserSpeed;
        this.x += this.laserSpeed;
    }
    else if(this.angle === 180) {
        this.y += this.laserSpeed;
    }
    else if(this.angle === 225) {
        this.y += this.laserSpeed;
        this.x -= this.laserSpeed;
    }
    else if(this.angle === 270) {
        this.x -= this.laserSpeed;
    }
    else if(this.angle === 315) {
        this.y -= this.laserSpeed;
        this.x -= this.laserSpeed;
    }

    return this;
};

Laser.prototype.draw = function () {
    this.context.fillStyle = "#f00";
    this.context.beginPath();
    this.context.arc(this.x, this.y-this.shipheight, 1.5, 0, Math.PI*2, true);
    this.context.closePath();
    this.context.fill();

    this.setLaserTrajectory();

    return this;
};<|endoftext|>


<commit_before>var async = require('async');
var uuid = require('node-uuid');
var util = require('util');
var EE   = require('events').EventEmitter;
var Ticket = require('./ticket');
var Worker = require('./worker');
var Tickets = require('./tickets');
var MemoryStore = require('./stores/memory');

function Queue(process, opts) {
  var self = this;
  opts = opts || {};
  if (typeof process === 'object') {
    opts = process || {};
  }
  if (typeof process === 'function') {
    opts.process = process;
  }
  if (!opts.process) {
    throw new Error("Queue has no process function.");
  }

  opts = opts || {};

  self.empty = opts.empty || function(){};
  self.drain = opts.drain || function(){};

  self.process = opts.process || function (task, cb) { cb(null, {}) };
  self.filter = opts.filter || function (input, cb) { cb(null, input) };
  self.priority = opts.priority || null;
  self.merge = opts.merge || function (oldTask, newTask, cb) { cb(null, newTask) };

  self.cancelIfRunning = (opts.cancelIfRunning === undefined ? true : !!opts.cancelIfRunning);
  self.autoResume = (opts.autoResume === undefined ? true : !!opts.autoResume);
  self.filo = opts.filo || false;
  self.batchSize = opts.batchSize || 1;
  self.concurrent = opts.concurrent || 1;
  self.processDelay = opts.processDelay || 0;
  self.processTimeout = opts.processTimeout || Infinity;
  self.idleTimeout = opts.idleTimeout || 0;
  self.maxRetries = opts.maxRetries || 0;

  // Statuses
  self._stopped = false;
  self._saturated = false;

  self._timeout = null;
  self._calledDrain = true;
  self._calledEmpty = true;
  self._running = 0;  // Active running tasks
  self._retries = {}; // Map of taskId => retries
  self._workers = {}; // Map of taskId => active job
  self._tickets = {}; // Map of taskId => tickets

  // Initialize Storage
  self.use(opts.store || 'memory');
  self._store.connect(function () {
    if (self.autoResume) {
      self.resume();
    }
  })
}

util.inherits(Queue, EE);

Queue.prototype.use = function (store, opts) {
  var self = this;
  if (typeof store === 'string') {
    try {
      var Store = require('./stores/' + store)
      return self._store = new Store(opts);
    } catch (e) {}
  }
  if (typeof store === 'object' && typeof store.type === 'string') {
    try {
      var Store = require('./stores/' + store.type)
      return self._store = new Store(store);
    } catch (e) {}
  }
  if (typeof store === 'object' &&
    store.putTask &&
    store.getTask &&
    ((self.filo && store.takeLastN) ||
     (!self.filo && store.takeFirstN))) {
    return self._store = store;
  }
  throw new Error('unknown_store');
}

Queue.prototype.resume = function () {
  var self = this;
  self._stopped = false;
  self._getWorkers().forEach(function (worker) {
    if (typeof worker.resume === 'function') {
      worker.resume();
    }
  })
  self._processNext();
}

Queue.prototype.pause = function () {
  this._stopped = true;
  this._getWorkers().forEach(function (worker) {
    if (typeof worker.pause === 'function') {
      worker.pause();
    }
  })
}

Queue.prototype.push = function (input, cb) {
  var self = this;
  var ticket = new Ticket();
  if (cb) {
    ticket
      .on('done', function (result) { cb(null, result) })
      .on('error', function (err) { cb(err) })
  }
  self.filter(input, function (err, task) {
    if (err || task === undefined || task === false || task === null) {
      return ticket.failed('input_rejected');
    }
    var taskId = task.id || uuid.v4();
    ticket.accept();
    self._queueTask(taskId, task, ticket);
  })
  return ticket;
}

Queue.prototype._getWorkers = function () {
  var self = this;
  var workers = [];
  Object.keys(self._workers).forEach(function (taskId) {
    var worker = self._workers[taskId];
    if (worker && workers.indexOf(worker) === -1) {
      workers.push(worker);
    }
  })
  return workers;
}

Queue.prototype._queueTask = function (taskId, task, ticket) {
  var self = this;
  var priority;
  var isNew = true;
  var putTask = function () {
    self._store.putTask(taskId, task, priority, function (err) {
      if (err) return ticket.failed('failed_to_put_task');

      if (!self._tickets[taskId]) {
        self._tickets[taskId] = new Tickets();
      }
      self._tickets[taskId].push(ticket);
      ticket.queued();

      if (isNew) {
        self._calledDrain = false;
        self._calledEmpty = false;
      }
      if (!self._timeout) {
        self._timeout = setTimeout(function () {
          self._timeout = null;
          self._processNext();
        }, self.processDelay)
      }
    })
  }
  var updateTask = function () {
    if (!self.priority) return putTask();
    self.priority(task, function (err, priority) {
      if (err) return ticket.failed('failed_to_prioritize');
      putTask();
    })
  }

  var worker = self._workers[taskId];
  if (self.cancelIfRunning && worker) {
    worker.cancel();
  }

  self._store.getTask(taskId, function (err, oldTask) {
    if (err) return ticket.failed('failed_to_get');

    // No task before
    if (oldTask === undefined) {
      return updateTask();
    }

    self.merge(oldTask, task, function (err, newTask) {
      if (err) return ticket.failed('failed_task_merge');
      if (newTask === undefined) return;
      task = newTask;
      isNew = false;
      updateTask();
    });
  })
}

Queue.prototype._emptied = function () {
  if (this._calledEmpty) return;
  if (typeof this.empty === 'function') {
    this._calledEmpty = true;
    this.empty();
  }
}

Queue.prototype._drained = function () {
  this._emptied();
  if (this._calledDrain) return;
  if (typeof this.drain === 'function') {
    this._calledDrain = true;
    this.drain();
  }
}

Queue.prototype._getNextBatch = function (cb) {
  this._store[this.filo ? 'takeLastN' : 'takeFirstN'](this.batchSize, cb)
}

Queue.prototype._processNext = function () {

  var self = this;
  self._saturated = (self._running >= self.concurrent);
  if (self._saturated) return;
  if (self._stopped) return;

  // Fetch next batch
  self._getNextBatch(function (err, batch) {
    if (err || !batch) return;

    var isEmpty = !Object.keys(batch).length;

    if (isEmpty && !self._running) {
      return self._drained();
    }

    if (isEmpty) {
      return self._emptied();
    }

    var tickets = {};
    Object.keys(batch).forEach(function (taskId) {
      var ticket = self._tickets[taskId];
      if (ticket) {
        ticket.started(batch[taskId].total);
        tickets[taskId] = ticket;
        delete self._tickets[taskId];
      }
    })

    self._startBatch(batch, tickets);

    // Continue processing until saturated
    setImmediate(function () {
      self._processNext();
    })
  });
}

Queue.prototype._startBatch = function (batch, tickets) {
  var self = this;
  var taskIds = Object.keys(batch);

  var timeout = null;
  var worker = new Worker({
    fn: self.process,
    batch: batch,
    single: (self.batchSize === 1)
  })
  if (self.processTimeout < Infinity) {
    timeout = setTimeout(function () {
      worker.failed('task_timeout');
    }, self.processTimeout);
  }
  worker.on('task_failed', function (taskId, msg) {
    self._retries[taskId] = self._retries[taskId] || 0;
    self._retries[taskId]++;
    if (self._retries[taskId] >= self.maxRetries) {
      if (tickets[taskId]) {
        // Mark as a failure
        tickets[taskId].failed(msg);
        delete tickets[taskId];
      }
      self.emit('task_failed', { task: taskId, message: msg });
    } else {
      // Pop back onto queue and retry
      self.emit('task_retry', { task: taskId, retries: self._retries[taskId] });
      self._queueTask(taskId, batch[taskId], tickets[taskId]);
    }
  })
  worker.on('task_finish', function (taskId, result) {
    if (tickets[taskId]) {
      tickets[taskId].finish(result);
      delete tickets[taskId];
    }
    self.emit('task_finish', { task: taskId, result: result });
  })
  worker.on('task_progress', function (taskId, completed) {
    if (tickets[taskId]) {
      tickets[taskId].progress(completed);
      delete tickets[taskId];
    }
    self.emit('task_progress', { task: taskId, completed: completed });
  })
  worker.on('end', function () {
    self._running--;
    if (timeout) {
      clearTimeout(timeout);
    }
    taskIds.forEach(function (taskId) {
      delete self._workers[taskId];
    });
    setTimeout(function () {
      self._processNext();
    }, self.idleTimeout);
  })

  // Acquire lock on process
  self._running++;
  worker.start();

  taskIds.forEach(function (taskId) {
    self._workers[taskId] = worker || {};
  });
}

module.exports = Queue;
<commit_msg>Fixed bug with callback<commit_after>var async = require('async');
var uuid = require('node-uuid');
var util = require('util');
var EE   = require('events').EventEmitter;
var Ticket = require('./ticket');
var Worker = require('./worker');
var Tickets = require('./tickets');
var MemoryStore = require('./stores/memory');

function Queue(process, opts) {
  var self = this;
  opts = opts || {};
  if (typeof process === 'object') {
    opts = process || {};
  }
  if (typeof process === 'function') {
    opts.process = process;
  }
  if (!opts.process) {
    throw new Error("Queue has no process function.");
  }

  opts = opts || {};

  self.empty = opts.empty || function(){};
  self.drain = opts.drain || function(){};

  self.process = opts.process || function (task, cb) { cb(null, {}) };
  self.filter = opts.filter || function (input, cb) { cb(null, input) };
  self.priority = opts.priority || null;
  self.merge = opts.merge || function (oldTask, newTask, cb) { cb(null, newTask) };

  self.cancelIfRunning = (opts.cancelIfRunning === undefined ? true : !!opts.cancelIfRunning);
  self.autoResume = (opts.autoResume === undefined ? true : !!opts.autoResume);
  self.filo = opts.filo || false;
  self.batchSize = opts.batchSize || 1;
  self.concurrent = opts.concurrent || 1;
  self.processDelay = opts.processDelay || 0;
  self.processTimeout = opts.processTimeout || Infinity;
  self.idleTimeout = opts.idleTimeout || 0;
  self.maxRetries = opts.maxRetries || 0;

  // Statuses
  self._stopped = false;
  self._saturated = false;

  self._timeout = null;
  self._calledDrain = true;
  self._calledEmpty = true;
  self._running = 0;  // Active running tasks
  self._retries = {}; // Map of taskId => retries
  self._workers = {}; // Map of taskId => active job
  self._tickets = {}; // Map of taskId => tickets

  // Initialize Storage
  self.use(opts.store || 'memory');
  self._store.connect(function () {
    if (self.autoResume) {
      self.resume();
    }
  })
}

util.inherits(Queue, EE);

Queue.prototype.use = function (store, opts) {
  var self = this;
  if (typeof store === 'string') {
    try {
      var Store = require('./stores/' + store)
      return self._store = new Store(opts);
    } catch (e) {}
  }
  if (typeof store === 'object' && typeof store.type === 'string') {
    try {
      var Store = require('./stores/' + store.type)
      return self._store = new Store(store);
    } catch (e) {}
  }
  if (typeof store === 'object' &&
    store.putTask &&
    store.getTask &&
    ((self.filo && store.takeLastN) ||
     (!self.filo && store.takeFirstN))) {
    return self._store = store;
  }
  throw new Error('unknown_store');
}

Queue.prototype.resume = function () {
  var self = this;
  self._stopped = false;
  self._getWorkers().forEach(function (worker) {
    if (typeof worker.resume === 'function') {
      worker.resume();
    }
  })
  self._processNext();
}

Queue.prototype.pause = function () {
  this._stopped = true;
  this._getWorkers().forEach(function (worker) {
    if (typeof worker.pause === 'function') {
      worker.pause();
    }
  })
}

Queue.prototype.push = function (input, cb) {
  var self = this;
  var ticket = new Ticket();
  if (cb) {
    ticket
      .on('done', function (result) { cb(null, result) })
      .on('fail', function (err) { cb(err) })
  }

  self.filter(input, function (err, task) {
    if (err || task === undefined || task === false || task === null) {
      return ticket.failed('input_rejected');
    }
    var taskId = task.id || uuid.v4();
    ticket.accept();
    self._queueTask(taskId, task, ticket);
  })
  return ticket;
}

Queue.prototype._getWorkers = function () {
  var self = this;
  var workers = [];
  Object.keys(self._workers).forEach(function (taskId) {
    var worker = self._workers[taskId];
    if (worker && workers.indexOf(worker) === -1) {
      workers.push(worker);
    }
  })
  return workers;
}

Queue.prototype._queueTask = function (taskId, task, ticket) {
  var self = this;
  var priority;
  var isNew = true;
  var putTask = function () {
    self._store.putTask(taskId, task, priority, function (err) {
      if (err) return ticket.failed('failed_to_put_task');

      if (!self._tickets[taskId]) {
        self._tickets[taskId] = new Tickets();
      }
      self._tickets[taskId].push(ticket);
      ticket.queued();

      if (isNew) {
        self._calledDrain = false;
        self._calledEmpty = false;
      }
      if (!self._timeout) {
        self._timeout = setTimeout(function () {
          self._timeout = null;
          self._processNext();
        }, self.processDelay)
      }
    })
  }
  var updateTask = function () {
    if (!self.priority) return putTask();
    self.priority(task, function (err, priority) {
      if (err) return ticket.failed('failed_to_prioritize');
      putTask();
    })
  }

  var worker = self._workers[taskId];
  if (self.cancelIfRunning && worker) {
    worker.cancel();
  }

  self._store.getTask(taskId, function (err, oldTask) {
    if (err) return ticket.failed('failed_to_get');

    // No task before
    if (oldTask === undefined) {
      return updateTask();
    }

    self.merge(oldTask, task, function (err, newTask) {
      if (err) return ticket.failed('failed_task_merge');
      if (newTask === undefined) return;
      task = newTask;
      isNew = false;
      updateTask();
    });
  })
}

Queue.prototype._emptied = function () {
  if (this._calledEmpty) return;
  if (typeof this.empty === 'function') {
    this._calledEmpty = true;
    this.empty();
  }
}

Queue.prototype._drained = function () {
  this._emptied();
  if (this._calledDrain) return;
  if (typeof this.drain === 'function') {
    this._calledDrain = true;
    this.drain();
  }
}

Queue.prototype._getNextBatch = function (cb) {
  this._store[this.filo ? 'takeLastN' : 'takeFirstN'](this.batchSize, cb)
}

Queue.prototype._processNext = function () {

  var self = this;
  self._saturated = (self._running >= self.concurrent);
  if (self._saturated) return;
  if (self._stopped) return;

  // Fetch next batch
  self._getNextBatch(function (err, batch) {
    if (err || !batch) return;

    var isEmpty = !Object.keys(batch).length;

    if (isEmpty && !self._running) {
      return self._drained();
    }

    if (isEmpty) {
      return self._emptied();
    }

    var tickets = {};
    Object.keys(batch).forEach(function (taskId) {
      var ticket = self._tickets[taskId];
      if (ticket) {
        ticket.started(batch[taskId].total);
        tickets[taskId] = ticket;
        delete self._tickets[taskId];
      }
    })

    self._startBatch(batch, tickets);

    // Continue processing until saturated
    setImmediate(function () {
      self._processNext();
    })
  });
}

Queue.prototype._startBatch = function (batch, tickets) {
  var self = this;
  var taskIds = Object.keys(batch);

  var timeout = null;
  var worker = new Worker({
    fn: self.process,
    batch: batch,
    single: (self.batchSize === 1)
  })
  if (self.processTimeout < Infinity) {
    timeout = setTimeout(function () {
      worker.failed('task_timeout');
    }, self.processTimeout);
  }
  worker.on('task_failed', function (taskId, msg) {
    self._retries[taskId] = self._retries[taskId] || 0;
    self._retries[taskId]++;
    if (self._retries[taskId] >= self.maxRetries) {
      if (tickets[taskId]) {
        // Mark as a failure
        tickets[taskId].failed(msg);
        delete tickets[taskId];
      }
      self.emit('task_failed', { task: taskId, message: msg });
    } else {
      // Pop back onto queue and retry
      self.emit('task_retry', { task: taskId, retries: self._retries[taskId] });
      self._queueTask(taskId, batch[taskId], tickets[taskId]);
    }
  })
  worker.on('task_finish', function (taskId, result) {
    if (tickets[taskId]) {
      tickets[taskId].finish(result);
      delete tickets[taskId];
    }
    self.emit('task_finish', { task: taskId, result: result });
  })
  worker.on('task_progress', function (taskId, completed) {
    if (tickets[taskId]) {
      tickets[taskId].progress(completed);
      delete tickets[taskId];
    }
    self.emit('task_progress', { task: taskId, completed: completed });
  })
  worker.on('end', function () {
    self._running--;
    if (timeout) {
      clearTimeout(timeout);
    }
    taskIds.forEach(function (taskId) {
      delete self._workers[taskId];
    });
    setTimeout(function () {
      self._processNext();
    }, self.idleTimeout);
  })

  // Acquire lock on process
  self._running++;
  worker.start();

  taskIds.forEach(function (taskId) {
    self._workers[taskId] = worker || {};
  });
}

module.exports = Queue;
<|endoftext|>


<commit_before>var PATH = require('./path'),
    INHERIT = require('inherit'),
    createTech = require('./tech').createTech,
    bemUtil = require('./util'),
    isRequireable = bemUtil.isRequireable,
    isRequireError = bemUtil.isRequireError,
    require = bemUtil.requireWrapper(require),

    getLevelClass = function(path) {
        var level = requireLevel(path);
        if(level.Level) return level.Level;
        return INHERIT(level.baseLevelPath? getLevelClass(level.baseLevelPath) : Level, level);
    },

    requireLevel = function(path) {
        try {
            var level = require(PATH.absolute(path), true);
        } catch (e) {
            if(!isRequireError(e)) throw e;
        }
        return level || {};
    };

exports.createLevel = function(path) {
    // NOTE: в директории .bem внутри уровня переопределения
    // лежит модуль-конфиг для уровня переопределения
    return new (getLevelClass(PATH.join(PATH.absolute(path), '.bem', 'level.js')))(path);
};

var Level = exports.Level = INHERIT({

    __constructor: function(path) {
        this.dir = PATH.absolute(path);
        // NOTE: keep this.path for backwards compatability
        this.path = this.bemDir = PATH.join(this.dir, '.bem');
        this.techs = this.initTechs(this.getTechs() || {});
        this._techsCache = {};
    },

    getConfig: function() {
        return {};
    },

    getTechs: function() {
        return this.techs || {};
    },

    initTechs: function(desc) {
        var techs = {};
        for(var t in desc) {
            techs[t] = this.resolveTech(desc[t], true);
        }
        return techs;
    },

    getTech: function(name, path) {
        if(!this._techsCache.hasOwnProperty(name)) {
            this._techsCache[name] = this.createTech(name, path || name);
        }
        return this._techsCache[name];
    },

    createTech: function(name, path) {
        return createTech(this.resolveTech(path || name), name);
    },

    resolveTech: function(techIdent, force) {
        if(bemUtil.isPath(techIdent)) {
            return this.resolveTechPath(techIdent);
        }
        if(!force && this.techs.hasOwnProperty(techIdent)) {
            return this.resolveTechName(techIdent);
        }
        return bemUtil.getBemTechPath(techIdent);
    },

    resolveTechName: function(techIdent) {
        return (this.techs[techIdent] || null);
    },

    resolveTechPath: function(techPath) {
        // Получить абсолютный путь, если путь начинается с .
        // NOTE: заменить на !isAbsolute() нельзя
        if(techPath.substring(0, 1) === '.') {
            // Развернуть относительный путь начиная от директории .bem
            techPath = PATH.join(this.bemDir, techPath);
            if(!isRequireable(techPath)) {
                throw new Error("Tech module on path '" + techPath + "' not found");
            }
            return techPath;
        }

        // Пробуем абсолютный или относительный путь без .
        if(isRequireable(techPath)) {
            return techPath;
        }

        throw new Error("Tech module with path '" + techPath + "' not found on require search paths");
    },

    getDefaultTechs: function() {
        return this.defaultTechs || Object.keys(this.techs);
    },

    resolvePaths: function(paths) {

        // resolve array of paths
        if (Array.isArray(paths)) {
            return paths.map(function(path) {
                return this.resolvePath(path);
            }, this);
        }

        // resolve paths in object values
        var resolved = {};
        Object.keys(paths).forEach(function(key) {
            resolved[key] = this.resolvePath(paths[key]);
        }, this);

        return resolved;

    },

    resolvePath: function(path) {
        return PATH.resolve(this.path, path);
    },

    getByObj: function(item) {
        return PATH.join(this.dir, this.getRelByObj(item));
    },

    getRelByObj: function(item) {
        var getter, args;
        if (item.block) {
            getter = 'block';
            args = [item.block];
            if (item.elem) {
                getter = 'elem';
                args.push(item.elem);
            }
            if (item.mod) {
                getter += '-mod';
                args.push(item.mod);
                if (item.val) {
                    getter += '-val';
                    args.push(item.val);
                }
            }
            return this.getRel(getter, args);
        }
    },

    get: function(what, args) {
        return PATH.join(this.dir, this.getRel(what, args));
    },

    getRel: function(what, args) {
        return this['get-' + what].apply(this, args);
    },

    'get-block': function(block) {
        return PATH.join.apply(null, [block, block]);
    },

    'get-block-mod': function(block, mod) {
        return PATH.join.apply(null,
            [block,
            '_' + mod,
            block + '_' + mod]);
    },

    'get-block-mod-val': function(block, mod, val) {
        return PATH.join.apply(null,
            [block,
            '_' + mod,
            block + '_' + mod + '_' + val]);
    },

    'get-elem': function(block, elem) {
        return PATH.join.apply(null,
            [block,
            '__' + elem,
            block + '__' + elem]);
    },

    'get-elem-mod': function(block, elem, mod) {
        return PATH.join.apply(null,
            [block,
            '__' + elem,
            '_' + mod,
            block + '__' + elem + '_' + mod]);
    },

    'get-elem-mod-val': function(block, elem, mod, val) {
        return PATH.join.apply(null,
            [block,
            '__' + elem,
            '_' + mod,
            block + '__' + elem + '_' + mod + '_' + val]);
    },

    matchRe: function() {
        return '[^_.' + PATH.dirSepRe + ']+';
    },

    matchOrder: function() {
        return ['elem-mod-val', 'elem-mod', 'block-mod-val',
            'block-mod', 'elem', 'block'];
    },

    matchTechsOrder: function() {
        var order = [];
        for (var key in this.techs) order.push(key);
        return order;
    },

    match: function(what, path) {
        return this['match-' + what].call(this, path);
    },

    'match-block': function(path) {
        var match = new RegExp(['^(' + this.matchRe() + ')',
            '\\1(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            suffix: match[2]
        };
    },

    'match-block-mod': function(path) {
        var m = this.matchRe(),
            match = new RegExp(['^(' + m + ')',
            '_(' + m + ')',
            '\\1_\\2(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            mod: match[2],
            suffix: match[3]
        };
    },

    'match-block-mod-val': function(path) {
        var m = this.matchRe(),
            match = new RegExp(['^(' + m + ')',
            '_(' + m + ')',
            '\\1_\\2_(' + m + ')(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            mod: match[2],
            val: match[3],
            suffix: match[4]
        };
    },

    'match-elem': function(path) {
        var m = this.matchRe(),
            match = new RegExp(['^(' + m + ')',
            '__(' + m + ')',
            '\\1__\\2(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            elem: match[2],
            suffix: match[3]
        };
    },

    'match-elem-mod': function(path) {
        var m = this.matchRe(),
            match = new RegExp(['^(' + m + ')',
            '__(' + m + ')',
            '_(' + m + ')',
            '\\1__\\2_\\3(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            elem: match[2],
            mod: match[3],
            suffix: match[4]
        };
    },

    'match-elem-mod-val': function(path) {
        var m = this.matchRe(),
            match = new RegExp(['^(' + m + ')',
            '__(' + m + ')',
            '_(' + m + ')',
            '\\1__\\2_\\3_(' + m + ')(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            elem: match[2],
            mod: match[3],
            val: match[4],
            suffix: match[5]
        };
    },

    getBlockByIntrospection: function(blockName) {
        var decl = this.getDeclByIntrospection(PATH.dirname(this.get('block', [blockName])));
        return decl.length? decl.shift() : {};
    },

    getDeclByIntrospection: function(from) {
        from = from || '.';
        var _this = this,
            decl = [],
            matchTechs = this.matchTechsOrder().map(function(techIdent) {
                return _this.getTech(techIdent);
            });

        bemUtil.fsWalkTree(PATH.resolve(_this.dir, from), function(f) {
            f = PATH.relative(_this.bemDir, f);
            _this.matchOrder().forEach(function(matcher) {
                var match = _this.match(matcher, f);
                if(match) {
                    matchTechs.forEach(function(t) {
                        !match.tech && t.matchSuffix(match.suffix) &&
                            (match.tech = t.getTechName());
                    });
                    if(match.tech) {
                        decl = _this._mergeMatchToDecl(match, decl);
                    }
                }
            });
        }, function(f) {
            return !_this.isIgnorablePath(f);
        });

        return decl;
    },

    isIgnorablePath: function(path) {
        return /\.svn$/.test(path);
    },

    _mergeMatchToDecl: function(match, decl) {
        var blocks, elems, mods, vals,
            techAdded = false,
            addTech = function(o) {
                if(!techAdded && match.tech) {
                    o.techs = [{ name: match.tech }];
                    techAdded = true;
                }
                return o;
            };

        match.val &&
            (vals = [addTech({name: match.val})]);
        match.mod && match.val &&
            (mods = [addTech({name: match.mod, vals: vals})]);
        match.mod && !match.val &&
            (mods = [addTech({name: match.mod})]);
        match.elem &&
            (elems = [addTech({name: match.elem, mods: mods})]) &&
            (blocks = [addTech({name: match.block, elems: elems})]);
        !match.elem &&
            (blocks = [addTech({name: match.block, mods: mods})]);

        return bemUtil.mergeDecls(decl, blocks);
    }

});
<commit_msg>Error when using tech from linked libraries in project bundles levels .bem/level.js<commit_after>var PATH = require('./path'),
    INHERIT = require('inherit'),
    createTech = require('./tech').createTech,
    bemUtil = require('./util'),
    isRequireable = bemUtil.isRequireable,
    isRequireError = bemUtil.isRequireError,
    require = bemUtil.requireWrapper(require),

    getLevelClass = function(path) {
        var level = requireLevel(path);
        if(level.Level) return level.Level;
        return INHERIT(level.baseLevelPath? getLevelClass(level.baseLevelPath) : Level, level);
    },

    requireLevel = function(path) {
        try {
            var level = require(PATH.absolute(path), true);
        } catch (e) {
            if(!isRequireError(e)) throw e;
        }
        return level || {};
    };

exports.createLevel = function(path) {
    // NOTE: в директории .bem внутри уровня переопределения
    // лежит модуль-конфиг для уровня переопределения
    return new (getLevelClass(PATH.join(PATH.absolute(path), '.bem', 'level.js')))(path);
};

var Level = exports.Level = INHERIT({

    __constructor: function(path) {
        this.dir = PATH.absolute(path);
        // NOTE: keep this.path for backwards compatability
        this.path = this.bemDir = PATH.join(this.dir, '.bem');
        this._techsCache = {};
    },

    getConfig: function() {
        return {};
    },

    getTechs: function() {
        return this.techs || {};
    },

    getTech: function(name, path) {
        if(!this._techsCache.hasOwnProperty(name)) {
            this._techsCache[name] = this.createTech(name, path || name);
        }
        return this._techsCache[name];
    },

    createTech: function(name, path) {
        return createTech(this.resolveTech(path || name), name);
    },

    resolveTech: function(techIdent, force) {
        if(bemUtil.isPath(techIdent)) {
            return this.resolveTechPath(techIdent);
        }
        if(!force && this.getTechs().hasOwnProperty(techIdent)) {
            return this.resolveTechName(techIdent);
        }
        return bemUtil.getBemTechPath(techIdent);
    },

    resolveTechName: function(techIdent) {
        var p = this.getTechs()[techIdent];
        return typeof p !== 'undefined'? this.resolveTech(p, true) : null;
    },

    resolveTechPath: function(techPath) {
        // Получить абсолютный путь, если путь начинается с .
        // NOTE: заменить на !isAbsolute() нельзя
        if(techPath.substring(0, 1) === '.') {
            // Развернуть относительный путь начиная от директории .bem
            techPath = PATH.join(this.bemDir, techPath);
            if(!isRequireable(techPath)) {
                throw new Error("Tech module on path '" + techPath + "' not found");
            }
            return techPath;
        }

        // Пробуем абсолютный или относительный путь без .
        if(isRequireable(techPath)) {
            return techPath;
        }

        throw new Error("Tech module with path '" + techPath + "' not found on require search paths");
    },

    getDefaultTechs: function() {
        return this.defaultTechs || Object.keys(this.getTechs());
    },

    resolvePaths: function(paths) {

        // resolve array of paths
        if (Array.isArray(paths)) {
            return paths.map(function(path) {
                return this.resolvePath(path);
            }, this);
        }

        // resolve paths in object values
        var resolved = {};
        Object.keys(paths).forEach(function(key) {
            resolved[key] = this.resolvePath(paths[key]);
        }, this);

        return resolved;

    },

    resolvePath: function(path) {
        return PATH.resolve(this.path, path);
    },

    getByObj: function(item) {
        return PATH.join(this.dir, this.getRelByObj(item));
    },

    getRelByObj: function(item) {
        var getter, args;
        if (item.block) {
            getter = 'block';
            args = [item.block];
            if (item.elem) {
                getter = 'elem';
                args.push(item.elem);
            }
            if (item.mod) {
                getter += '-mod';
                args.push(item.mod);
                if (item.val) {
                    getter += '-val';
                    args.push(item.val);
                }
            }
            return this.getRel(getter, args);
        }
    },

    get: function(what, args) {
        return PATH.join(this.dir, this.getRel(what, args));
    },

    getRel: function(what, args) {
        return this['get-' + what].apply(this, args);
    },

    'get-block': function(block) {
        return PATH.join.apply(null, [block, block]);
    },

    'get-block-mod': function(block, mod) {
        return PATH.join.apply(null,
            [block,
            '_' + mod,
            block + '_' + mod]);
    },

    'get-block-mod-val': function(block, mod, val) {
        return PATH.join.apply(null,
            [block,
            '_' + mod,
            block + '_' + mod + '_' + val]);
    },

    'get-elem': function(block, elem) {
        return PATH.join.apply(null,
            [block,
            '__' + elem,
            block + '__' + elem]);
    },

    'get-elem-mod': function(block, elem, mod) {
        return PATH.join.apply(null,
            [block,
            '__' + elem,
            '_' + mod,
            block + '__' + elem + '_' + mod]);
    },

    'get-elem-mod-val': function(block, elem, mod, val) {
        return PATH.join.apply(null,
            [block,
            '__' + elem,
            '_' + mod,
            block + '__' + elem + '_' + mod + '_' + val]);
    },

    matchRe: function() {
        return '[^_.' + PATH.dirSepRe + ']+';
    },

    matchOrder: function() {
        return ['elem-mod-val', 'elem-mod', 'block-mod-val',
            'block-mod', 'elem', 'block'];
    },

    matchTechsOrder: function() {
        return Object.keys(this.getTechs());
    },

    match: function(what, path) {
        return this['match-' + what].call(this, path);
    },

    'match-block': function(path) {
        var match = new RegExp(['^(' + this.matchRe() + ')',
            '\\1(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            suffix: match[2]
        };
    },

    'match-block-mod': function(path) {
        var m = this.matchRe(),
            match = new RegExp(['^(' + m + ')',
            '_(' + m + ')',
            '\\1_\\2(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            mod: match[2],
            suffix: match[3]
        };
    },

    'match-block-mod-val': function(path) {
        var m = this.matchRe(),
            match = new RegExp(['^(' + m + ')',
            '_(' + m + ')',
            '\\1_\\2_(' + m + ')(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            mod: match[2],
            val: match[3],
            suffix: match[4]
        };
    },

    'match-elem': function(path) {
        var m = this.matchRe(),
            match = new RegExp(['^(' + m + ')',
            '__(' + m + ')',
            '\\1__\\2(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            elem: match[2],
            suffix: match[3]
        };
    },

    'match-elem-mod': function(path) {
        var m = this.matchRe(),
            match = new RegExp(['^(' + m + ')',
            '__(' + m + ')',
            '_(' + m + ')',
            '\\1__\\2_\\3(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            elem: match[2],
            mod: match[3],
            suffix: match[4]
        };
    },

    'match-elem-mod-val': function(path) {
        var m = this.matchRe(),
            match = new RegExp(['^(' + m + ')',
            '__(' + m + ')',
            '_(' + m + ')',
            '\\1__\\2_\\3_(' + m + ')(.*?)$'].join(PATH.dirSepRe)).exec(path);
        if (!match) return false;
        return {
            block: match[1],
            elem: match[2],
            mod: match[3],
            val: match[4],
            suffix: match[5]
        };
    },

    getBlockByIntrospection: function(blockName) {
        var decl = this.getDeclByIntrospection(PATH.dirname(this.get('block', [blockName])));
        return decl.length? decl.shift() : {};
    },

    getDeclByIntrospection: function(from) {
        from = from || '.';
        var _this = this,
            decl = [],
            matchTechs = this.matchTechsOrder().map(function(techIdent) {
                return _this.getTech(techIdent);
            });

        bemUtil.fsWalkTree(PATH.resolve(_this.dir, from), function(f) {
            f = PATH.relative(_this.bemDir, f);
            _this.matchOrder().forEach(function(matcher) {
                var match = _this.match(matcher, f);
                if(match) {
                    matchTechs.forEach(function(t) {
                        !match.tech && t.matchSuffix(match.suffix) &&
                            (match.tech = t.getTechName());
                    });
                    if(match.tech) {
                        decl = _this._mergeMatchToDecl(match, decl);
                    }
                }
            });
        }, function(f) {
            return !_this.isIgnorablePath(f);
        });

        return decl;
    },

    isIgnorablePath: function(path) {
        return /\.svn$/.test(path);
    },

    _mergeMatchToDecl: function(match, decl) {
        var blocks, elems, mods, vals,
            techAdded = false,
            addTech = function(o) {
                if(!techAdded && match.tech) {
                    o.techs = [{ name: match.tech }];
                    techAdded = true;
                }
                return o;
            };

        match.val &&
            (vals = [addTech({name: match.val})]);
        match.mod && match.val &&
            (mods = [addTech({name: match.mod, vals: vals})]);
        match.mod && !match.val &&
            (mods = [addTech({name: match.mod})]);
        match.elem &&
            (elems = [addTech({name: match.elem, mods: mods})]) &&
            (blocks = [addTech({name: match.block, elems: elems})]);
        !match.elem &&
            (blocks = [addTech({name: match.block, mods: mods})]);

        return bemUtil.mergeDecls(decl, blocks);
    }

});
<|endoftext|>


<commit_before>/**
 *
 * This module provides routines dealing with javascript objects.
 *
 * @module dex/object
 * @name object
 * @memberOf dex
 *
 */

module.exports = function object(dex) {

  return {
    /**
     *
     * Return the lccal keys of this object without the inherited ones.
     *
     * @param obj The object whose local keys we are interested in.
     *
     * @returns {Array} An array of 0 or more lccal keys.
     */
    'keys': function keys(obj) {
      var keys = [];

      for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          keys.push(key);
        }
      }

      return keys;
    },

    /**
     *
     * A pretty good, but imperfect mechanism for performing a deep
     * clone of an object.
     *
     * @param obj The object to clone.
     * @returns {*} The cloned object.
     *
     */
    'clone': function clone(obj) {
      var i, attr, len;

      // Handle the 3 simple types, and null or undefined
      if (null == obj || "object" != typeof obj)
        return obj;

      // Handle Date
      if (obj instanceof Date) {
        var copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
      }

      // Handle Array
      if (obj instanceof Array) {
        var copy = [];
        for (i = 0, len = obj.length; i < len; i++) {
          copy[i] = dex.object.clone(obj[i]);
        }
        return copy;
      }

      // DOM Nodes are nothing but trouble.
      if (dex.object.isElement(obj) ||
        dex.object.isNode(obj)) {
        return obj;
      }

      // Handle Object
      if (obj instanceof Object) {
        var copy = {};
        //jQuery.extend(copy, obj);
        for (attr in obj) {
          if (obj.hasOwnProperty(attr)) {
            copy[attr] = dex.object.clone(obj[attr]);
            //copy[attr] = obj[attr];
          }
        }
        return copy;
      }

      throw new Error("Unable to copy obj! Its type isn't supported.");
    },

    /*
     This version causes expand to continue forever.

     'isEmpty' : function isEmpty(obj) {
     return _.isEmpty(obj);
     };
     */

    /**
     *
     * Kind of misleading.  This really signals when expand should quit
     * expanding.  I need to clean this up.
     *
     * @param obj
     * @returns {boolean}
     */
    'isEmpty': function isEmpty(obj) {
      //dex.console.log("isEmpty(" + obj + ") typeof=" + (typeof obj));
      if (!obj || obj instanceof Array) {
        return true;
      }
      if ("object" == typeof obj) {
        for (var key in obj) {
          if (obj.hasOwnProperty(key)) {
            //dex.console.log("OBJ: ", obj, " contains key '" + key + "'");
            return false;
          }
        }
      }

      return true;
    },

    /**
     *
     * Overlay the top object on top of the bottom.  This method will first clone
     * the bottom object.  Then it will drop the values within the top object
     * into the clone.
     *
     * @param {Object} top - The object who's properties will be on top.
     * @param {Object} bottom - The object who's properties will be on bottom.
     * @return {Object} The overlaid object where the properties in top override
     *                  properties in bottom.  The return object is a clone or
     *                  copy.
     *
     */
    'overlay': function overlay(top, bottom) {
      // Make a clone of the bottom object.
      var overlay = dex.object.clone(bottom);
      var prop;

      // If we have parameters in the top object, overlay them on top
      // of the bottom object.
      if (top !== 'undefined') {
        // Iterate over the props in top.
        for (prop in top) {
          // Arrays are special cases. [A] on top of [A,B] should give [A], not [A,B]
          if (typeof top[prop] == 'object' && overlay[prop] != null && !(top[prop] instanceof Array)) {
            //console.log("PROP: " + prop + ", top=" + top + ", overlay=" + overlay);
            overlay[prop] = dex.object.overlay(top[prop], overlay[prop]);
          }
          // Simply overwrite for simple cases and arrays.
          else {
            overlay[prop] = top[prop];
          }
        }
      }

      //console.dir(config);
      return overlay;
    },

    /**
     *
     * This method returns whether or not the supplied object is a Node.
     *
     * @param {Object} obj - The object to test.
     *
     * @returns {boolean} True if obj is a Node, false otherwise.
     *
     */
    'isNode': function isNode(obj) {
      return (
        typeof Node === "object" ? obj instanceof Node :
        obj && typeof obj === "object" && typeof obj.nodeType === "number" && typeof obj.nodeName === "string"
      );
    },

    /**
     *
     * This method returns whether or not the supplied object is a
     * DOM node.
     *
     * @param {Object} obj - The object to test.
     *
     * @returns {boolean} - True if obj is a DOM node, false otherwise.
     *
     */
    'isElement': function isElement(obj) {
      return (
        typeof HTMLElement === "object" ? obj instanceof HTMLElement : //DOM2
        obj && typeof obj === "object" && obj.nodeType === 1 && typeof obj.nodeName === "string"
      );
    },

    /**
     *
     * This method returns a boolean representing whether obj is contained
     * within container.
     *
     * @param {Object} container - The container to test.
     * @param {Object} obj - The object to test.
     *
     * @return True if container contains obj.  False otherwise.
     */
    'contains': function contains(container, obj) {
      var i = container.length;
      while (i--) {
        if (container[i] === obj) {
          return true;
        }
      }
      return false;
    },

    /**
     *
     * Return whether or not the supplied object is a function.
     *
     * @param obj The object to check.
     * @returns {boolean} True if obj is a function, false otherwise.
     *
     */
    'isFunction': function isFunction(obj) {
      //return typeof obj === 'function';
      return _.isFunction(obj);
    },

    /**
     *
     * Visit each local property within.
     *
     * @param obj
     * @param func
     */
    /*
     'visit' : function (obj, func) {
     var prop;
     func(obj);
     for (prop in obj) {
     if (obj.hasOwnProperty(prop)) {
     if (typeof obj[prop] === 'object') {
     dex.object.visit(obj[prop], func);
     }
     }
     }
     }
     */

    /**
     *
     * @param map
     * @param values
     * @returns {exports}
     */
    'connect': function connect(map, values) {
      //dex.console.log("map:", map, "values:", values);

      if (!values || values.length <= 0) {
        return this;
      }
      if (!map[values[0]]) {
        map[values[0]] = {};
      }
      dex.object.connect(map[values[0]], values.slice(1));

      return this;
    },

    /**
     *
     * @param obj
     * @returns {boolean}
     */
    'isNumeric': function (obj) {
      return !isNaN(parseFloat(obj)) && isFinite(obj);
    },

    /**
     *
     * @param hierarchy
     * @param name
     * @param value
     * @param delimiter
     * @returns {*}
     */
    'setHierarchical': function (hierarchy, name, value, delimiter) {
      if (hierarchy == null) {
        hierarchy = {};
      }

      if (typeof hierarchy != 'object') {
        return hierarchy;
      }

      // Create an array of names by splitting delimiter, then call
      // this function in the 3 argument (Array of paths) context.
      if (arguments.length == 4) {
        return dex.object.setHierarchical(hierarchy,
          name.split(delimiter), value);
      }

      // Array of paths context.
      else {
        // This is the last variable name, just set the value.
        if (name.length === 1) {
          hierarchy[name[0]] = value;
        }
        // We still have to traverse.
        else {
          // Undefined container object, just create an empty.
          if (!(name[0] in hierarchy)) {
            hierarchy[name[0]] = {};
          }

          // Recursively traverse down the hierarchy.
          dex.object.setHierarchical(hierarchy[name[0]], name.splice(1), value);
        }
      }

      return hierarchy;
    }
  };
};

<commit_msg>Documentation fix<commit_after>/**
 *
 * This module provides routines dealing with javascript objects.
 *
 * @module dex:object
 * @name object
 * @memberOf dex
 *
 */

module.exports = function object(dex) {

  return {
    /**
     *
     * Return the local keys of this object without the inherited ones.
     *
     * @param obj The object whose local keys we are interested in.
     *
     * @returns {Array} An array of 0 or more local keys.
     */
    'keys': function keys(obj) {
      var keys = [];

      for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          keys.push(key);
        }
      }

      return keys;
    },

    /**
     *
     * A pretty good, but imperfect mechanism for performing a deep
     * clone of an object.
     *
     * @param obj The object to clone.
     * @returns {*} The cloned object.
     *
     */
    'clone': function clone(obj) {
      var i, attr, len;

      // Handle the 3 simple types, and null or undefined
      if (null == obj || "object" != typeof obj)
        return obj;

      // Handle Date
      if (obj instanceof Date) {
        var copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
      }

      // Handle Array
      if (obj instanceof Array) {
        var copy = [];
        for (i = 0, len = obj.length; i < len; i++) {
          copy[i] = dex.object.clone(obj[i]);
        }
        return copy;
      }

      // DOM Nodes are nothing but trouble.
      if (dex.object.isElement(obj) ||
        dex.object.isNode(obj)) {
        return obj;
      }

      // Handle Object
      if (obj instanceof Object) {
        var copy = {};
        //jQuery.extend(copy, obj);
        for (attr in obj) {
          if (obj.hasOwnProperty(attr)) {
            copy[attr] = dex.object.clone(obj[attr]);
            //copy[attr] = obj[attr];
          }
        }
        return copy;
      }

      throw new Error("Unable to copy obj! Its type isn't supported.");
    },

    /*
     This version causes expand to continue forever.

     'isEmpty' : function isEmpty(obj) {
     return _.isEmpty(obj);
     };
     */

    /**
     *
     * Kind of misleading.  This really signals when expand should quit
     * expanding.  I need to clean this up.
     *
     * @param obj
     * @returns {boolean}
     */
    'isEmpty': function isEmpty(obj) {
      //dex.console.log("isEmpty(" + obj + ") typeof=" + (typeof obj));
      if (!obj || obj instanceof Array) {
        return true;
      }
      if ("object" == typeof obj) {
        for (var key in obj) {
          if (obj.hasOwnProperty(key)) {
            //dex.console.log("OBJ: ", obj, " contains key '" + key + "'");
            return false;
          }
        }
      }

      return true;
    },

    /**
     *
     * Overlay the top object on top of the bottom.  This method will first clone
     * the bottom object.  Then it will drop the values within the top object
     * into the clone.
     *
     * @param {Object} top - The object who's properties will be on top.
     * @param {Object} bottom - The object who's properties will be on bottom.
     * @return {Object} The overlaid object where the properties in top override
     *                  properties in bottom.  The return object is a clone or
     *                  copy.
     *
     */
    'overlay': function overlay(top, bottom) {
      // Make a clone of the bottom object.
      var overlay = dex.object.clone(bottom);
      var prop;

      // If we have parameters in the top object, overlay them on top
      // of the bottom object.
      if (top !== 'undefined') {
        // Iterate over the props in top.
        for (prop in top) {
          // Arrays are special cases. [A] on top of [A,B] should give [A], not [A,B]
          if (typeof top[prop] == 'object' && overlay[prop] != null && !(top[prop] instanceof Array)) {
            //console.log("PROP: " + prop + ", top=" + top + ", overlay=" + overlay);
            overlay[prop] = dex.object.overlay(top[prop], overlay[prop]);
          }
          // Simply overwrite for simple cases and arrays.
          else {
            overlay[prop] = top[prop];
          }
        }
      }

      //console.dir(config);
      return overlay;
    },

    /**
     *
     * This method returns whether or not the supplied object is a Node.
     *
     * @param {Object} obj - The object to test.
     *
     * @returns {boolean} True if obj is a Node, false otherwise.
     *
     */
    'isNode': function isNode(obj) {
      return (
        typeof Node === "object" ? obj instanceof Node :
        obj && typeof obj === "object" && typeof obj.nodeType === "number" && typeof obj.nodeName === "string"
      );
    },

    /**
     *
     * This method returns whether or not the supplied object is a
     * DOM node.
     *
     * @param {Object} obj - The object to test.
     *
     * @returns {boolean} - True if obj is a DOM node, false otherwise.
     *
     */
    'isElement': function isElement(obj) {
      return (
        typeof HTMLElement === "object" ? obj instanceof HTMLElement : //DOM2
        obj && typeof obj === "object" && obj.nodeType === 1 && typeof obj.nodeName === "string"
      );
    },

    /**
     *
     * This method returns a boolean representing whether obj is contained
     * within container.
     *
     * @param {Object} container - The container to test.
     * @param {Object} obj - The object to test.
     *
     * @return True if container contains obj.  False otherwise.
     */
    'contains': function contains(container, obj) {
      var i = container.length;
      while (i--) {
        if (container[i] === obj) {
          return true;
        }
      }
      return false;
    },

    /**
     *
     * Return whether or not the supplied object is a function.
     *
     * @param obj The object to check.
     * @returns {boolean} True if obj is a function, false otherwise.
     *
     */
    'isFunction': function isFunction(obj) {
      //return typeof obj === 'function';
      return _.isFunction(obj);
    },

    /**
     *
     * Visit each local property within.
     *
     * @param obj
     * @param func
     */
    /*
     'visit' : function (obj, func) {
     var prop;
     func(obj);
     for (prop in obj) {
     if (obj.hasOwnProperty(prop)) {
     if (typeof obj[prop] === 'object') {
     dex.object.visit(obj[prop], func);
     }
     }
     }
     }
     */

    /**
     *
     * @param map
     * @param values
     * @returns {exports}
     */
    'connect': function connect(map, values) {
      //dex.console.log("map:", map, "values:", values);

      if (!values || values.length <= 0) {
        return this;
      }
      if (!map[values[0]]) {
        map[values[0]] = {};
      }
      dex.object.connect(map[values[0]], values.slice(1));

      return this;
    },

    /**
     *
     * @param obj
     * @returns {boolean}
     */
    'isNumeric': function (obj) {
      return !isNaN(parseFloat(obj)) && isFinite(obj);
    },

    /**
     *
     * @param hierarchy
     * @param name
     * @param value
     * @param delimiter
     * @returns {*}
     */
    'setHierarchical': function (hierarchy, name, value, delimiter) {
      if (hierarchy == null) {
        hierarchy = {};
      }

      if (typeof hierarchy != 'object') {
        return hierarchy;
      }

      // Create an array of names by splitting delimiter, then call
      // this function in the 3 argument (Array of paths) context.
      if (arguments.length == 4) {
        return dex.object.setHierarchical(hierarchy,
          name.split(delimiter), value);
      }

      // Array of paths context.
      else {
        // This is the last variable name, just set the value.
        if (name.length === 1) {
          hierarchy[name[0]] = value;
        }
        // We still have to traverse.
        else {
          // Undefined container object, just create an empty.
          if (!(name[0] in hierarchy)) {
            hierarchy[name[0]] = {};
          }

          // Recursively traverse down the hierarchy.
          dex.object.setHierarchical(hierarchy[name[0]], name.splice(1), value);
        }
      }

      return hierarchy;
    }
  };
};

<|endoftext|>


<commit_before>'use strict'

var Readable = require('stream').Readable
var util = require('util')

function RangeStream (opt) {
  Readable.call(this, opt)

  this.opt = opt
  this.opt.count = this.opt.count || 10
  this.results = false

  this.range()
}

util.inherits(RangeStream, Readable)

RangeStream.prototype.range = function () {
  var self = this

  this.opt.redis.lrange(this.opt.key, 0, 10000, function lrangeResult (err, results) {
    handlePacket(err, results, self)
  })
}

function handlePacket (err, res, self) {
  if (err) {
    self.emit('error', err)
    return
  }
  console.log('========', res)
  if (res.length) {
    self.results = res
  } else {
    self.results = null
  }

  // if (res !== '{}') {
  //   var results = parse(res)

  //   if (results.err) {
  //     self.emit('error', results.err)
  //     return
  //   }
  //   self.results = results.value
  // } else {
  //   self.results = null
  // }

  self.emit('ready')
}

RangeStream.prototype._read = function () {
  if (this.results === false) {
    return this.once('ready', this._read)
  }

  var results = this.results
  this.results = null

  this.push(results)
}

module.exports = RangeStream
<commit_msg>removed logs<commit_after>'use strict'

var Readable = require('stream').Readable
var util = require('util')

function RangeStream (opt) {
  Readable.call(this, opt)

  this.opt = opt
  this.opt.count = this.opt.count || 10
  this.results = false

  this.range()
}

util.inherits(RangeStream, Readable)

RangeStream.prototype.range = function () {
  var self = this

  this.opt.redis.lrange(this.opt.key, 0, 10000, function lrangeResult (err, results) {
    handlePacket(err, results, self)
  })
}

function handlePacket (err, res, self) {
  if (err) {
    self.emit('error', err)
    return
  }

  if (res.length) {
    self.results = res
  } else {
    self.results = null
  }

  self.emit('ready')
}

RangeStream.prototype._read = function () {
  if (this.results === false) {
    return this.once('ready', this._read)
  }

  var results = this.results
  this.results = null

  this.push(results)
}

module.exports = RangeStream
<|endoftext|>


<commit_before>// Color object

'use strict';

var math = require('../util/math');
var color = require('../util/color');
var js = require('../util/js');

// var RGB = 'RGB';
var HSB = 'HSB';
var HSL = 'HSL';
var HEX = 'HEX';

var Color = function (v1, v2, v3, v4, v5) {
    var _r, _g, _b, _a, rgb, options;
    if (v1 === undefined) {
        _r = _g = _b = 0;
        _a = 1;
    } else if (Array.isArray(v1)) {
        options = v2 || {};
        _r = v1[0] !== undefined ? v1[0] : 0;
        _g = v1[1] !== undefined ? v1[1] : 0;
        _b = v1[2] !== undefined ? v1[2] : 0;
        _a = v1[3] !== undefined ? v1[3] : options.range || 1;
    } else if (v1.r !== undefined) {
        options = v2 || {};
        _r = v1.r;
        _g = v1.g;
        _b = v1.b;
        _a = v1.a !== undefined ? v1.a : options.range || 1;
    } else if (typeof v1 === 'string') {
        rgb = color.hex2rgb(v1);
        _r = rgb[0];
        _g = rgb[1];
        _b = rgb[2];
        _a = 1;
    } else if (typeof v1 === 'number') {
        if (arguments.length === 1) { // Grayscale value
            _r = _g = _b = v1;
            _a = 1;
        } else if (arguments.length === 2) { // Gray and alpha or options
            _r = _g = _b = v1;
            if (typeof v2 === 'number') {
                _a = v2;
            } else {
                options = v2;
                _a = options.range || 1;
            }
        } else if (arguments.length === 3) { // RGB or gray, alpha and options
            if (typeof v3 === 'number') {
                _r = v1;
                _g = v2;
                _b = v3;
                _a = 1;
            } else {
                _r = _g = _b = v1;
                _a = v2;
                options = v3;
            }
        } else if (arguments.length === 4) { // RGB and alpha or options
            _r = v1;
            _g = v2;
            _b = v3;
            if (typeof v4 === 'number') {
                _a = v4;
            } else {
                options = v4;
                _a = options.range || 1;
            }
        } else { // RGBA + options
            _r = v1;
            _g = v2;
            _b = v3;
            _a = v4;
            options = v5;
        }
    }
    options = options || {};

    // The range option allows you to specify values in a different range.
    if (options.range !== undefined) {
        _r /= options.range;
        _g /= options.range;
        _b /= options.range;
        _a /= options.range;
        if (options.mode === HSB) {
            v1 /= options.range;
            v2 /= options.range;
            v3 /= options.range;
        }
    }
    // Convert HSB colors to RGB
    if (options.mode === HSB) {
        v1 = math.clamp(v1, 0, 1);
        v2 = math.clamp(v2, 0, 1);
        v3 = math.clamp(v3, 0, 1);
        rgb = color.hsb2rgb(v1, v2, v3);
        _r = rgb[0];
        _g = rgb[1];
        _b = rgb[2];
    // Convert HSL colors to RGB
    } else if (options.mode === HSL) {
        v1 = math.clamp(v1, 0, 1);
        v2 = math.clamp(v2, 0, 1);
        v3 = math.clamp(v3, 0, 1);
        rgb = color.hsl2rgb(v1, v2, v3);
        _r = rgb[0];
        _g = rgb[1];
        _b = rgb[2];
    } else if (options.mode === HEX) {
        rgb = color.hex2rgb(v1);
        _r = rgb[0];
        _g = rgb[1];
        _b = rgb[2];
        _a = 1;
    }

    this.r = math.clamp(_r, 0, 1);
    this.g = math.clamp(_g, 0, 1);
    this.b = math.clamp(_b, 0, 1);
    this.a = math.clamp(_a, 0, 1);
};

Color.BLACK = new Color(0);
Color.WHITE = new Color(1);

js.defineAlias(Color, 'r', 'red');
js.defineAlias(Color, 'g', 'green');
js.defineAlias(Color, 'b', 'blue');
js.defineAlias(Color, 'a', 'alpha');

// The hue of the color, in HSL color mode. (Although hue is the same in HSL and HSB).
js.defineGetter(Color, 'h', function () {
    return color.rgb2hsl(this.r, this.g, this.b)[0];
});

// The saturation of the color, in HSL color mode. (Saturation is different in HSL and HSB).
js.defineGetter(Color, 's', function () {
    return color.rgb2hsl(this.r, this.g, this.b)[1];
});

// The lightness of the color, in HSL color mode. (Lightness in HSL is different from brightness in HSB).
js.defineGetter(Color, 'l', function () {
    return color.rgb2hsl(this.r, this.g, this.b)[2];
});

js.defineAlias(Color, 'h', 'hue');
js.defineAlias(Color, 's', 'saturation');
js.defineAlias(Color, 'l', 'lightness');

js.defineGetter(Color, 'rgb', function () {
    return [this.r, this.g, this.b];
});

js.defineGetter(Color, 'rgba', function () {
    return [this.r, this.g, this.b, this.a];
});

js.defineGetter(Color, 'hsb', function () {
    return color.rgb2hsb(this.r, this.g, this.b);
});

js.defineGetter(Color, 'hsba', function () {
    return color.rgb2hsb(this.r, this.g, this.b).concat([this.a]);
});

js.defineGetter(Color, 'hsl', function () {
    return color.rgb2hsl(this.r, this.g, this.b);
});

js.defineGetter(Color, 'hsla', function () {
    return color.rgb2hsl(this.r, this.g, this.b).concat([this.a]);
});

Color.prototype.toCSS = function () {
    return Color.toCSS(this);
};

Color.prototype.toHex = function () {
    if (this.a >= 1) {
        return color.rgb2hex(this.r, this.g, this.b);
    } else {
        return color.rgba2hex(this.r, this.g, this.b, this.a);
    }
};

Color.prototype.desaturate = function (options) {
    if (this.r === this.g && this.g === this.b) { return this; }
    var rCoeff, gCoeff, bCoeff;
    if (options === undefined || !options.method || options.method === 'ITU-R BT.601') {
        rCoeff = 0.3; gCoeff = 0.59; bCoeff = 0.11;
    } else if (options.method === 'ITU-R BT.709') {
        rCoeff = 0.2125; gCoeff = 0.7154; bCoeff = 0.0721;
    }
    var gray = this.r * rCoeff + this.g * gCoeff + this.b * bCoeff;
    return new Color(gray, gray, gray, this.a);
};

Color.prototype.invert = function () {
    return new Color(1 - this.r, 1 - this.g, 1 - this.b, this.a);
};

Color.clone = function (c) {
    if (c === null || c === undefined) {
        return null;
    } else if (typeof c === 'string') {
        return c;
    } else {
        return new Color(c.r, c.g, c.b, c.a);
    }
};

Color.toCSS = function (c) {
    if (c === null) {
        return 'none';
    } else if (c === undefined) {
        return 'black';
    } else if (typeof c === 'string') {
        return c;
    } else if (c instanceof Color) {
        var r255 = Math.round(c.r * 255),
            g255 = Math.round(c.g * 255),
            b255 = Math.round(c.b * 255);
        return 'rgba(' + r255 + ', ' + g255 + ', ' + b255 + ', ' + c.a + ')';
    } else if (c.r !== undefined && c.g !== undefined && c.b !== undefined) {
        if (c.a === undefined) {
            return 'rgb(' + c.r + ', ' + c.g + ', ' + c.b + ')';
        } else {
            return 'rgba(' + c.r + ', ' + c.g + ', ' + c.b + ', ' + c.a + ')';
        }
    } else {
        throw new Error('Don\'t know how to convert ' + c + ' to CSS.');
    }
};

Color.toHex = function (c) {
    return Color.parse(c).toHex();
};

Color.make = function () {
    var c = Object.create(Color.prototype);
    c.constructor = Color.prototype;
    Color.apply(c, arguments);
    return c;
};

Color.parse = function (s) {
    var m;
    if (s === undefined || s === null) {
        return new Color(0, 0, 0, 0);
    } else if (s instanceof Color) {
        return s;
    } else if (color.namedColors[s]) {
        return Color.make.apply(null, color.namedColors[s]);
    } else if (s[0] === '#') {
        return new Color(s, 0, 0, 0, { mode: HEX });
    } else if (s.startsWith('rgba')) {
        m = s.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+|\d+.\d+)\s*\)$/i);
        if (m) {
            return new Color(parseInt(m[1]) / 255, parseInt(m[2]) / 255, parseInt(m[3]) / 255, parseFloat(m[4]));
        }
        return new Color(0, 0, 0, 0);
    } else if (s.startsWith('rgb')) {
        m = s.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
        if (m) {
            return new Color(parseInt(m[1]) / 255, parseInt(m[2]) / 255, parseInt(m[3]) / 255);
        }
        return new Color(0, 0, 0, 0);
    } else if (s.startsWith('hsla')) {
        m = s.match(/^hsla\s*\(\s*(\d+|\d+.\d+)\s*,\s*(\d+|\d+.\d+)%\s*,\s*(\d+|\d+.\d+)%\s*,\s*(\d+|\d+.\d+)\s*\)$/i);
        if (m) {
            return new Color(parseFloat(m[1]) / 360, parseFloat(m[2]) / 100, parseFloat(m[3]) / 100, parseFloat(m[4]));
        }
        return new Color(0, 0, 0, 0);
    } else if (s.startsWith('hsl')) {
        m = s.match(/^hsl\s*\(\s*(\d+|\d+.\d+)\s*,\s*(\d+|\d+.\d+)%\s*,\s*(\d+|\d+.\d+)%\s*\)$/i);
        if (m) {
            return new Color(parseFloat(m[1]) / 360, parseFloat(m[2]) / 100, parseFloat(m[3]) / 100);
        }
        return new Color(0, 0, 0, 0);
    } else if (s === 'none') {
        return new Color(0, 0, 0, 0);
    } else {
        throw new Error('Color ' + s + 'can not be parsed');
    }
};

Color.gray = function (gray, alpha, range) {
    range = Math.max(range, 1);
    return new Color(gray / range, gray / range, gray / range, alpha / range);
};

Color.rgb = function (red, green, blue, alpha, range) {
    range = Math.max(range, 1);
    return new Color(red / range, green / range, blue / range, alpha / range);
};

Color.hsb = function (hue, saturation, brightness, alpha, range) {
    range = Math.max(range, 1);
    return new Color(hue / range, saturation / range, brightness / range, alpha / range, { mode: HSB });
};

Color.hsl = function (hue, saturation, lightness, alpha, range) {
    range = Math.max(range, 1);
    return new Color(hue / range, saturation / range, lightness / range, alpha / range, { mode: HSL });
};

module.exports = Color;
<commit_msg>npm test couldn't handle ''.startsWith<commit_after>// Color object

'use strict';

var math = require('../util/math');
var color = require('../util/color');
var js = require('../util/js');

// var RGB = 'RGB';
var HSB = 'HSB';
var HSL = 'HSL';
var HEX = 'HEX';

var Color = function (v1, v2, v3, v4, v5) {
    var _r, _g, _b, _a, rgb, options;
    if (v1 === undefined) {
        _r = _g = _b = 0;
        _a = 1;
    } else if (Array.isArray(v1)) {
        options = v2 || {};
        _r = v1[0] !== undefined ? v1[0] : 0;
        _g = v1[1] !== undefined ? v1[1] : 0;
        _b = v1[2] !== undefined ? v1[2] : 0;
        _a = v1[3] !== undefined ? v1[3] : options.range || 1;
    } else if (v1.r !== undefined) {
        options = v2 || {};
        _r = v1.r;
        _g = v1.g;
        _b = v1.b;
        _a = v1.a !== undefined ? v1.a : options.range || 1;
    } else if (typeof v1 === 'string') {
        rgb = color.hex2rgb(v1);
        _r = rgb[0];
        _g = rgb[1];
        _b = rgb[2];
        _a = 1;
    } else if (typeof v1 === 'number') {
        if (arguments.length === 1) { // Grayscale value
            _r = _g = _b = v1;
            _a = 1;
        } else if (arguments.length === 2) { // Gray and alpha or options
            _r = _g = _b = v1;
            if (typeof v2 === 'number') {
                _a = v2;
            } else {
                options = v2;
                _a = options.range || 1;
            }
        } else if (arguments.length === 3) { // RGB or gray, alpha and options
            if (typeof v3 === 'number') {
                _r = v1;
                _g = v2;
                _b = v3;
                _a = 1;
            } else {
                _r = _g = _b = v1;
                _a = v2;
                options = v3;
            }
        } else if (arguments.length === 4) { // RGB and alpha or options
            _r = v1;
            _g = v2;
            _b = v3;
            if (typeof v4 === 'number') {
                _a = v4;
            } else {
                options = v4;
                _a = options.range || 1;
            }
        } else { // RGBA + options
            _r = v1;
            _g = v2;
            _b = v3;
            _a = v4;
            options = v5;
        }
    }
    options = options || {};

    // The range option allows you to specify values in a different range.
    if (options.range !== undefined) {
        _r /= options.range;
        _g /= options.range;
        _b /= options.range;
        _a /= options.range;
        if (options.mode === HSB) {
            v1 /= options.range;
            v2 /= options.range;
            v3 /= options.range;
        }
    }
    // Convert HSB colors to RGB
    if (options.mode === HSB) {
        v1 = math.clamp(v1, 0, 1);
        v2 = math.clamp(v2, 0, 1);
        v3 = math.clamp(v3, 0, 1);
        rgb = color.hsb2rgb(v1, v2, v3);
        _r = rgb[0];
        _g = rgb[1];
        _b = rgb[2];
    // Convert HSL colors to RGB
    } else if (options.mode === HSL) {
        v1 = math.clamp(v1, 0, 1);
        v2 = math.clamp(v2, 0, 1);
        v3 = math.clamp(v3, 0, 1);
        rgb = color.hsl2rgb(v1, v2, v3);
        _r = rgb[0];
        _g = rgb[1];
        _b = rgb[2];
    } else if (options.mode === HEX) {
        rgb = color.hex2rgb(v1);
        _r = rgb[0];
        _g = rgb[1];
        _b = rgb[2];
        _a = 1;
    }

    this.r = math.clamp(_r, 0, 1);
    this.g = math.clamp(_g, 0, 1);
    this.b = math.clamp(_b, 0, 1);
    this.a = math.clamp(_a, 0, 1);
};

Color.BLACK = new Color(0);
Color.WHITE = new Color(1);

js.defineAlias(Color, 'r', 'red');
js.defineAlias(Color, 'g', 'green');
js.defineAlias(Color, 'b', 'blue');
js.defineAlias(Color, 'a', 'alpha');

// The hue of the color, in HSL color mode. (Although hue is the same in HSL and HSB).
js.defineGetter(Color, 'h', function () {
    return color.rgb2hsl(this.r, this.g, this.b)[0];
});

// The saturation of the color, in HSL color mode. (Saturation is different in HSL and HSB).
js.defineGetter(Color, 's', function () {
    return color.rgb2hsl(this.r, this.g, this.b)[1];
});

// The lightness of the color, in HSL color mode. (Lightness in HSL is different from brightness in HSB).
js.defineGetter(Color, 'l', function () {
    return color.rgb2hsl(this.r, this.g, this.b)[2];
});

js.defineAlias(Color, 'h', 'hue');
js.defineAlias(Color, 's', 'saturation');
js.defineAlias(Color, 'l', 'lightness');

js.defineGetter(Color, 'rgb', function () {
    return [this.r, this.g, this.b];
});

js.defineGetter(Color, 'rgba', function () {
    return [this.r, this.g, this.b, this.a];
});

js.defineGetter(Color, 'hsb', function () {
    return color.rgb2hsb(this.r, this.g, this.b);
});

js.defineGetter(Color, 'hsba', function () {
    return color.rgb2hsb(this.r, this.g, this.b).concat([this.a]);
});

js.defineGetter(Color, 'hsl', function () {
    return color.rgb2hsl(this.r, this.g, this.b);
});

js.defineGetter(Color, 'hsla', function () {
    return color.rgb2hsl(this.r, this.g, this.b).concat([this.a]);
});

Color.prototype.toCSS = function () {
    return Color.toCSS(this);
};

Color.prototype.toHex = function () {
    if (this.a >= 1) {
        return color.rgb2hex(this.r, this.g, this.b);
    } else {
        return color.rgba2hex(this.r, this.g, this.b, this.a);
    }
};

Color.prototype.desaturate = function (options) {
    if (this.r === this.g && this.g === this.b) { return this; }
    var rCoeff, gCoeff, bCoeff;
    if (options === undefined || !options.method || options.method === 'ITU-R BT.601') {
        rCoeff = 0.3; gCoeff = 0.59; bCoeff = 0.11;
    } else if (options.method === 'ITU-R BT.709') {
        rCoeff = 0.2125; gCoeff = 0.7154; bCoeff = 0.0721;
    }
    var gray = this.r * rCoeff + this.g * gCoeff + this.b * bCoeff;
    return new Color(gray, gray, gray, this.a);
};

Color.prototype.invert = function () {
    return new Color(1 - this.r, 1 - this.g, 1 - this.b, this.a);
};

Color.clone = function (c) {
    if (c === null || c === undefined) {
        return null;
    } else if (typeof c === 'string') {
        return c;
    } else {
        return new Color(c.r, c.g, c.b, c.a);
    }
};

Color.toCSS = function (c) {
    if (c === null) {
        return 'none';
    } else if (c === undefined) {
        return 'black';
    } else if (typeof c === 'string') {
        return c;
    } else if (c instanceof Color) {
        var r255 = Math.round(c.r * 255),
            g255 = Math.round(c.g * 255),
            b255 = Math.round(c.b * 255);
        return 'rgba(' + r255 + ', ' + g255 + ', ' + b255 + ', ' + c.a + ')';
    } else if (c.r !== undefined && c.g !== undefined && c.b !== undefined) {
        if (c.a === undefined) {
            return 'rgb(' + c.r + ', ' + c.g + ', ' + c.b + ')';
        } else {
            return 'rgba(' + c.r + ', ' + c.g + ', ' + c.b + ', ' + c.a + ')';
        }
    } else {
        throw new Error('Don\'t know how to convert ' + c + ' to CSS.');
    }
};

Color.toHex = function (c) {
    return Color.parse(c).toHex();
};

Color.make = function () {
    var c = Object.create(Color.prototype);
    c.constructor = Color.prototype;
    Color.apply(c, arguments);
    return c;
};

Color.parse = function (s) {
    function startsWith (s, value) {
        if (!s || !value) { return false; }
        s = String(s);
        return s.indexOf(value) === 0;
    }

    var m;
    if (s === undefined || s === null) {
        return new Color(0, 0, 0, 0);
    } else if (s instanceof Color) {
        return s;
    } else if (color.namedColors[s]) {
        return Color.make.apply(null, color.namedColors[s]);
    } else if (s[0] === '#') {
        return new Color(s, 0, 0, 0, { mode: HEX });
    } else if (startsWith(s, 'rgba')) {
        m = s.match(/^rgba\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+|\d+.\d+)\s*\)$/i);
        if (m) {
            return new Color(parseInt(m[1]) / 255, parseInt(m[2]) / 255, parseInt(m[3]) / 255, parseFloat(m[4]));
        }
        return new Color(0, 0, 0, 0);
    } else if (startsWith(s, 'rgb')) {
        m = s.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/i);
        if (m) {
            return new Color(parseInt(m[1]) / 255, parseInt(m[2]) / 255, parseInt(m[3]) / 255);
        }
        return new Color(0, 0, 0, 0);
    } else if (startsWith(s, 'hsla')) {
        m = s.match(/^hsla\s*\(\s*(\d+|\d+.\d+)\s*,\s*(\d+|\d+.\d+)%\s*,\s*(\d+|\d+.\d+)%\s*,\s*(\d+|\d+.\d+)\s*\)$/i);
        if (m) {
            return new Color(parseFloat(m[1]) / 360, parseFloat(m[2]) / 100, parseFloat(m[3]) / 100, parseFloat(m[4]));
        }
        return new Color(0, 0, 0, 0);
    } else if (startsWith(s, 'hsl')) {
        m = s.match(/^hsl\s*\(\s*(\d+|\d+.\d+)\s*,\s*(\d+|\d+.\d+)%\s*,\s*(\d+|\d+.\d+)%\s*\)$/i);
        if (m) {
            return new Color(parseFloat(m[1]) / 360, parseFloat(m[2]) / 100, parseFloat(m[3]) / 100);
        }
        return new Color(0, 0, 0, 0);
    } else if (s === 'none') {
        return new Color(0, 0, 0, 0);
    } else {
        throw new Error('Color ' + s + 'can not be parsed');
    }
};

Color.gray = function (gray, alpha, range) {
    range = Math.max(range, 1);
    return new Color(gray / range, gray / range, gray / range, alpha / range);
};

Color.rgb = function (red, green, blue, alpha, range) {
    range = Math.max(range, 1);
    return new Color(red / range, green / range, blue / range, alpha / range);
};

Color.hsb = function (hue, saturation, brightness, alpha, range) {
    range = Math.max(range, 1);
    return new Color(hue / range, saturation / range, brightness / range, alpha / range, { mode: HSB });
};

Color.hsl = function (hue, saturation, lightness, alpha, range) {
    range = Math.max(range, 1);
    return new Color(hue / range, saturation / range, lightness / range, alpha / range, { mode: HSL });
};

module.exports = Color;
<|endoftext|>


<commit_before>// Apply login on current session and change session id for security reasons.

'use strict';

var rnd = require('nodeca.core/lib/rnd');

module.exports = function login(env, userId) {
  env.session.user_id = userId;
  env.origin.req.sid = rnd(); // Generate secure random hex string.
};
<commit_msg>comment update<commit_after>// Apply login on current session and change session id for security reasons.

'use strict';

var rnd = require('nodeca.core/lib/rnd');

module.exports = function login(env, userId) {
  env.session.user_id = userId;
  env.origin.req.sid = rnd(); // Generate cryptostrong random hex string.
};
<|endoftext|>


<commit_before>const Ajv   = require('ajv');
const {Map} = require('immutable');
const is    = require('is_js');

const {randomInt} = require('./random');

class Ratio {
  constructor(param) {
    const mapWithoutUndefined = Ratio.validate(param);
    this.map = Map(mapWithoutUndefined);

    [this.ranges, this.max] = this.map
      .filter((v) => v > 0)
      .reduce(([map, sum], v, k) => {
        const upper = sum + v;
        return [map.set(k, [sum + 1, upper]), upper];
      }, [Map(), 0]);
  }

  sample() {
    const sample = randomInt(1, this.max);
    const key    = this.ranges.findKey(([lower, upper]) => lower <= sample && sample <= upper);
    return is.existy(key) ? key : null;
  }

  static validate(param) {
    const withoutUndefined = is.json(param) ? Map(param).filter(is.not.undefined).toJSON() : param;
    // NOTICE: keys with "undefined" are not ignored!
    const schema = {
      type                : 'object',
      additionalProperties: {type: 'integer'},
    };
    const ajv     = new Ajv();
    const isValid = ajv.validate(schema, withoutUndefined);
    if (!isValid) {
      throw new Error('1st argument{k_1: v_1, ...} must satisfy any v_i is "null" or "integer"');
    }
    return withoutUndefined;
  }
}

module.exports = Ratio;
<commit_msg>Fix error message<commit_after>const Ajv   = require('ajv');
const {Map} = require('immutable');
const is    = require('is_js');

const {randomInt} = require('./random');

class Ratio {
  constructor(param) {
    const mapWithoutUndefined = Ratio.validate(param);
    this.map = Map(mapWithoutUndefined);

    [this.ranges, this.max] = this.map
      .filter((v) => v > 0)
      .reduce(([map, sum], v, k) => {
        const upper = sum + v;
        return [map.set(k, [sum + 1, upper]), upper];
      }, [Map(), 0]);
  }

  sample() {
    const sample = randomInt(1, this.max);
    const key    = this.ranges.findKey(([lower, upper]) => lower <= sample && sample <= upper);
    return is.existy(key) ? key : null;
  }

  static validate(param) {
    const withoutUndefined = is.json(param) ? Map(param).filter(is.not.undefined).toJSON() : param;
    // NOTICE: keys with "undefined" are not ignored!
    const schema = {
      type                : 'object',
      additionalProperties: {type: 'integer'},
    };
    const ajv     = new Ajv();
    const isValid = ajv.validate(schema, withoutUndefined);
    if (!isValid) {
      throw new Error('1st argument{k_1: v_1, ...} must satisfy any v_i is "undefined" or "integer"');
    }
    return withoutUndefined;
  }
}

module.exports = Ratio;
<|endoftext|>


<commit_before>/**
 * @module ol/source/OSM
 */

import XYZ from './XYZ.js';

/**
 * The attribution containing a link to the OpenStreetMap Copyright and License
 * page.
 * @const
 * @type {string}
 * @api
 */
export const ATTRIBUTION = '© ' +
      'OpenStreetMap ' +
      'contributors.';

/**
 * @typedef {Object} Options
 * @property {import("./Source.js").AttributionLike} [attributions] Attributions.
 * @property {number} [cacheSize] Tile cache size. The default depends on the screen size. Will increase if too small.
 * @property {null|string} [crossOrigin] The `crossOrigin` attribute for loaded images.  Note that
 * you must provide a `crossOrigin` value if you want to access pixel data with the Canvas renderer.
 * See https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image for more detail.
 * @property {number} [maxZoom=19] Max zoom.
 * @property {boolean} [opaque=true] Whether the layer is opaque.
 * @property {number} [reprojectionErrorThreshold=1.5] Maximum allowed reprojection error (in pixels).
 * Higher values can increase reprojection performance, but decrease precision.
 * @property {import("../Tile.js").LoadFunction} [tileLoadFunction] Optional function to load a tile given a URL. The default is
 * ```js
 * function(imageTile, src) {
 *   imageTile.getImage().src = src;
 * };
 * ```
 * @property {string} [url='https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'] URL template.
 * Must include `{x}`, `{y}` or `{-y}`, and `{z}` placeholders.
 * @property {boolean} [wrapX=true] Whether to wrap the world horizontally.
 */

/**
 * @classdesc
 * Layer source for the OpenStreetMap tile server.
 * @api
 */
class OSM extends XYZ {
  /**
   * @param {Options=} [opt_options] Open Street Map options.
   */
  constructor(opt_options) {

    const options = opt_options || {};

    let attributions;
    if (options.attributions !== undefined) {
      attributions = options.attributions;
    } else {
      attributions = [ATTRIBUTION];
    }

    const crossOrigin = options.crossOrigin !== undefined ?
      options.crossOrigin : 'anonymous';

    const url = options.url !== undefined ?
      options.url : 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png';

    super({
      attributions: attributions,
      cacheSize: options.cacheSize,
      crossOrigin: crossOrigin,
      opaque: options.opaque !== undefined ? options.opaque : true,
      maxZoom: options.maxZoom !== undefined ? options.maxZoom : 19,
      reprojectionErrorThreshold: options.reprojectionErrorThreshold,
      tileLoadFunction: options.tileLoadFunction,
      url: url,
      wrapX: options.wrapX,
      attributionsCollapsible: false
    });

  }

}

export default OSM;
<commit_msg>Document the OSM crossOrigin default<commit_after>/**
 * @module ol/source/OSM
 */

import XYZ from './XYZ.js';

/**
 * The attribution containing a link to the OpenStreetMap Copyright and License
 * page.
 * @const
 * @type {string}
 * @api
 */
export const ATTRIBUTION = '© ' +
      'OpenStreetMap ' +
      'contributors.';

/**
 * @typedef {Object} Options
 * @property {import("./Source.js").AttributionLike} [attributions] Attributions.
 * @property {number} [cacheSize] Tile cache size. The default depends on the screen size. Will increase if too small.
 * @property {null|string} [crossOrigin='anonymous'] The `crossOrigin` attribute for loaded images.  Note that
 * you must provide a `crossOrigin` value if you want to access pixel data with the Canvas renderer.
 * See https://developer.mozilla.org/en-US/docs/Web/HTML/CORS_enabled_image for more detail.
 * @property {number} [maxZoom=19] Max zoom.
 * @property {boolean} [opaque=true] Whether the layer is opaque.
 * @property {number} [reprojectionErrorThreshold=1.5] Maximum allowed reprojection error (in pixels).
 * Higher values can increase reprojection performance, but decrease precision.
 * @property {import("../Tile.js").LoadFunction} [tileLoadFunction] Optional function to load a tile given a URL. The default is
 * ```js
 * function(imageTile, src) {
 *   imageTile.getImage().src = src;
 * };
 * ```
 * @property {string} [url='https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png'] URL template.
 * Must include `{x}`, `{y}` or `{-y}`, and `{z}` placeholders.
 * @property {boolean} [wrapX=true] Whether to wrap the world horizontally.
 */

/**
 * @classdesc
 * Layer source for the OpenStreetMap tile server.
 * @api
 */
class OSM extends XYZ {
  /**
   * @param {Options=} [opt_options] Open Street Map options.
   */
  constructor(opt_options) {

    const options = opt_options || {};

    let attributions;
    if (options.attributions !== undefined) {
      attributions = options.attributions;
    } else {
      attributions = [ATTRIBUTION];
    }

    const crossOrigin = options.crossOrigin !== undefined ?
      options.crossOrigin : 'anonymous';

    const url = options.url !== undefined ?
      options.url : 'https://{a-c}.tile.openstreetmap.org/{z}/{x}/{y}.png';

    super({
      attributions: attributions,
      cacheSize: options.cacheSize,
      crossOrigin: crossOrigin,
      opaque: options.opaque !== undefined ? options.opaque : true,
      maxZoom: options.maxZoom !== undefined ? options.maxZoom : 19,
      reprojectionErrorThreshold: options.reprojectionErrorThreshold,
      tileLoadFunction: options.tileLoadFunction,
      url: url,
      wrapX: options.wrapX,
      attributionsCollapsible: false
    });

  }

}

export default OSM;
<|endoftext|>