From e175aa9b491caf64ec847d95bfcb40096cef39c9 Mon Sep 17 00:00:00 2001 From: Jose Farias Date: Thu, 18 Apr 2024 18:03:52 -0600 Subject: [PATCH] Reindent TimeSeries classes --- app/models/time_series.rb | 135 ++++++++++++++++---------------- app/models/time_series/value.rb | 48 ++++++------ 2 files changed, 91 insertions(+), 92 deletions(-) diff --git a/app/models/time_series.rb b/app/models/time_series.rb index 001c7bdd..b868b710 100644 --- a/app/models/time_series.rb +++ b/app/models/time_series.rb @@ -1,83 +1,82 @@ - class TimeSeries - attr_reader :type + attr_reader :type - def self.from_collection(collection, value_method, options = {}) - data = collection.map do |obj| - { date: obj.date, value: obj.public_send(value_method), original: obj } - end - new(data, options) + def self.from_collection(collection, value_method, options = {}) + data = collection.map do |obj| + { date: obj.date, value: obj.public_send(value_method), original: obj } end + new(data, options) + end - def initialize(data, options = {}) - @type = options[:type] || :normal - initialize_series_data(data) - end + def initialize(data, options = {}) + @type = options[:type] || :normal + initialize_series_data(data) + end - def values - @values ||= add_trends_to_series - end + def values + @values ||= add_trends_to_series + end - def first - values.first - end + def first + values.first + end - def last - values.last - end + def last + values.last + end - def on(date) - values.find { |v| v.date == date } - end + def on(date) + values.find { |v| v.date == date } + end - def trend - TimeSeries::Trend.new( - current: last&.value, - previous: first&.value, - type: @type - ) - end + def trend + TimeSeries::Trend.new( + current: last&.value, + previous: first&.value, + type: @type + ) + end - # Data shape that frontend expects for D3 charts - def to_json(*_args) + # Data shape that frontend expects for D3 charts + def to_json(*_args) + { + values: values.map do |v| { - values: values.map do |v| - { - date: v.date, - value: JSON.parse(v.value.to_json), - trend: { - type: v.trend.type, - direction: v.trend.direction, - value: JSON.parse(v.trend.value.to_json), - percent: v.trend.percent - } - } - end, - trend: { - type: @type, - direction: trend.direction, - value: JSON.parse(trend.value.to_json), - percent: trend.percent - }, - type: @type - }.to_json + date: v.date, + value: JSON.parse(v.value.to_json), + trend: { + type: v.trend.type, + direction: v.trend.direction, + value: JSON.parse(v.trend.value.to_json), + percent: v.trend.percent + } + } + end, + trend: { + type: @type, + direction: trend.direction, + value: JSON.parse(trend.value.to_json), + percent: trend.percent + }, + type: @type + }.to_json + end + + private + def initialize_series_data(data) + @series_data = data.nil? || data.empty? ? [] : data.map { |d| TimeSeries::Value.new(d) }.sort_by(&:date) end - private - def initialize_series_data(data) - @series_data = data.nil? || data.empty? ? [] : data.map { |d| TimeSeries::Value.new(d) }.sort_by(&:date) - end - - def add_trends_to_series - [ nil, *@series_data ].each_cons(2).map do |previous, current| - unless current.trend - current.trend = TimeSeries::Trend.new( - current: current.value, - previous: previous&.value, - type: @type - ) - end - current - end + def add_trends_to_series + [ nil, *@series_data ].each_cons(2).map do |previous, current| + unless current.trend + current.trend = TimeSeries::Trend.new( + current: current.value, + previous: previous&.value, + type: @type + ) end + current + end + end end diff --git a/app/models/time_series/value.rb b/app/models/time_series/value.rb index fbf8ab31..a2fb4852 100644 --- a/app/models/time_series/value.rb +++ b/app/models/time_series/value.rb @@ -1,32 +1,32 @@ class TimeSeries::Value - include Comparable + include Comparable - attr_accessor :trend - attr_reader :value, :date, :original + attr_accessor :trend + attr_reader :value, :date, :original - def initialize(obj) - @original = obj.fetch(:original, obj) + def initialize(obj) + @original = obj.fetch(:original, obj) - if obj.is_a?(Hash) - @date = obj[:date] - @value = obj[:value] - else - @date = obj.date - @value = obj.value - end - - validate_input + if obj.is_a?(Hash) + @date = obj[:date] + @value = obj[:value] + else + @date = obj.date + @value = obj.value end - def <=>(other) - result = date <=> other.date - result = value <=> other.value if result == 0 - result - end + validate_input + end - private - def validate_input - raise ArgumentError, "Date is required" unless @date.is_a?(Date) - raise ArgumentError, "Money or Numeric value is required" unless @value.is_a?(Money) || @value.is_a?(Numeric) - end + def <=>(other) + result = date <=> other.date + result = value <=> other.value if result == 0 + result + end + + private + def validate_input + raise ArgumentError, "Date is required" unless @date.is_a?(Date) + raise ArgumentError, "Money or Numeric value is required" unless @value.is_a?(Money) || @value.is_a?(Numeric) + end end