func bytesPerSecController(bytesPerSecCh <-chan bytesPerSecMsg, bytesPerSecDisplayCh chan<- string) {

	bytesRecdForSecond := rb.MakeNew(INFO)
	durationForSecond := rb.MakeNew(INFO)
	lookbackSecs := 5

	timeToRedraw := make(chan bool)
	go func(timeToRedraw chan bool) {
		for {
			time.Sleep(1000 * time.Millisecond)
			timeToRedraw <- true
		}
	}(timeToRedraw)

	for {
		select {
		case msg := <-bytesPerSecCh:
			bytesRecdForSecond.IncrementAtBy(msg.receivedOnSec, msg.bytes)
			durationForSecond.IncrementAtBy(msg.receivedOnSec, int64(msg.duration))
		case <-timeToRedraw:
			windowDur := durationForSecond.SumPrevN(lookbackSecs)
			windowBytes := bytesRecdForSecond.SumPrevN(lookbackSecs)
			// divide-by-zero guard
			if windowDur == 0 {
				windowDur = 1
			}
			bytesPerSecDisplayCh <- fmt.Sprintf("%10.2f", float64(windowBytes)/float64(windowDur)*1000)
		}

	}
}
// This sends messages to both the barsToDrawCh and the durationDisplayCh--
// so should I rename this method?
func barsController(
	reqMadeOnSecListenerCh <-chan interface{},
	failsOnSecCh <-chan int,
	barsToDrawCh chan<- currentBars,
	reqSecDisplayCh chan<- string,
) {
	requestsForSecond := rb.MakeNew(INFO) // one column for each clock second
	failsForSecond := rb.MakeNew(INFO)    // one column for each clock second

	secsSeen := 0

	timeToRedraw := make(chan bool)
	go func(timeToRedraw chan bool) {
		for {
			time.Sleep(1000 * time.Millisecond)
			timeToRedraw <- true
			if secsSeen <= 60 {
				secsSeen++
			}
		}
	}(timeToRedraw)

	for {
		select {
		case msg := <-reqMadeOnSecListenerCh:
			second := msg.(int)
			requestsForSecond.IncrementAt(second)
		case second := <-failsOnSecCh:
			failsForSecond.IncrementAt(second)
		case <-timeToRedraw:
			barsToDrawCh <- currentBars{
				requestsForSecond.GetArray(),
				failsForSecond.GetArray(),
				requestsForSecond.GetMax(),
			}
			reqSecDisplayCh <- fmt.Sprintf("%d/%2.2d/%2.2d",
				requestsForSecond.GetPrevVal(),
				// won't be accurate for first five secs
				requestsForSecond.SumPrevN(5)/5,
				requestsForSecond.SumPrevN(secsSeen)/
					int64(secsSeen),
			)
		}
	}
}
func durationWinController(
	durationCh <-chan int64,
	durationDisplayCh chan<- string,
) {
	totalDurForSecond := rb.MakeNew(INFO) // total durations for each clock second
	countForSecond := rb.MakeNew(INFO)    // how many received per second
	lookbackSecs := 5
	//	secsSeen := 0

	timeToRedraw := make(chan bool)
	go func(timeToRedraw chan bool) {
		for {
			time.Sleep(1000 * time.Millisecond)
			timeToRedraw <- true
		}
	}(timeToRedraw)

	for {
		select {
		case dur := <-durationCh:
			totalDurForSecond.ChangeHeadBy(dur)
			countForSecond.IncrementHead()
		case <-timeToRedraw:

			windowDur := totalDurForSecond.SumPrevN(lookbackSecs)
			windowCount := countForSecond.SumPrevN(lookbackSecs)

			if windowCount > 0 {
				avgDur := float64(windowDur) / float64(windowCount)
				durationDisplayCh <- fmt.Sprintf("%11.2f\n (avg last %d)", avgDur, lookbackSecs)
			} else {
				durationDisplayCh <- "0"
			}
		}
	}
}