From 11f7ac772bdfe8a5da4ece865efd5a092ee8e4ff Mon Sep 17 00:00:00 2001 From: Ivan Ivanov Date: Mon, 16 Dec 2024 16:12:31 +0200 Subject: [PATCH] aggregated_timeseries_data in SocialData.MetricAdapter for more metrics - Support the aggregated_timeseries_data for sentiment metrics, too. - Extract the functionality in one function - Allow for other aggregations to be provided via API --- lib/sanbase/social_data/metric_adapter.ex | 31 +++++------------------ lib/sanbase/utils/math_aggregation.ex | 20 +++++++++++++++ 2 files changed, 26 insertions(+), 25 deletions(-) create mode 100644 lib/sanbase/utils/math_aggregation.ex diff --git a/lib/sanbase/social_data/metric_adapter.ex b/lib/sanbase/social_data/metric_adapter.ex index f8a5fbb82..5452a5ee6 100644 --- a/lib/sanbase/social_data/metric_adapter.ex +++ b/lib/sanbase/social_data/metric_adapter.ex @@ -162,47 +162,28 @@ defmodule Sanbase.SocialData.MetricAdapter do end @impl Sanbase.Metric.Behaviour - def aggregated_timeseries_data(metric, selector, from, to, opts) - when metric in @social_volume_timeseries_metrics or - metric in @community_messages_count_timeseries_metrics do + def aggregated_timeseries_data(metric, selector, from, to, opts) do slug = Map.get(selector, :slug) case is_nil(slug) or is_binary(slug) do - true -> - case timeseries_data(metric, selector, from, to, "1h", opts) do - {:ok, result} -> - value = Enum.reduce(result, 0, &(&1.value + &2)) - {:ok, %{value: value}} - - {:error, error} -> - {:error, error} - end - false -> {:error, "Aggregated timeseries data is not supported for lists of slugs."} - end - end - def aggregated_timeseries_data(metric, selector, from, to, opts) - when metric in @social_dominance_timeseries_metrics do - slug = Map.get(selector, :slug) - - case is_nil(slug) or is_binary(slug) do true -> case timeseries_data(metric, selector, from, to, "1h", opts) do {:ok, result} -> + {:ok, metadata} = metadata(metric) + aggregation = Keyword.get(opts, :aggregation) || metadata.default_aggregation + value = - Enum.map(result, & &1.value) - |> Sanbase.Math.mean() + Sanbase.MathAggregation.compute(result, aggregation, & &1.value) + |> Sanbase.Math.round_float() {:ok, %{value: value}} {:error, error} -> {:error, error} end - - false -> - {:error, "Aggregated timeseries data is not supported for lists of slugs."} end end diff --git a/lib/sanbase/utils/math_aggregation.ex b/lib/sanbase/utils/math_aggregation.ex new file mode 100644 index 000000000..e809fa036 --- /dev/null +++ b/lib/sanbase/utils/math_aggregation.ex @@ -0,0 +1,20 @@ +defmodule Sanbase.MathAggregation do + def compute(list, aggregation, fun \\ & &1) + def compute(list, :max, fun), do: Enum.map(list, fun) |> Enum.max() + def compute(list, :min, fun), do: Enum.map(list, fun) |> Enum.min() + def compute(list, :avg, fun), do: Enum.map(list, fun) |> Sanbase.Math.mean() + def compute(list, :median, fun), do: Enum.map(list, fun) |> Sanbase.Math.median() + def compute(list, :count, _fun), do: Enum.count(list) + def compute(list, :sum, fun), do: Enum.map(list, fun) |> Enum.sum() + def compute(list, :first, fun), do: Enum.map(list, fun) |> List.first() + def compute(list, :last, fun), do: Enum.map(list, fun) |> List.last() + + def compute(list, :ohlc, fun) do + %{ + open: compute(list, :first, fun), + high: compute(list, :max, fun), + low: compute(list, :min, fun), + close: compute(list, :last, fun) + } + end +end