Class: Omnizip::ETA::SampleHistory

Inherits:
Object
  • Object
show all
Defined in:
lib/omnizip/eta/sample_history.rb

Overview

Stores historical samples for ETA calculation.

This class maintains a time-series of progress samples with a limited size to avoid unbounded memory growth. It provides statistics on the samples for rate calculation and trend analysis.

Defined Under Namespace

Classes: Sample

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(max_size: 100) ⇒ SampleHistory

Initialize a new sample history

Parameters:

  • max_size (Integer) (defaults to: 100)

    Maximum number of samples to retain



35
36
37
38
# File 'lib/omnizip/eta/sample_history.rb', line 35

def initialize(max_size: 100)
  @max_size = max_size
  @samples = []
end

Instance Attribute Details

#max_sizeObject (readonly)

Returns the value of attribute max_size.



30
31
32
# File 'lib/omnizip/eta/sample_history.rb', line 30

def max_size
  @max_size
end

#samplesObject (readonly)

Returns the value of attribute samples.



30
31
32
# File 'lib/omnizip/eta/sample_history.rb', line 30

def samples
  @samples
end

Instance Method Details

#add_sample(bytes_processed:, files_processed:, timestamp: Time.now) ⇒ Object

Add a new sample to the history

Parameters:

  • bytes_processed (Integer)

    Total bytes processed so far

  • files_processed (Integer)

    Total files processed so far

  • timestamp (Time) (defaults to: Time.now)

    Sample timestamp (defaults to now)



45
46
47
48
49
50
51
# File 'lib/omnizip/eta/sample_history.rb', line 45

def add_sample(bytes_processed:, files_processed:, timestamp: Time.now)
  sample = Sample.new(timestamp, bytes_processed, files_processed)
  @samples << sample

  # Trim oldest samples if we exceed max size
  @samples.shift if @samples.size > max_size
end

#average_rateFloat

Calculate average rate over all samples

Returns:

  • (Float)

    Average bytes per second



81
82
83
84
85
86
87
# File 'lib/omnizip/eta/sample_history.rb', line 81

def average_rate
  return 0.0 if @samples.size < 2

  first = @samples.first
  last = @samples.last
  last.rate_since(first)
end

#clearObject

Clear all samples



124
125
126
# File 'lib/omnizip/eta/sample_history.rb', line 124

def clear
  @samples.clear
end

#empty?Boolean

Check if history is empty

Returns:

  • (Boolean)

    true if no samples



138
139
140
# File 'lib/omnizip/eta/sample_history.rb', line 138

def empty?
  @samples.empty?
end

#latestSample?

Get the most recent sample

Returns:

  • (Sample, nil)

    Most recent sample or nil if empty



56
57
58
# File 'lib/omnizip/eta/sample_history.rb', line 56

def latest
  @samples.last
end

#oldestSample?

Get the oldest sample

Returns:

  • (Sample, nil)

    Oldest sample or nil if empty



63
64
65
# File 'lib/omnizip/eta/sample_history.rb', line 63

def oldest
  @samples.first
end

#rate_std_dev(window_size = 10) ⇒ Float

Calculate standard deviation of recent rates

Parameters:

  • window_size (Integer) (defaults to: 10)

    Number of samples to use

Returns:

  • (Float)

    Standard deviation of rates



106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# File 'lib/omnizip/eta/sample_history.rb', line 106

def rate_std_dev(window_size = 10)
  return 0.0 if @samples.size < 3

  recent = @samples.last([window_size, @samples.size].min)
  rates = []

  1.upto(recent.size - 1) do |i|
    rates << recent[i].rate_since(recent[i - 1])
  end

  return 0.0 if rates.empty?

  mean = rates.sum / rates.size
  variance = rates.sum { |r| (r - mean)**2 } / rates.size
  Math.sqrt(variance)
end

#recent_rate(seconds = 10.0) ⇒ Float

Calculate average rate over recent time window

Parameters:

  • seconds (Float) (defaults to: 10.0)

    Time window in seconds

Returns:

  • (Float)

    Average bytes per second over window



93
94
95
96
97
98
99
100
# File 'lib/omnizip/eta/sample_history.rb', line 93

def recent_rate(seconds = 10.0)
  recent = recent_samples(seconds)
  return 0.0 if recent.size < 2

  first = recent.first
  last = recent.last
  last.rate_since(first)
end

#recent_samples(seconds) ⇒ Array<Sample>

Get samples from a specific time window

Parameters:

  • seconds (Float)

    Number of seconds to look back

Returns:

  • (Array<Sample>)

    Samples within the time window



71
72
73
74
75
76
# File 'lib/omnizip/eta/sample_history.rb', line 71

def recent_samples(seconds)
  return [] if @samples.empty?

  cutoff_time = Time.now - seconds
  @samples.select { |s| s.timestamp >= cutoff_time }
end

#sizeInteger

Get number of samples

Returns:

  • (Integer)

    Number of samples stored



131
132
133
# File 'lib/omnizip/eta/sample_history.rb', line 131

def size
  @samples.size
end