1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-08-04 21:15:19 +02:00

Refactor TimeSeries artifacts

This commit is contained in:
Jose Farias 2024-04-18 20:03:46 -06:00
parent cc7b878d50
commit 4ed294eb13
8 changed files with 159 additions and 111 deletions

View file

@ -1,20 +1,21 @@
class TimeSeries
attr_reader :type
DIRECTIONS = %w[ up down ].freeze
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)
attr_reader :values, :favorable_direction
def self.from_collection(collection, value_method)
collection.map do |obj|
{
date: obj.date,
value: obj.public_send(value_method),
original: obj
}
end.then { |data| new(data) }
end
def initialize(data, options = {})
@type = options[:type] || :normal
initialize_series_data(data)
end
def values
@values ||= add_trends_to_series
def initialize(data, favorable_direction: "up")
@favorable_direction = (favorable_direction.presence_in(DIRECTIONS) || "up").inquiry
@values = initialize_values data
end
def first
@ -30,53 +31,27 @@ class TimeSeries
end
def trend
TimeSeries::Trend.new(
TimeSeries::Trend.new \
current: last&.value,
previous: first&.value,
type: @type
)
series: self
end
# Data shape that frontend expects for D3 charts
def to_json(*_args)
# `to_json` returns the data shape used by D3 charts
def to_json
{
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
values: values.map(&:as_json),
trend: trend.as_json,
favorable_direction: favorable_direction
}.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
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
def initialize_values(data)
[ nil, *data ].each_cons(2).map do |previous, current|
TimeSeries::Value.new current,
previous: (TimeSeries::Value.new(previous) if previous),
series: self
end
end
end