| 28 | 28 |
lastState state
|
| 29 | 29 |
}
|
| 30 | 30 |
|
| 31 | |
// Statistics represents statistics of the progress bar
|
| 32 | |
// instance of this, sent to DecoratorFunc, as param
|
|
31 |
// Statistics represents statistics of the progress bar.
|
|
32 |
// Cantains: Total, Current, TimeElapsed, TimePerItemEstimate
|
| 33 | 33 |
type Statistics struct {
|
| 34 | 34 |
Total, Current int64
|
| 35 | |
TermWidth int
|
| 36 | 35 |
TimeElapsed, TimePerItemEstimate time.Duration
|
| 37 | 36 |
}
|
| 38 | 37 |
|
|
38 |
// Eta returns exponential-weighted-moving-average ETA estimator
|
| 39 | 39 |
func (s *Statistics) Eta() time.Duration {
|
| 40 | 40 |
return time.Duration(s.Total-s.Current) * s.TimePerItemEstimate
|
| 41 | 41 |
}
|
|
| 200 | 200 |
b.refillCh <- &refill{c, int64(n)}
|
| 201 | 201 |
}
|
| 202 | 202 |
|
| 203 | |
// Current returns the actual current.
|
| 204 | |
func (b *Bar) Current() int64 {
|
| 205 | |
if IsClosed(b.done) {
|
| 206 | |
return b.lastState.current
|
| 207 | |
}
|
| 208 | |
ch := make(chan state, 1)
|
| 209 | |
b.stateReqCh <- ch
|
| 210 | |
state := <-ch
|
| 211 | |
return state.current
|
|
203 |
// GetAppenders returns slice of appender DecoratorFunc
|
|
204 |
func (b *Bar) GetAppenders() []DecoratorFunc {
|
|
205 |
s := b.getState()
|
|
206 |
return s.appendFuncs
|
|
207 |
}
|
|
208 |
|
|
209 |
// GetAppenders returns slice of prepender DecoratorFunc
|
|
210 |
func (b *Bar) GetPrependers() []DecoratorFunc {
|
|
211 |
s := b.getState()
|
|
212 |
return s.prependFuncs
|
|
213 |
}
|
|
214 |
|
|
215 |
// GetStatistics returs *Statistics, which contains information like Tottal,
|
|
216 |
// Current, TimeElapsed and TimePerItemEstimate
|
|
217 |
func (b *Bar) GetStatistics() *Statistics {
|
|
218 |
state := b.getState()
|
|
219 |
return state.newStat()
|
| 212 | 220 |
}
|
| 213 | 221 |
|
| 214 | 222 |
// InProgress returns true, while progress is running
|
|
| 261 | 269 |
b.completeReqCh <- struct{}{}
|
| 262 | 270 |
}
|
| 263 | 271 |
|
| 264 | |
func (b *Bar) bytes(termWidth int) []byte {
|
| 265 | |
if IsClosed(b.done) {
|
| 266 | |
return b.lastState.draw(termWidth)
|
|
272 |
func (b *Bar) getState() state {
|
|
273 |
if IsClosed(b.done) {
|
|
274 |
return b.lastState
|
| 267 | 275 |
}
|
| 268 | 276 |
ch := make(chan state, 1)
|
| 269 | 277 |
b.stateReqCh <- ch
|
| 270 | |
s := <-ch
|
| 271 | |
return s.draw(termWidth)
|
|
278 |
return <-ch
|
|
279 |
}
|
|
280 |
|
|
281 |
func (b *Bar) bytes(termWidth int) []byte {
|
|
282 |
state := b.getState()
|
|
283 |
return state.draw(termWidth)
|
| 272 | 284 |
}
|
| 273 | 285 |
|
| 274 | 286 |
func (b *Bar) server(ctx context.Context, wg *sync.WaitGroup, total int64, barWidth int) {
|
|
| 364 | 376 |
b.removeReqCh <- struct{}{}
|
| 365 | 377 |
}
|
| 366 | 378 |
|
|
379 |
func (s *state) newStat() *Statistics {
|
|
380 |
return &Statistics{
|
|
381 |
Total: s.total,
|
|
382 |
Current: s.current,
|
|
383 |
TimeElapsed: s.timeElapsed,
|
|
384 |
TimePerItemEstimate: s.timePerItem,
|
|
385 |
}
|
|
386 |
}
|
|
387 |
|
| 367 | 388 |
func (s *state) draw(termWidth int) []byte {
|
| 368 | 389 |
if termWidth <= 0 {
|
| 369 | 390 |
termWidth = s.barWidth
|
| 370 | 391 |
}
|
| 371 | |
stat := &Statistics{
|
| 372 | |
Total: s.total,
|
| 373 | |
Current: s.current,
|
| 374 | |
TermWidth: termWidth,
|
| 375 | |
TimeElapsed: s.timeElapsed,
|
| 376 | |
TimePerItemEstimate: s.timePerItem,
|
| 377 | |
}
|
|
392 |
|
|
393 |
stat := s.newStat()
|
| 378 | 394 |
|
| 379 | 395 |
// render append functions to the right of the bar
|
| 380 | 396 |
var appendBlock []byte
|
|
| 458 | 474 |
return buf
|
| 459 | 475 |
}
|
| 460 | 476 |
|
| 461 | |
func (b *Bar) status() int {
|
| 462 | |
var total, current int64
|
| 463 | |
if IsClosed(b.done) {
|
| 464 | |
total = b.lastState.total
|
| 465 | |
current = b.lastState.current
|
| 466 | |
} else {
|
| 467 | |
ch := make(chan state, 1)
|
| 468 | |
b.stateReqCh <- ch
|
| 469 | |
state := <-ch
|
| 470 | |
total = state.total
|
| 471 | |
current = state.current
|
| 472 | |
}
|
| 473 | |
return percentage(total, current, 100)
|
| 474 | |
}
|
| 475 | |
|
| 476 | |
// SortableBarSlice satisfies sort interface
|
| 477 | |
type SortableBarSlice []*Bar
|
| 478 | |
|
| 479 | |
func (p SortableBarSlice) Len() int { return len(p) }
|
| 480 | |
|
| 481 | |
func (p SortableBarSlice) Less(i, j int) bool { return p[i].status() < p[j].status() }
|
| 482 | |
|
| 483 | |
func (p SortableBarSlice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
| 484 | |
|
| 485 | 477 |
func calcTimePerItemEstimate(tpie time.Duration, blockStartTime time.Time, alpha float64, items int64) time.Duration {
|
| 486 | 478 |
lastBlockTime := time.Since(blockStartTime)
|
| 487 | 479 |
lastItemEstimate := float64(lastBlockTime) / float64(items)
|