Skip to content

Instantly share code, notes, and snippets.

@perplexes
Created June 22, 2011 21:17
Show Gist options
  • Select an option

  • Save perplexes/1041238 to your computer and use it in GitHub Desktop.

Select an option

Save perplexes/1041238 to your computer and use it in GitHub Desktop.
A progress counter and estimator.
class Progress
SECOND = 1
MINUTE = SECOND * 60
HOUR = MINUTE * 60
DAY = HOUR * 24
CONV = [DAY, HOUR, MINUTE, SECOND]
NAMES = %w(days hours minutes seconds)
attr_accessor :total, :current
def initialize(total, *counters)
@total = total
@counters = counters.inject({}) do |hash, label|
hash[label] = 0
hash
end
@current = 0
@sample = []
@sample_size = 5
@started_at = Time.now
end
def incr(label=nil)
@last_incr ||= @started_at
@sample << Time.now - @last_incr
if @sample.size > @sample_size
@sample.shift
end
@last_incr = Time.now
if label.nil?
@current += 1
else
@counters[label] += 1
end
end
def get_estimate(remain)
conversion, _ = CONV.inject([[], remain.to_f]) do |(parts, seconds), conv|
if seconds < conv
parts << nil
[parts, seconds]
else
time = seconds / conv
parts << time
[parts, seconds - (time.floor * conv)]
end
end
NAMES.zip(conversion).reject{|name, time| time.nil?}.map{|name, time| "%d #{name}" % time}.join(', ')
end
def stat
speed = @current.to_f / (Time.now - @started_at)
sample_speed = 1 / (@sample.sum / @sample.size)
remain = (@total - @current) / speed
estimate = get_estimate(remain)
percent = (@current.to_f/@total.to_f) * 100
output = "%.02f%%, %d:%d/s // C:%d/s (%d/%d), est. %s" % [percent, @sample_size, sample_speed, speed, @current, @total, estimate]
@counters.each do |k, v|
output += "\n #{k}: #{v}"
end
output
end
def every(type = :interval, amount = 100, &block)
case type
when :interval
if @current % amount
block.call
end
when :time
@output_start_time ||= Time.now
if (Time.now - @output_start_time) > amount
block.call
@output_start_time = Time.now
end
end
end
def puts_every_second(&block)
every(:time, 1) do
puts stat
block.call if block
end
end
def puts_every_100(&block)
every(:interval, 100) do
puts stat
block.call if block
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment