dawarich/app/services/countries_and_cities.rb
2024-12-11 17:14:26 +01:00

46 lines
1.3 KiB
Ruby

# frozen_string_literal: true
class CountriesAndCities
CityStats = Struct.new(:points, :last_timestamp, :stayed_for, keyword_init: true)
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
points
.reject { |point| point.country.nil? || point.city.nil? }
.group_by(&:country)
.transform_values { |country_points| process_country_points(country_points) }
.map { |country, cities| CountryData.new(country: country, cities: cities) }
end
private
attr_reader :points
def process_country_points(country_points)
country_points
.group_by(&:city)
.transform_values do |city_points|
timestamps = city_points.map(&:timestamp)
build_city_data(city_points.first.city, city_points.size, timestamps)
end
.values
end
def build_city_data(city, points_count, timestamps)
CityData.new(
city: city,
points: points_count,
timestamp: timestamps.max,
stayed_for: calculate_duration_in_minutes(timestamps)
)
end
def calculate_duration_in_minutes(timestamps)
((timestamps.max - timestamps.min).to_i / 60)
end
end