dawarich/app/services/visits/suggest.rb

111 lines
2.8 KiB
Ruby
Raw Normal View History

2024-08-05 15:23:08 -04:00
# frozen_string_literal: true
class Visits::Suggest
2024-09-14 15:09:29 -04:00
include Rails.application.routes.url_helpers
2024-08-12 16:18:11 -04:00
attr_reader :points, :user, :start_at, :end_at
def initialize(user, start_at:, end_at:)
@start_at = start_at.to_i
@end_at = end_at.to_i
@points = user.tracked_points.not_visited.order(timestamp: :asc).where(timestamp: start_at..end_at)
2024-08-12 16:18:11 -04:00
@user = user
2024-08-05 15:23:08 -04:00
end
def call
2024-08-12 16:18:11 -04:00
prepared_visits = Visits::Prepare.new(points).call
2024-08-05 15:23:08 -04:00
2024-08-12 16:18:11 -04:00
visited_places = create_places(prepared_visits)
visits = create_visits(visited_places)
2024-08-05 15:23:08 -04:00
2024-08-12 16:18:11 -04:00
create_visits_notification(user)
2024-08-05 15:23:08 -04:00
return nil unless DawarichSettings.reverse_geocoding_enabled?
2024-08-05 15:23:08 -04:00
2024-08-25 13:46:50 -04:00
reverse_geocode(visits)
2024-08-05 15:23:08 -04:00
end
private
2024-08-12 16:18:11 -04:00
def create_places(prepared_visits)
prepared_visits.flat_map do |date|
date[:visits] = handle_visits(date[:visits])
2024-08-05 15:23:08 -04:00
2024-08-12 16:18:11 -04:00
date
end
2024-08-05 15:23:08 -04:00
end
2024-08-12 16:18:11 -04:00
def create_visits(visited_places)
visited_places.flat_map do |date|
date[:visits].map do |visit_data|
ActiveRecord::Base.transaction do
search_params = {
user_id: user.id,
duration: visit_data[:duration],
started_at: Time.zone.at(visit_data[:points].first.timestamp)
2024-08-12 16:18:11 -04:00
}
if visit_data[:area].present?
search_params[:area_id] = visit_data[:area].id
elsif visit_data[:place].present?
search_params[:place_id] = visit_data[:place].id
end
visit = Visit.find_or_initialize_by(search_params)
visit.name = visit_data[:place]&.name || visit_data[:area]&.name if visit.name.blank?
visit.ended_at = Time.zone.at(visit_data[:points].last.timestamp)
2024-08-12 16:18:11 -04:00
visit.save!
2024-08-05 15:23:08 -04:00
2024-08-12 16:18:11 -04:00
visit_data[:points].each { |point| point.update!(visit_id: visit.id) }
visit
end
end
2024-08-05 15:23:08 -04:00
end
2024-08-12 16:18:11 -04:00
end
def reverse_geocode(visits)
visits.each(&:async_reverse_geocode)
2024-08-12 16:18:11 -04:00
end
def create_visits_notification(user)
content = <<~CONTENT
2024-09-14 15:09:29 -04:00
New visits have been suggested based on your location data from #{Time.zone.at(start_at)} to #{Time.zone.at(end_at)}. You can review them on the <a href="#{visits_path}" class="link">Visits</a> page.
2024-08-12 16:18:11 -04:00
CONTENT
user.notifications.create!(
kind: :info,
title: 'New visits suggested',
content:
)
end
def create_place(visit)
place = Place.find_or_initialize_by(
latitude: visit[:latitude].to_f.round(5),
longitude: visit[:longitude].to_f.round(5)
2024-08-12 16:18:11 -04:00
)
place.name = Place::DEFAULT_NAME
place.source = Place.sources[:manual]
place.save!
place
end
def handle_visits(visits)
visits.map do |visit|
area = Area.near([visit[:latitude], visit[:longitude]], 0.100).first
if area.present?
visit.merge(area:)
else
place = create_place(visit)
visit.merge(place:)
end
end
2024-08-05 15:23:08 -04:00
end
end