mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-11 09:41:40 -05:00
Fix logic for grouping consecutive points in CountriesAndCities
This update corrects the logic for grouping consecutive points in the group_points_with_consecutive_cities method. It ensures sessions are properly split when transitioning between cities or encountering significant time gaps, leading to accurate grouping and filtering of points based on session duration.
This commit is contained in:
parent
a43f2c6a1d
commit
c1b767d791
1 changed files with 52 additions and 31 deletions
|
|
@ -12,43 +12,64 @@ class CountriesAndCities
|
|||
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) }
|
||||
.map do |country, country_points|
|
||||
cities = process_country_points(country_points)
|
||||
CountryData.new(country: country, cities: cities) if cities.any?
|
||||
end.compact
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :points
|
||||
|
||||
# Step 1: Process points to group by consecutive cities and time
|
||||
def group_points_with_consecutive_cities(country_points)
|
||||
sorted_points = country_points.sort_by(&:timestamp)
|
||||
|
||||
sessions = []
|
||||
current_session = []
|
||||
|
||||
sorted_points.each_with_index do |point, index|
|
||||
if current_session.empty?
|
||||
current_session << point
|
||||
next
|
||||
end
|
||||
|
||||
prev_point = sorted_points[index - 1]
|
||||
|
||||
# Split session if city changes or time gap exceeds the threshold
|
||||
if point.city != prev_point.city
|
||||
sessions << current_session
|
||||
current_session = []
|
||||
end
|
||||
|
||||
current_session << point
|
||||
end
|
||||
|
||||
sessions << current_session unless current_session.empty?
|
||||
sessions
|
||||
end
|
||||
|
||||
# Step 2: Filter sessions that don't meet the minimum minutes per city
|
||||
def filter_sessions(sessions)
|
||||
sessions.map do |session|
|
||||
end_time = session.last.timestamp
|
||||
duration = (end_time - session.first.timestamp) / 60 # Convert seconds to minutes
|
||||
|
||||
if duration >= MIN_MINUTES_SPENT_IN_CITY
|
||||
CityData.new(
|
||||
city: session.first.city,
|
||||
points: session.size,
|
||||
timestamp: end_time,
|
||||
stayed_for: duration
|
||||
)
|
||||
end
|
||||
end.compact
|
||||
end
|
||||
|
||||
# Process points for each country
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
build_city_data(city, points_count, timestamps, duration)
|
||||
end
|
||||
|
||||
def build_city_data(city, points_count, timestamps, duration)
|
||||
return nil if duration < ::MIN_MINUTES_SPENT_IN_CITY
|
||||
|
||||
CityData.new(
|
||||
city: city,
|
||||
points: points_count,
|
||||
timestamp: timestamps.max,
|
||||
stayed_for: duration
|
||||
)
|
||||
end
|
||||
|
||||
def calculate_duration_in_minutes(timestamps)
|
||||
((timestamps.max - timestamps.min).to_i / 60)
|
||||
sessions = group_points_with_consecutive_cities(country_points)
|
||||
filter_sessions(sessions)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Reference in a new issue