Skip to content

Commit

Permalink
Merge pull request #86 from Freika/countries-and-cities-revised
Browse files Browse the repository at this point in the history
Countries and cities revised
  • Loading branch information
Freika committed Jun 25, 2024
2 parents b735b17 + 591eeb2 commit 6e89bc9
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 3 deletions.
2 changes: 1 addition & 1 deletion app/assets/builds/tailwind.css

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion app/controllers/map_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class MapController < ApplicationController
def index
@points = current_user.tracked_points.without_raw_data.where('timestamp >= ? AND timestamp <= ?', start_at, end_at).order(timestamp: :asc)

@countries_and_cities = CountriesAndCities.new(@points).call
@countries_and_cities = Visits::Calculate.new(@points).uniq_visits
@coordinates =
@points.pluck(:latitude, :longitude, :battery, :altitude, :timestamp, :velocity, :id)
.map { [_1.to_f, _2.to_f, _3.to_s, _4.to_s, _5.to_s, _6.to_s, _7] }
Expand Down
2 changes: 1 addition & 1 deletion app/jobs/reverse_geocoding_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def perform(point_id)
result = Geocoder.search([point.latitude, point.longitude])
return if result.blank?

point.update(
point.update!(
city: result.first.city,
country: result.first.country
)
Expand Down
89 changes: 89 additions & 0 deletions app/services/visits/calculate.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
# frozen_string_literal: true

class Visits::Calculate
def initialize(points)
@points = points
end

def call
normalize_result(city_visits)
end

def uniq_visits
# Only one visit per city per day
call.flat_map do |country|
{ country: country[:country], cities: country[:cities].uniq { [_1[:city], Time.at(_1[:timestamp]).to_date] } }
end
end

private

attr_reader :points

def group_points
points.sort_by(&:timestamp).reject { _1.city.nil? }.group_by(&:country)
end

def city_visits
group_points.transform_values do |grouped_points|
grouped_points
.group_by(&:city)
.transform_values { |city_points| identify_consecutive_visits(city_points) }
end
end

def identify_consecutive_visits(city_points)
visits = []
current_visit = []

city_points.each_cons(2) do |point1, point2|
time_diff = (point2.timestamp - point1.timestamp) / 60

if time_diff <= MIN_MINUTES_SPENT_IN_CITY
current_visit << point1 unless current_visit.include?(point1)
current_visit << point2
else
visits << create_visit(current_visit) if current_visit.size > 1
current_visit = []
end
end

visits << create_visit(current_visit) if current_visit.size > 1
visits
end

def create_visit(points)
{
city: points.first.city,
points:,
stayed_for: calculate_stayed_time(points),
last_timestamp: points.last.timestamp
}
end

def calculate_stayed_time(points)
return 0 if points.empty?

min_time = points.first.timestamp
max_time = points.last.timestamp
((max_time - min_time) / 60).round
end

def normalize_result(hash)
hash.map do |country, cities|
{
country:,
cities: cities.values.flatten
.select { |visit| visit[:stayed_for] >= MIN_MINUTES_SPENT_IN_CITY }
.map do |visit|
{
city: visit[:city],
points: visit[:points].count,
timestamp: visit[:last_timestamp],
stayed_for: visit[:stayed_for]
}
end
}
end.reject { |entry| entry[:cities].empty? }
end
end
1 change: 1 addition & 0 deletions app/views/shared/_right_sidebar.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@

<% if REVERSE_GEOCODING_ENABLED && @countries_and_cities&.any? %>
<hr class='my-5'>
<h2 class='text-lg font-semibold'>Countries and cities</h2>
<% @countries_and_cities.each do |country| %>
<% next if country[:cities].empty? %>

Expand Down

0 comments on commit 6e89bc9

Please sign in to comment.