dawarich/app/services/countries_and_cities.rb

55 lines
1.4 KiB
Ruby
Raw Permalink Normal View History

# frozen_string_literal: true
class CountriesAndCities
2024-12-11 11:14:26 -05:00
CountryData = Struct.new(:country, :cities, keyword_init: true)
CityData = Struct.new(:city, :points, :timestamp, :stayed_for, keyword_init: true)
def initialize(points)
@points = points
end
def call
2024-12-11 11:14:26 -05:00
points
.reject { |point| point.country_name.nil? || point.city.nil? }
2025-09-10 18:19:34 -04:00
.group_by(&:country_name)
2025-06-09 06:09:26 -04:00
.transform_values { |country_points| process_country_points(country_points) }
.map { |country, cities| CountryData.new(country: country, cities: cities) }
end
private
attr_reader :points
2025-06-09 06:09:26 -04:00
def process_country_points(country_points)
country_points
.group_by(&:city)
.transform_values { |city_points| create_city_data_if_valid(city_points) }
.values
.compact
end
2025-06-09 06:09:26 -04:00
def create_city_data_if_valid(city_points)
timestamps = city_points.pluck(:timestamp)
duration = calculate_duration_in_minutes(timestamps)
city = city_points.first.city
points_count = city_points.size
2025-06-09 06:09:26 -04:00
build_city_data(city, points_count, timestamps, duration)
2024-12-16 09:10:46 -05:00
end
2025-06-09 06:09:26 -04:00
def build_city_data(city, points_count, timestamps, duration)
return nil if duration < ::MIN_MINUTES_SPENT_IN_CITY
2024-12-16 09:10:46 -05:00
2025-06-09 06:09:26 -04:00
CityData.new(
city: city,
points: points_count,
timestamp: timestamps.max,
stayed_for: duration
)
end
2025-06-09 06:09:26 -04:00
def calculate_duration_in_minutes(timestamps)
((timestamps.max - timestamps.min).to_i / 60)
end
end