mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-10 17:21:38 -05:00
64 lines
1.7 KiB
Ruby
64 lines
1.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class Stats::DailyDistanceQuery
|
|
def initialize(monthly_points, timespan)
|
|
@monthly_points = monthly_points
|
|
@timespan = timespan
|
|
end
|
|
|
|
def call
|
|
daily_distances = daily_distances(monthly_points)
|
|
distance_by_day_map = distance_by_day_map(daily_distances)
|
|
|
|
convert_to_daily_distances(distance_by_day_map)
|
|
end
|
|
|
|
private
|
|
|
|
attr_reader :monthly_points, :timespan
|
|
|
|
def daily_distances(monthly_points)
|
|
Stat.connection.select_all(<<-SQL.squish)
|
|
WITH points_with_distances AS (
|
|
SELECT
|
|
EXTRACT(day FROM to_timestamp(timestamp)) as day_of_month,
|
|
CASE
|
|
WHEN LAG(lonlat) OVER (
|
|
PARTITION BY EXTRACT(day FROM to_timestamp(timestamp))
|
|
ORDER BY timestamp
|
|
) IS NOT NULL THEN
|
|
ST_Distance(
|
|
lonlat::geography,
|
|
LAG(lonlat) OVER (
|
|
PARTITION BY EXTRACT(day FROM to_timestamp(timestamp))
|
|
ORDER BY timestamp
|
|
)::geography
|
|
)
|
|
ELSE 0
|
|
END as segment_distance
|
|
FROM (#{monthly_points.to_sql}) as points
|
|
)
|
|
SELECT
|
|
day_of_month,
|
|
ROUND(COALESCE(SUM(segment_distance), 0)) as distance_meters
|
|
FROM points_with_distances
|
|
GROUP BY day_of_month
|
|
ORDER BY day_of_month
|
|
SQL
|
|
end
|
|
|
|
def distance_by_day_map(daily_distances)
|
|
daily_distances.index_by do |row|
|
|
row['day_of_month'].to_i
|
|
end
|
|
end
|
|
|
|
def convert_to_daily_distances(distance_by_day_map)
|
|
timespan.to_a.map.with_index(1) do |day, index|
|
|
distance_meters =
|
|
distance_by_day_map[day.day]&.fetch('distance_meters', 0) || 0
|
|
|
|
[index, distance_meters.to_i]
|
|
end
|
|
end
|
|
end
|