# frozen_string_literal: true module Calculateable extend ActiveSupport::Concern def calculate_path updated_path = build_path_from_coordinates set_path_attributes(updated_path) end def calculate_distance calculated_distance_meters = calculate_distance_from_coordinates self.distance = convert_distance_for_storage(calculated_distance_meters) end def recalculate_path! calculate_path save_if_changed! end def recalculate_distance! calculate_distance save_if_changed! end def recalculate_path_and_distance! calculate_path calculate_distance save_if_changed! end private def path_coordinates points.pluck(:lonlat) end def build_path_from_coordinates Tracks::BuildPath.new(path_coordinates).call end def set_path_attributes(updated_path) self.path = updated_path if respond_to?(:path=) self.original_path = updated_path if respond_to?(:original_path=) end def calculate_distance_from_coordinates # Always calculate in meters for consistent storage Point.total_distance(points, :m) end def convert_distance_for_storage(calculated_distance_meters) # Store as integer meters for consistency calculated_distance_meters.round end def track_model? self.class.name == 'Track' end def save_if_changed! save! if changed? end end