ne-sachirou/stream_stat

View on GitHub
lib/stream_stat/v.rb

Summary

Maintainability
A
35 mins
Test Coverage
# frozen_string_literal: true

class StreamStat
  # Accumrator.
  #
  # This holds :avg, :variance, :sd, :min & :max
  class V
    attr_reader :avg, :min, :max

    # @param [Integer] count
    # @param [Float] avg
    # @param [Float] square_avg
    # @param [Float] min
    # @param [Float] max
    def initialize(count = 0, avg = 0.0, square_avg = 0.0, min = Float::INFINITY, max = -Float::INFINITY)
      @count = count
      @avg = avg
      @square_avg = square_avg
      @min = min
      @max = max
    end

    # @param [Numeric] item
    # @return [StreamStat::V]
    def next(item)
      item = item.to_f
      next_length = @count + 1
      self.class.new(
        next_length,
        next_avg(next_length, item),
        next_square_avg(next_length, item),
        [@min, item].min,
        [@max, item].max
      )
    end

    # @return [Float]
    def variance
      @square_avg - @avg**2
    end

    # @return [Float]
    def sd
      Math.sqrt variance
    end

    private

    def next_avg(next_length, item)
      @avg + (item - @avg) / next_length
    end

    def next_square_avg(next_length, item)
      @square_avg + (item**2 - @square_avg) / next_length
    end
  end
end