2024-06-07 15:22:57 -04:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
2024-03-23 15:29:55 -04:00
|
|
|
class StatsController < ApplicationController
|
2025-09-12 15:08:45 -04:00
|
|
|
before_action :authenticate_user!
|
|
|
|
|
before_action :authenticate_active_user!, only: %i[update update_all]
|
2024-03-23 15:29:55 -04:00
|
|
|
|
|
|
|
|
def index
|
2025-07-22 13:43:27 -04:00
|
|
|
@stats = build_stats
|
|
|
|
|
assign_points_statistics
|
|
|
|
|
@year_distances = precompute_year_distances
|
2024-03-23 15:29:55 -04:00
|
|
|
end
|
2024-03-24 14:25:33 -04:00
|
|
|
|
2024-03-24 14:46:55 -04:00
|
|
|
def show
|
|
|
|
|
@year = params[:year].to_i
|
2024-03-28 10:11:59 -04:00
|
|
|
@stats = current_user.stats.where(year: @year).order(:month)
|
2025-07-22 16:41:12 -04:00
|
|
|
@year_distances = { @year => Stat.year_distance(@year, current_user) }
|
2024-03-24 14:46:55 -04:00
|
|
|
end
|
|
|
|
|
|
2025-09-10 18:19:34 -04:00
|
|
|
def month
|
|
|
|
|
@year = params[:year].to_i
|
|
|
|
|
@month = params[:month].to_i
|
|
|
|
|
@stat = current_user.stats.find_by(year: @year, month: @month)
|
|
|
|
|
@previous_stat = current_user.stats.find_by(year: @year, month: @month - 1) if @month > 1
|
2025-09-13 10:41:28 -04:00
|
|
|
@average_distance_this_year = current_user.stats.where(year: @year).average(:distance).to_i / 1000
|
2025-09-10 18:19:34 -04:00
|
|
|
end
|
|
|
|
|
|
2024-03-24 14:25:33 -04:00
|
|
|
def update
|
2024-12-20 09:26:25 -05:00
|
|
|
if params[:month] == 'all'
|
|
|
|
|
(1..12).each do |month|
|
|
|
|
|
Stats::CalculatingJob.perform_later(current_user.id, params[:year], month)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
target = "the whole #{params[:year]}"
|
|
|
|
|
else
|
|
|
|
|
Stats::CalculatingJob.perform_later(current_user.id, params[:year], params[:month])
|
|
|
|
|
|
|
|
|
|
target = "#{Date::MONTHNAMES[params[:month].to_i]} of #{params[:year]}"
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
redirect_to stats_path, notice: "Stats for #{target} are being updated", status: :see_other
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def update_all
|
2024-12-06 10:52:36 -05:00
|
|
|
current_user.years_tracked.each do |year|
|
2024-12-16 09:10:46 -05:00
|
|
|
year[:months].each do |month|
|
|
|
|
|
Stats::CalculatingJob.perform_later(
|
|
|
|
|
current_user.id, year[:year], Date::ABBR_MONTHNAMES.index(month)
|
|
|
|
|
)
|
2024-12-06 10:52:36 -05:00
|
|
|
end
|
|
|
|
|
end
|
2024-03-24 14:25:33 -04:00
|
|
|
|
|
|
|
|
redirect_to stats_path, notice: 'Stats are being updated', status: :see_other
|
|
|
|
|
end
|
2025-07-22 13:43:27 -04:00
|
|
|
|
|
|
|
|
private
|
|
|
|
|
|
|
|
|
|
def assign_points_statistics
|
|
|
|
|
points_stats = ::StatsQuery.new(current_user).points_stats
|
|
|
|
|
|
|
|
|
|
@points_total = points_stats[:total]
|
|
|
|
|
@points_reverse_geocoded = points_stats[:geocoded]
|
|
|
|
|
@points_reverse_geocoded_without_data = points_stats[:without_data]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def precompute_year_distances
|
|
|
|
|
year_distances = {}
|
|
|
|
|
|
2025-07-26 19:08:29 -04:00
|
|
|
@stats.each do |year, stats|
|
|
|
|
|
stats_by_month = stats.index_by(&:month)
|
2025-08-14 14:50:22 -04:00
|
|
|
|
2025-07-26 19:08:29 -04:00
|
|
|
year_distances[year] = (1..12).map do |month|
|
|
|
|
|
month_name = Date::MONTHNAMES[month]
|
|
|
|
|
distance = stats_by_month[month]&.distance || 0
|
2025-08-14 14:50:22 -04:00
|
|
|
|
2025-07-26 19:08:29 -04:00
|
|
|
[month_name, distance]
|
|
|
|
|
end
|
2025-07-22 13:43:27 -04:00
|
|
|
end
|
|
|
|
|
|
|
|
|
|
year_distances
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def build_stats
|
2026-01-07 13:48:14 -05:00
|
|
|
# Select only needed columns - avoid loading large JSONB fields
|
|
|
|
|
# daily_distance and h3_hex_ids are never needed on index page
|
|
|
|
|
columns = [:id, :year, :month, :distance, :updated_at, :user_id]
|
|
|
|
|
columns << :toponyms if DawarichSettings.reverse_geocoding_enabled?
|
|
|
|
|
|
|
|
|
|
current_user.stats
|
|
|
|
|
.select(columns)
|
|
|
|
|
.order(year: :desc, updated_at: :desc)
|
|
|
|
|
.group_by(&:year)
|
2025-07-22 13:43:27 -04:00
|
|
|
end
|
2024-03-23 15:29:55 -04:00
|
|
|
end
|