| 'use strict' |
| var util = require('util') |
| var TrackerBase = require('./tracker-base.js') |
| var Tracker = require('./tracker.js') |
| var TrackerStream = require('./tracker-stream.js') |
| |
| var TrackerGroup = module.exports = function (name) { |
| TrackerBase.call(this, name) |
| this.parentGroup = null |
| this.trackers = [] |
| this.completion = {} |
| this.weight = {} |
| this.totalWeight = 0 |
| this.finished = false |
| this.bubbleChange = bubbleChange(this) |
| } |
| util.inherits(TrackerGroup, TrackerBase) |
| |
| function bubbleChange (trackerGroup) { |
| return function (name, completed, tracker) { |
| trackerGroup.completion[tracker.id] = completed |
| if (trackerGroup.finished) return |
| trackerGroup.emit('change', name || trackerGroup.name, trackerGroup.completed(), trackerGroup) |
| } |
| } |
| |
| TrackerGroup.prototype.nameInTree = function () { |
| var names = [] |
| var from = this |
| while (from) { |
| names.unshift(from.name) |
| from = from.parentGroup |
| } |
| return names.join('/') |
| } |
| |
| TrackerGroup.prototype.addUnit = function (unit, weight) { |
| if (unit.addUnit) { |
| var toTest = this |
| while (toTest) { |
| if (unit === toTest) { |
| throw new Error( |
| 'Attempted to add tracker group ' + |
| unit.name + ' to tree that already includes it ' + |
| this.nameInTree(this)) |
| } |
| toTest = toTest.parentGroup |
| } |
| unit.parentGroup = this |
| } |
| this.weight[unit.id] = weight || 1 |
| this.totalWeight += this.weight[unit.id] |
| this.trackers.push(unit) |
| this.completion[unit.id] = unit.completed() |
| unit.on('change', this.bubbleChange) |
| if (!this.finished) this.emit('change', unit.name, this.completion[unit.id], unit) |
| return unit |
| } |
| |
| TrackerGroup.prototype.completed = function () { |
| if (this.trackers.length === 0) return 0 |
| var valPerWeight = 1 / this.totalWeight |
| var completed = 0 |
| for (var ii = 0; ii < this.trackers.length; ii++) { |
| var trackerId = this.trackers[ii].id |
| completed += valPerWeight * this.weight[trackerId] * this.completion[trackerId] |
| } |
| return completed |
| } |
| |
| TrackerGroup.prototype.newGroup = function (name, weight) { |
| return this.addUnit(new TrackerGroup(name), weight) |
| } |
| |
| TrackerGroup.prototype.newItem = function (name, todo, weight) { |
| return this.addUnit(new Tracker(name, todo), weight) |
| } |
| |
| TrackerGroup.prototype.newStream = function (name, todo, weight) { |
| return this.addUnit(new TrackerStream(name, todo), weight) |
| } |
| |
| TrackerGroup.prototype.finish = function () { |
| this.finished = true |
| if (!this.trackers.length) this.addUnit(new Tracker(), 1, true) |
| for (var ii = 0; ii < this.trackers.length; ii++) { |
| var tracker = this.trackers[ii] |
| tracker.finish() |
| tracker.removeListener('change', this.bubbleChange) |
| } |
| this.emit('change', this.name, 1, this) |
| } |
| |
| var buffer = ' ' |
| TrackerGroup.prototype.debug = function (depth) { |
| depth = depth || 0 |
| var indent = depth ? buffer.substr(0, depth) : '' |
| var output = indent + (this.name || 'top') + ': ' + this.completed() + '\n' |
| this.trackers.forEach(function (tracker) { |
| if (tracker instanceof TrackerGroup) { |
| output += tracker.debug(depth + 1) |
| } else { |
| output += indent + ' ' + tracker.name + ': ' + tracker.completed() + '\n' |
| } |
| }) |
| return output |
| } |