dawarich/app/controllers/stats_controller.rb
Evgenii Burmakin ce8a7cd4ef
Implement some performance improvements and caching for various featu… (#2133)
* Implement some performance improvements and caching for various features.

* Fix failing tests

* Implement routes behaviour in map v2 to match map v1

* Fix route highlighting

* Add fallbacks when retrieving full route features to handle cases where source data access methods vary.

* Fix some e2e tests
2026-01-07 19:48:14 +01:00

93 lines
2.7 KiB
Ruby

# frozen_string_literal: true
class StatsController < ApplicationController
before_action :authenticate_user!
before_action :authenticate_active_user!, only: %i[update update_all]
def index
@stats = build_stats
assign_points_statistics
@year_distances = precompute_year_distances
end
def show
@year = params[:year].to_i
@stats = current_user.stats.where(year: @year).order(:month)
@year_distances = { @year => Stat.year_distance(@year, current_user) }
end
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
@average_distance_this_year = current_user.stats.where(year: @year).average(:distance).to_i / 1000
end
def update
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
current_user.years_tracked.each do |year|
year[:months].each do |month|
Stats::CalculatingJob.perform_later(
current_user.id, year[:year], Date::ABBR_MONTHNAMES.index(month)
)
end
end
redirect_to stats_path, notice: 'Stats are being updated', status: :see_other
end
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 = {}
@stats.each do |year, stats|
stats_by_month = stats.index_by(&:month)
year_distances[year] = (1..12).map do |month|
month_name = Date::MONTHNAMES[month]
distance = stats_by_month[month]&.distance || 0
[month_name, distance]
end
end
year_distances
end
def build_stats
# 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)
end
end