mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-04 21:15:19 +02:00
Reindent TimeSeries classes
This commit is contained in:
parent
f5f624881f
commit
e175aa9b49
2 changed files with 91 additions and 92 deletions
|
@ -1,83 +1,82 @@
|
||||||
|
|
||||||
class TimeSeries
|
class TimeSeries
|
||||||
attr_reader :type
|
attr_reader :type
|
||||||
|
|
||||||
def self.from_collection(collection, value_method, options = {})
|
def self.from_collection(collection, value_method, options = {})
|
||||||
data = collection.map do |obj|
|
data = collection.map do |obj|
|
||||||
{ date: obj.date, value: obj.public_send(value_method), original: obj }
|
{ date: obj.date, value: obj.public_send(value_method), original: obj }
|
||||||
end
|
|
||||||
new(data, options)
|
|
||||||
end
|
end
|
||||||
|
new(data, options)
|
||||||
|
end
|
||||||
|
|
||||||
def initialize(data, options = {})
|
def initialize(data, options = {})
|
||||||
@type = options[:type] || :normal
|
@type = options[:type] || :normal
|
||||||
initialize_series_data(data)
|
initialize_series_data(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
def values
|
def values
|
||||||
@values ||= add_trends_to_series
|
@values ||= add_trends_to_series
|
||||||
end
|
end
|
||||||
|
|
||||||
def first
|
def first
|
||||||
values.first
|
values.first
|
||||||
end
|
end
|
||||||
|
|
||||||
def last
|
def last
|
||||||
values.last
|
values.last
|
||||||
end
|
end
|
||||||
|
|
||||||
def on(date)
|
def on(date)
|
||||||
values.find { |v| v.date == date }
|
values.find { |v| v.date == date }
|
||||||
end
|
end
|
||||||
|
|
||||||
def trend
|
def trend
|
||||||
TimeSeries::Trend.new(
|
TimeSeries::Trend.new(
|
||||||
current: last&.value,
|
current: last&.value,
|
||||||
previous: first&.value,
|
previous: first&.value,
|
||||||
type: @type
|
type: @type
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Data shape that frontend expects for D3 charts
|
# Data shape that frontend expects for D3 charts
|
||||||
def to_json(*_args)
|
def to_json(*_args)
|
||||||
|
{
|
||||||
|
values: values.map do |v|
|
||||||
{
|
{
|
||||||
values: values.map do |v|
|
date: v.date,
|
||||||
{
|
value: JSON.parse(v.value.to_json),
|
||||||
date: v.date,
|
trend: {
|
||||||
value: JSON.parse(v.value.to_json),
|
type: v.trend.type,
|
||||||
trend: {
|
direction: v.trend.direction,
|
||||||
type: v.trend.type,
|
value: JSON.parse(v.trend.value.to_json),
|
||||||
direction: v.trend.direction,
|
percent: v.trend.percent
|
||||||
value: JSON.parse(v.trend.value.to_json),
|
}
|
||||||
percent: v.trend.percent
|
}
|
||||||
}
|
end,
|
||||||
}
|
trend: {
|
||||||
end,
|
type: @type,
|
||||||
trend: {
|
direction: trend.direction,
|
||||||
type: @type,
|
value: JSON.parse(trend.value.to_json),
|
||||||
direction: trend.direction,
|
percent: trend.percent
|
||||||
value: JSON.parse(trend.value.to_json),
|
},
|
||||||
percent: trend.percent
|
type: @type
|
||||||
},
|
}.to_json
|
||||||
type: @type
|
end
|
||||||
}.to_json
|
|
||||||
|
private
|
||||||
|
def initialize_series_data(data)
|
||||||
|
@series_data = data.nil? || data.empty? ? [] : data.map { |d| TimeSeries::Value.new(d) }.sort_by(&:date)
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
def add_trends_to_series
|
||||||
def initialize_series_data(data)
|
[ nil, *@series_data ].each_cons(2).map do |previous, current|
|
||||||
@series_data = data.nil? || data.empty? ? [] : data.map { |d| TimeSeries::Value.new(d) }.sort_by(&:date)
|
unless current.trend
|
||||||
end
|
current.trend = TimeSeries::Trend.new(
|
||||||
|
current: current.value,
|
||||||
def add_trends_to_series
|
previous: previous&.value,
|
||||||
[ nil, *@series_data ].each_cons(2).map do |previous, current|
|
type: @type
|
||||||
unless current.trend
|
)
|
||||||
current.trend = TimeSeries::Trend.new(
|
|
||||||
current: current.value,
|
|
||||||
previous: previous&.value,
|
|
||||||
type: @type
|
|
||||||
)
|
|
||||||
end
|
|
||||||
current
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
current
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
class TimeSeries::Value
|
class TimeSeries::Value
|
||||||
include Comparable
|
include Comparable
|
||||||
|
|
||||||
attr_accessor :trend
|
attr_accessor :trend
|
||||||
attr_reader :value, :date, :original
|
attr_reader :value, :date, :original
|
||||||
|
|
||||||
def initialize(obj)
|
def initialize(obj)
|
||||||
@original = obj.fetch(:original, obj)
|
@original = obj.fetch(:original, obj)
|
||||||
|
|
||||||
if obj.is_a?(Hash)
|
if obj.is_a?(Hash)
|
||||||
@date = obj[:date]
|
@date = obj[:date]
|
||||||
@value = obj[:value]
|
@value = obj[:value]
|
||||||
else
|
else
|
||||||
@date = obj.date
|
@date = obj.date
|
||||||
@value = obj.value
|
@value = obj.value
|
||||||
end
|
|
||||||
|
|
||||||
validate_input
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def <=>(other)
|
validate_input
|
||||||
result = date <=> other.date
|
end
|
||||||
result = value <=> other.value if result == 0
|
|
||||||
result
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
def <=>(other)
|
||||||
def validate_input
|
result = date <=> other.date
|
||||||
raise ArgumentError, "Date is required" unless @date.is_a?(Date)
|
result = value <=> other.value if result == 0
|
||||||
raise ArgumentError, "Money or Numeric value is required" unless @value.is_a?(Money) || @value.is_a?(Numeric)
|
result
|
||||||
end
|
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
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue