lib/tty/progressbar/meter.rb
# frozen_string_literal: true
module TTY
class ProgressBar
# Used by {ProgressBar} to measure progress rate per interval
# by default 1s
#
# @api private
class Meter
# Create Meter
#
# @param [Integer] interval
# the interval for measurement samples
#
# @api private
def initialize(interval)
@interval = interval || 1 # 1 sec
start
end
# Start sampling timer
#
# @api public
def start
@start_time = Time.now
@current = 0
@samples = [[@start_time, 0]]
@rates = []
@start_time
end
# Update meter with value
#
# @param [Time] at
# the time of the sampling
#
# @param [Integer] value
# the current value of progress
#
# @api public
def sample(at, value)
@current += value
prune_samples(at)
@samples << [at, @current]
save_rate(at)
end
# Remove samples that are obsolete
#
# @api private
def prune_samples(at)
cutoff = at - @interval
while @samples.size > 1 && (@samples.first.first < cutoff)
@samples.shift
end
end
# If we crossed a period boundary since @start_time,
# save the rate for {#rates}
#
# @api private
def save_rate(at)
period_index = ((at - @start_time) / @interval).floor
while period_index > @rates.size
@rates << rate
end
end
# The current rate of sampling for a given interval
#
# @return [Number]
# the current rate in decimal or 0 if cannot be determined
#
# @api public
def rate
first_at, first_value = @samples.first
last_at, last_value = @samples.last
if first_at == last_at
0
else
(last_value - first_value) / (last_at - first_at)
end
end
# Group all rates per interval
#
# @api public
def rates
@rates + [rate]
end
# The mean rate of all the sampled rates
#
# @return [Number]
# the mean rate
#
# @api public
def mean_rate
last_at, last_value = @samples.last
if last_at == @start_time
0
else
last_value / (last_at - @start_time)
end
end
alias avg_rate mean_rate
# Reset the meter by clearing out it's metrics
#
# @api public
def clear
start
end
end # Meter
end # ProgressBar
end # TTY