Class: Progressor::UnlimitedSequence

Inherits:
Object
  • Object
show all
Includes:
Formatting
Defined in:
lib/progressor/unlimited_sequence.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Formatting

#format_float, #format_int, #format_time

Constructor Details

#initialize(min_samples: 1, max_samples: 100, formatter: nil) ⇒ UnlimitedSequence

Creates a new UnlimitedSequence with the given parameters:

  • min_samples: The number of samples to collect before attempting to calculate a time per iteration. Default: 1

  • max_samples: The maximum number of measurements to collect and average. Default: 100.

  • formatter: A callable that accepts the sequence object and returns a custom formatted string.

Raises:



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/progressor/unlimited_sequence.rb', line 24

def initialize(min_samples: 1, max_samples: 100, formatter: nil)
  @min_samples = min_samples
  @max_samples = max_samples
  @formatter   = formatter

  raise Error.new("min_samples needs to be a positive number") if min_samples <= 0
  raise Error.new("max_samples needs to be larger than min_samples") if max_samples <= min_samples

  @start_time   = Time.now
  @current      = 0
  @measurements = []
  @averages     = []
end

Instance Attribute Details

#currentObject (readonly)

The current loop index, starts at 1



8
9
10
# File 'lib/progressor/unlimited_sequence.rb', line 8

def current
  @current
end

#max_samplesObject (readonly)

Returns the value of attribute max_samples.



5
6
7
# File 'lib/progressor/unlimited_sequence.rb', line 5

def max_samples
  @max_samples
end

#min_samplesObject (readonly)

Returns the value of attribute min_samples.



5
6
7
# File 'lib/progressor/unlimited_sequence.rb', line 5

def min_samples
  @min_samples
end

#start_timeObject (readonly)

The time the object was created



11
12
13
# File 'lib/progressor/unlimited_sequence.rb', line 11

def start_time
  @start_time
end

Instance Method Details

#elapsed_timeObject

Returns the time since the object was instantiated, formatted like all the other durations.



101
102
103
# File 'lib/progressor/unlimited_sequence.rb', line 101

def elapsed_time
  format_time(Time.now - @start_time)
end

#etaObject

Is supposed to return an estimation for the Estimated Time of Arrival (time until done).

For an UnlimitedSequence, this always returns nil.



94
95
96
# File 'lib/progressor/unlimited_sequence.rb', line 94

def eta
  # No estimation possible
end

#per_iterationObject

Returns an estimation for the time per single iteration. Implemented as an average of averages to provide a smoother gradient from loop to loop.

Returns nil if not enough samples have been collected yet.



84
85
86
87
# File 'lib/progressor/unlimited_sequence.rb', line 84

def per_iteration
  return nil if @measurements.count < min_samples
  average(@averages)
end

#push(duration) ⇒ Object

Adds a duration in seconds to the internal storage of samples. Updates averages accordingly.



41
42
43
44
45
46
47
48
49
50
51
# File 'lib/progressor/unlimited_sequence.rb', line 41

def push(duration)
  @current += 1
  @measurements << duration
  # only keep last `max_samples`
  @measurements.shift if @measurements.count > max_samples

  @averages << average(@measurements)
  @averages = @averages.compact
  # only keep last `max_samples`
  @averages.shift if @averages.count > max_samples
end

#skip(_n) ⇒ Object

“Skips” an iteration, which, in the context of an UnlimitedSequence is a no-op.



55
56
57
# File 'lib/progressor/unlimited_sequence.rb', line 55

def skip(_n)
  # Nothing to do
end

#to_sObject

Outputs a textual representation of the current state of the UnlimitedSequence. Shows:

  • the current (1-indexed) number of iterations

  • how long since the start time

  • how long a single iteration takes

A custom ‘formatter` provided at construction time overrides this default output.



69
70
71
72
73
74
75
76
77
# File 'lib/progressor/unlimited_sequence.rb', line 69

def to_s
  return @formatter.call(self).to_s if @formatter

  [
    "#{@current + 1}",
    "t: #{elapsed_time}",
    "t/i: #{format_time(per_iteration)}",
  ].join(', ')
end