tracker-group.js 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. 'use strict'
  2. var util = require('util')
  3. var TrackerBase = require('./tracker-base.js')
  4. var Tracker = require('./tracker.js')
  5. var TrackerStream = require('./tracker-stream.js')
  6. var TrackerGroup = module.exports = function (name) {
  7. TrackerBase.call(this, name)
  8. this.parentGroup = null
  9. this.trackers = []
  10. this.completion = {}
  11. this.weight = {}
  12. this.totalWeight = 0
  13. this.finished = false
  14. this.bubbleChange = bubbleChange(this)
  15. }
  16. util.inherits(TrackerGroup, TrackerBase)
  17. function bubbleChange (trackerGroup) {
  18. return function (name, completed, tracker) {
  19. trackerGroup.completion[tracker.id] = completed
  20. if (trackerGroup.finished) {
  21. return
  22. }
  23. trackerGroup.emit('change', name || trackerGroup.name, trackerGroup.completed(), trackerGroup)
  24. }
  25. }
  26. TrackerGroup.prototype.nameInTree = function () {
  27. var names = []
  28. var from = this
  29. while (from) {
  30. names.unshift(from.name)
  31. from = from.parentGroup
  32. }
  33. return names.join('/')
  34. }
  35. TrackerGroup.prototype.addUnit = function (unit, weight) {
  36. if (unit.addUnit) {
  37. var toTest = this
  38. while (toTest) {
  39. if (unit === toTest) {
  40. throw new Error(
  41. 'Attempted to add tracker group ' +
  42. unit.name + ' to tree that already includes it ' +
  43. this.nameInTree(this))
  44. }
  45. toTest = toTest.parentGroup
  46. }
  47. unit.parentGroup = this
  48. }
  49. this.weight[unit.id] = weight || 1
  50. this.totalWeight += this.weight[unit.id]
  51. this.trackers.push(unit)
  52. this.completion[unit.id] = unit.completed()
  53. unit.on('change', this.bubbleChange)
  54. if (!this.finished) {
  55. this.emit('change', unit.name, this.completion[unit.id], unit)
  56. }
  57. return unit
  58. }
  59. TrackerGroup.prototype.completed = function () {
  60. if (this.trackers.length === 0) {
  61. return 0
  62. }
  63. var valPerWeight = 1 / this.totalWeight
  64. var completed = 0
  65. for (var ii = 0; ii < this.trackers.length; ii++) {
  66. var trackerId = this.trackers[ii].id
  67. completed +=
  68. valPerWeight * this.weight[trackerId] * this.completion[trackerId]
  69. }
  70. return completed
  71. }
  72. TrackerGroup.prototype.newGroup = function (name, weight) {
  73. return this.addUnit(new TrackerGroup(name), weight)
  74. }
  75. TrackerGroup.prototype.newItem = function (name, todo, weight) {
  76. return this.addUnit(new Tracker(name, todo), weight)
  77. }
  78. TrackerGroup.prototype.newStream = function (name, todo, weight) {
  79. return this.addUnit(new TrackerStream(name, todo), weight)
  80. }
  81. TrackerGroup.prototype.finish = function () {
  82. this.finished = true
  83. if (!this.trackers.length) {
  84. this.addUnit(new Tracker(), 1, true)
  85. }
  86. for (var ii = 0; ii < this.trackers.length; ii++) {
  87. var tracker = this.trackers[ii]
  88. tracker.finish()
  89. tracker.removeListener('change', this.bubbleChange)
  90. }
  91. this.emit('change', this.name, 1, this)
  92. }
  93. var buffer = ' '
  94. TrackerGroup.prototype.debug = function (depth) {
  95. depth = depth || 0
  96. var indent = depth ? buffer.substr(0, depth) : ''
  97. var output = indent + (this.name || 'top') + ': ' + this.completed() + '\n'
  98. this.trackers.forEach(function (tracker) {
  99. if (tracker instanceof TrackerGroup) {
  100. output += tracker.debug(depth + 1)
  101. } else {
  102. output += indent + ' ' + tracker.name + ': ' + tracker.completed() + '\n'
  103. }
  104. })
  105. return output
  106. }