(function () {

/* Imports */
var Meteor = Package.meteor.Meteor;
var _ = Package.underscore._;
var IdMap = Package['id-map'].IdMap;

/* Package-scope variables */
var MaxHeap, MinHeap, MinMaxHeap;

(function(){

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                    //
// packages/binary-heap/max-heap.js                                                   //
//                                                                                    //
////////////////////////////////////////////////////////////////////////////////////////
                                                                                      //
// Constructor of Heap                                                                // 1
// - comparator - Function - given two items returns a number                         // 2
// - options:                                                                         // 3
//   - initData - Array - Optional - the initial data in a format:                    // 4
//        Object:                                                                     // 5
//          - id - String - unique id of the item                                     // 6
//          - value - Any - the data value                                            // 7
//      each value is retained                                                        // 8
//   - IdMap - Constructor - Optional - custom IdMap class to store id->index         // 9
//       mappings internally. Standard IdMap is used by default.                      // 10
MaxHeap = function (comparator, options) {                                            // 11
  if (! _.isFunction(comparator))                                                     // 12
    throw new Error('Passed comparator is invalid, should be a comparison function');
  var self = this;                                                                    // 14
                                                                                      // 15
  // a C-style comparator that is given two values and returns a number,              // 16
  // negative if the first value is less than the second, positive if the second      // 17
  // value is greater than the first and zero if they are equal.                      // 18
  self._comparator = comparator;                                                      // 19
                                                                                      // 20
  options = _.defaults(options || {}, { IdMap: IdMap });                              // 21
                                                                                      // 22
  // _heapIdx maps an id to an index in the Heap array the corresponding value        // 23
  // is located on.                                                                   // 24
  self._heapIdx = new options.IdMap;                                                  // 25
                                                                                      // 26
  // The Heap data-structure implemented as a 0-based contiguous array where          // 27
  // every item on index idx is a node in a complete binary tree. Every node can      // 28
  // have children on indexes idx*2+1 and idx*2+2, except for the leaves. Every       // 29
  // node has a parent on index (idx-1)/2;                                            // 30
  self._heap = [];                                                                    // 31
                                                                                      // 32
  // If the initial array is passed, we can build the heap in linear time             // 33
  // complexity (O(N)) compared to linearithmic time complexity (O(nlogn)) if         // 34
  // we push elements one by one.                                                     // 35
  if (_.isArray(options.initData))                                                    // 36
    self._initFromData(options.initData);                                             // 37
};                                                                                    // 38
                                                                                      // 39
_.extend(MaxHeap.prototype, {                                                         // 40
  // Builds a new heap in-place in linear time based on passed data                   // 41
  _initFromData: function (data) {                                                    // 42
    var self = this;                                                                  // 43
                                                                                      // 44
    self._heap = _.map(data, function (o) {                                           // 45
      return { id: o.id, value: o.value };                                            // 46
    });                                                                               // 47
                                                                                      // 48
    _.each(data, function (o, i) {                                                    // 49
      self._heapIdx.set(o.id, i);                                                     // 50
    });                                                                               // 51
                                                                                      // 52
    if (! data.length)                                                                // 53
      return;                                                                         // 54
                                                                                      // 55
    // start from the first non-leaf - the parent of the last leaf                    // 56
    for (var i = parentIdx(data.length - 1); i >= 0; i--)                             // 57
      self._downHeap(i);                                                              // 58
  },                                                                                  // 59
                                                                                      // 60
  _downHeap: function (idx) {                                                         // 61
    var self = this;                                                                  // 62
                                                                                      // 63
    while (leftChildIdx(idx) < self.size()) {                                         // 64
      var left = leftChildIdx(idx);                                                   // 65
      var right = rightChildIdx(idx);                                                 // 66
      var largest = idx;                                                              // 67
                                                                                      // 68
      if (left < self.size()) {                                                       // 69
        largest = self._maxIndex(largest, left);                                      // 70
      }                                                                               // 71
      if (right < self.size()) {                                                      // 72
        largest = self._maxIndex(largest, right);                                     // 73
      }                                                                               // 74
                                                                                      // 75
      if (largest === idx)                                                            // 76
        break;                                                                        // 77
                                                                                      // 78
      self._swap(largest, idx);                                                       // 79
      idx = largest;                                                                  // 80
    }                                                                                 // 81
  },                                                                                  // 82
                                                                                      // 83
  _upHeap: function (idx) {                                                           // 84
    var self = this;                                                                  // 85
                                                                                      // 86
    while (idx > 0) {                                                                 // 87
      var parent = parentIdx(idx);                                                    // 88
      if (self._maxIndex(parent, idx) === idx) {                                      // 89
        self._swap(parent, idx)                                                       // 90
        idx = parent;                                                                 // 91
      } else {                                                                        // 92
        break;                                                                        // 93
      }                                                                               // 94
    }                                                                                 // 95
  },                                                                                  // 96
                                                                                      // 97
  _maxIndex: function (idxA, idxB) {                                                  // 98
    var self = this;                                                                  // 99
    var valueA = self._get(idxA);                                                     // 100
    var valueB = self._get(idxB);                                                     // 101
    return self._comparator(valueA, valueB) >= 0 ? idxA : idxB;                       // 102
  },                                                                                  // 103
                                                                                      // 104
  // Internal: gets raw data object placed on idxth place in heap                     // 105
  _get: function (idx) {                                                              // 106
    var self = this;                                                                  // 107
    return self._heap[idx].value;                                                     // 108
  },                                                                                  // 109
                                                                                      // 110
  _swap: function (idxA, idxB) {                                                      // 111
    var self = this;                                                                  // 112
    var recA = self._heap[idxA];                                                      // 113
    var recB = self._heap[idxB];                                                      // 114
                                                                                      // 115
    self._heapIdx.set(recA.id, idxB);                                                 // 116
    self._heapIdx.set(recB.id, idxA);                                                 // 117
                                                                                      // 118
    self._heap[idxA] = recB;                                                          // 119
    self._heap[idxB] = recA;                                                          // 120
  },                                                                                  // 121
                                                                                      // 122
  get: function (id) {                                                                // 123
    var self = this;                                                                  // 124
    if (! self.has(id))                                                               // 125
      return null;                                                                    // 126
    return self._get(self._heapIdx.get(id));                                          // 127
  },                                                                                  // 128
  set: function (id, value) {                                                         // 129
    var self = this;                                                                  // 130
                                                                                      // 131
    if (self.has(id)) {                                                               // 132
      if (self.get(id) === value)                                                     // 133
        return;                                                                       // 134
                                                                                      // 135
      var idx = self._heapIdx.get(id);                                                // 136
      self._heap[idx].value = value;                                                  // 137
                                                                                      // 138
      // Fix the new value's position                                                 // 139
      // Either bubble new value up if it is greater than its parent                  // 140
      self._upHeap(idx);                                                              // 141
      // or bubble it down if it is smaller than one of its children                  // 142
      self._downHeap(idx);                                                            // 143
    } else {                                                                          // 144
      self._heapIdx.set(id, self._heap.length);                                       // 145
      self._heap.push({ id: id, value: value });                                      // 146
      self._upHeap(self._heap.length - 1);                                            // 147
    }                                                                                 // 148
  },                                                                                  // 149
  remove: function (id) {                                                             // 150
    var self = this;                                                                  // 151
                                                                                      // 152
    if (self.has(id)) {                                                               // 153
      var last = self._heap.length - 1;                                               // 154
      var idx = self._heapIdx.get(id);                                                // 155
                                                                                      // 156
      if (idx !== last) {                                                             // 157
        self._swap(idx, last);                                                        // 158
        self._heap.pop();                                                             // 159
        self._heapIdx.remove(id);                                                     // 160
                                                                                      // 161
        // Fix the swapped value's position                                           // 162
        self._upHeap(idx);                                                            // 163
        self._downHeap(idx);                                                          // 164
      } else {                                                                        // 165
        self._heap.pop();                                                             // 166
        self._heapIdx.remove(id);                                                     // 167
      }                                                                               // 168
    }                                                                                 // 169
  },                                                                                  // 170
  has: function (id) {                                                                // 171
    var self = this;                                                                  // 172
    return self._heapIdx.has(id);                                                     // 173
  },                                                                                  // 174
  empty: function () {                                                                // 175
    var self = this;                                                                  // 176
    return !self.size();                                                              // 177
  },                                                                                  // 178
  clear: function () {                                                                // 179
    var self = this;                                                                  // 180
    self._heap = [];                                                                  // 181
    self._heapIdx.clear();                                                            // 182
  },                                                                                  // 183
  // iterate over values in no particular order                                       // 184
  forEach: function (iterator) {                                                      // 185
    var self = this;                                                                  // 186
    _.each(self._heap, function (obj) {                                               // 187
      return iterator(obj.value, obj.id);                                             // 188
    });                                                                               // 189
  },                                                                                  // 190
  size: function () {                                                                 // 191
    var self = this;                                                                  // 192
    return self._heap.length;                                                         // 193
  },                                                                                  // 194
  setDefault: function (id, def) {                                                    // 195
    var self = this;                                                                  // 196
    if (self.has(id))                                                                 // 197
      return self.get(id);                                                            // 198
    self.set(id, def);                                                                // 199
    return def;                                                                       // 200
  },                                                                                  // 201
  clone: function () {                                                                // 202
    var self = this;                                                                  // 203
    var clone = new MaxHeap(self._comparator, self._heap);                            // 204
    return clone;                                                                     // 205
  },                                                                                  // 206
                                                                                      // 207
  maxElementId: function () {                                                         // 208
    var self = this;                                                                  // 209
    return self.size() ? self._heap[0].id : null;                                     // 210
  },                                                                                  // 211
                                                                                      // 212
  _selfCheck: function () {                                                           // 213
    var self = this;                                                                  // 214
    for (var i = 1; i < self._heap.length; i++)                                       // 215
      if (self._maxIndex(parentIdx(i), i) !== parentIdx(i))                           // 216
          throw new Error("An item with id " + self._heap[i].id +                     // 217
                          " has a parent younger than it: " +                         // 218
                          self._heap[parentIdx(i)].id);                               // 219
  }                                                                                   // 220
});                                                                                   // 221
                                                                                      // 222
function leftChildIdx (i) { return i * 2 + 1; }                                       // 223
function rightChildIdx (i) { return i * 2 + 2; }                                      // 224
function parentIdx (i) { return (i - 1) >> 1; }                                       // 225
                                                                                      // 226
                                                                                      // 227
////////////////////////////////////////////////////////////////////////////////////////

}).call(this);






(function(){

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                    //
// packages/binary-heap/min-heap.js                                                   //
//                                                                                    //
////////////////////////////////////////////////////////////////////////////////////////
                                                                                      //
MinHeap = function (comparator, options) {                                            // 1
  var self = this;                                                                    // 2
  MaxHeap.call(self, function (a, b) {                                                // 3
    return -comparator(a, b);                                                         // 4
  }, options);                                                                        // 5
};                                                                                    // 6
                                                                                      // 7
Meteor._inherits(MinHeap, MaxHeap);                                                   // 8
                                                                                      // 9
_.extend(MinHeap.prototype, {                                                         // 10
  maxElementId: function () {                                                         // 11
    throw new Error("Cannot call maxElementId on MinHeap");                           // 12
  },                                                                                  // 13
  minElementId: function () {                                                         // 14
    var self = this;                                                                  // 15
    return MaxHeap.prototype.maxElementId.call(self);                                 // 16
  }                                                                                   // 17
});                                                                                   // 18
                                                                                      // 19
                                                                                      // 20
////////////////////////////////////////////////////////////////////////////////////////

}).call(this);






(function(){

////////////////////////////////////////////////////////////////////////////////////////
//                                                                                    //
// packages/binary-heap/min-max-heap.js                                               //
//                                                                                    //
////////////////////////////////////////////////////////////////////////////////////////
                                                                                      //
// This implementation of Min/Max-Heap is just a subclass of Max-Heap                 // 1
// with a Min-Heap as an encapsulated property.                                       // 2
//                                                                                    // 3
// Most of the operations are just proxy methods to call the same method on both      // 4
// heaps.                                                                             // 5
//                                                                                    // 6
// This implementation takes 2*N memory but is fairly simple to write and             // 7
// understand. And the constant factor of a simple Heap is usually smaller            // 8
// compared to other two-way priority queues like Min/Max Heaps                       // 9
// (http://www.cs.otago.ac.nz/staffpriv/mike/Papers/MinMaxHeaps/MinMaxHeaps.pdf)      // 10
// and Interval Heaps                                                                 // 11
// (http://www.cise.ufl.edu/~sahni/dsaac/enrich/c13/double.htm)                       // 12
MinMaxHeap = function (comparator, options) {                                         // 13
  var self = this;                                                                    // 14
                                                                                      // 15
  MaxHeap.call(self, comparator, options);                                            // 16
  self._minHeap = new MinHeap(comparator, options);                                   // 17
};                                                                                    // 18
                                                                                      // 19
Meteor._inherits(MinMaxHeap, MaxHeap);                                                // 20
                                                                                      // 21
_.extend(MinMaxHeap.prototype, {                                                      // 22
  set: function (id, value) {                                                         // 23
    var self = this;                                                                  // 24
    MaxHeap.prototype.set.apply(self, arguments);                                     // 25
    self._minHeap.set(id, value);                                                     // 26
  },                                                                                  // 27
  remove: function (id) {                                                             // 28
    var self = this;                                                                  // 29
    MaxHeap.prototype.remove.apply(self, arguments);                                  // 30
    self._minHeap.remove(id);                                                         // 31
  },                                                                                  // 32
  clear: function () {                                                                // 33
    var self = this;                                                                  // 34
    MaxHeap.prototype.clear.apply(self, arguments);                                   // 35
    self._minHeap.clear();                                                            // 36
  },                                                                                  // 37
  setDefault: function (id, def) {                                                    // 38
    var self = this;                                                                  // 39
    MaxHeap.prototype.setDefault.apply(self, arguments);                              // 40
    return self._minHeap.setDefault(id, def);                                         // 41
  },                                                                                  // 42
  clone: function () {                                                                // 43
    var self = this;                                                                  // 44
    var clone = new MinMaxHeap(self._comparator, self._heap);                         // 45
    return clone;                                                                     // 46
  },                                                                                  // 47
  minElementId: function () {                                                         // 48
    var self = this;                                                                  // 49
    return self._minHeap.minElementId();                                              // 50
  }                                                                                   // 51
});                                                                                   // 52
                                                                                      // 53
                                                                                      // 54
////////////////////////////////////////////////////////////////////////////////////////

}).call(this);


/* Exports */
if (typeof Package === 'undefined') Package = {};
Package['binary-heap'] = {
  MaxHeap: MaxHeap,
  MinHeap: MinHeap,
  MinMaxHeap: MinMaxHeap
};

})();

//# sourceMappingURL=binary-heap.js.map
