# frozen_string_literal: true class CountriesAndCities def initialize(points) @points = points end def call grouped_records = group_points mapped_with_cities = map_with_cities(grouped_records) filtered_cities = filter_cities(mapped_with_cities) normalize_result(filtered_cities) end private attr_reader :points def group_points points.group_by(&:country) end def map_with_cities(grouped_records) grouped_records.transform_values do |grouped_points| grouped_points .pluck(:city, :timestamp) # Extract city and timestamp .delete_if { _1.first.nil? } # Remove records without city .group_by { |city, _| city } # Group by city .transform_values do |cities| { points: cities.count, last_timestamp: cities.map(&:last).max, # Get the maximum timestamp stayed_for: ((cities.map(&:last).max - cities.map(&:last).min).to_i / 60) # Calculate the time stayed in minutes } end end end def filter_cities(mapped_with_cities) # Remove cities where user stayed for less than 1 hour mapped_with_cities.transform_values do |cities| cities.reject { |_, data| data[:stayed_for] < CITY_VISIT_THRESHOLD } end end def normalize_result(hash) hash.map do |country, cities| { country:, cities: cities.map do |city, data| { city:, points: data[:points], timestamp: data[:last_timestamp], stayed_for: data[:stayed_for]} end } end end end