mirror of
https://github.com/Freika/dawarich.git
synced 2026-01-12 02:01:39 -05:00
Remove unsed class
This commit is contained in:
parent
ab765a4370
commit
a97e133b35
3 changed files with 3 additions and 312 deletions
|
|
@ -31,12 +31,9 @@ module Maps
|
|||
end
|
||||
|
||||
def coerce_string_param(param)
|
||||
# Check if it's a numeric string (timestamp) or date string
|
||||
if param.match?(/^\d+$/)
|
||||
param.to_i
|
||||
else
|
||||
Time.parse(param).to_i
|
||||
end
|
||||
return param.to_i if param.match?(/^\d+$/)
|
||||
|
||||
Time.parse(param).to_i
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,85 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Maps
|
||||
class H3HexagonCalculator
|
||||
def initialize(user_id, start_date, end_date, h3_resolution = 8)
|
||||
@user_id = user_id
|
||||
@start_date = start_date
|
||||
@end_date = end_date
|
||||
@h3_resolution = h3_resolution
|
||||
end
|
||||
|
||||
def call
|
||||
user_points = fetch_user_points
|
||||
return { success: false, error: 'No points found for the given date range' } if user_points.empty?
|
||||
|
||||
h3_indexes = calculate_h3_indexes(user_points)
|
||||
hexagon_features = build_hexagon_features(h3_indexes)
|
||||
|
||||
{
|
||||
success: true,
|
||||
data: {
|
||||
type: 'FeatureCollection',
|
||||
features: hexagon_features
|
||||
}
|
||||
}
|
||||
rescue StandardError => e
|
||||
{ success: false, error: e.message }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :user_id, :start_date, :end_date, :h3_resolution
|
||||
|
||||
def fetch_user_points
|
||||
Point.without_raw_data
|
||||
.where(user_id: user_id)
|
||||
.where(timestamp: start_date.to_i..end_date.to_i)
|
||||
.where.not(lonlat: nil)
|
||||
.select(:id, :lonlat, :timestamp)
|
||||
end
|
||||
|
||||
def calculate_h3_indexes(points)
|
||||
h3_counts = Hash.new(0)
|
||||
|
||||
points.find_each do |point|
|
||||
# Convert PostGIS point to lat/lng array: [lat, lng]
|
||||
coordinates = [point.lonlat.y, point.lonlat.x]
|
||||
|
||||
# Get H3 index for these coordinates at specified resolution
|
||||
h3_index = H3.from_geo_coordinates(coordinates, h3_resolution)
|
||||
|
||||
# Count points in each hexagon
|
||||
h3_counts[h3_index] += 1
|
||||
end
|
||||
|
||||
h3_counts
|
||||
end
|
||||
|
||||
def build_hexagon_features(h3_counts)
|
||||
h3_counts.map do |h3_index, point_count|
|
||||
# Get the boundary coordinates for this H3 hexagon
|
||||
boundary_coordinates = H3.to_boundary(h3_index)
|
||||
|
||||
# Convert to GeoJSON polygon format (lng, lat)
|
||||
polygon_coordinates = boundary_coordinates.map { |lat, lng| [lng, lat] }
|
||||
|
||||
# Close the polygon by adding the first point at the end
|
||||
polygon_coordinates << polygon_coordinates.first
|
||||
|
||||
{
|
||||
type: 'Feature',
|
||||
geometry: {
|
||||
type: 'Polygon',
|
||||
coordinates: [polygon_coordinates]
|
||||
},
|
||||
properties: {
|
||||
h3_index: h3_index.to_s(16),
|
||||
point_count: point_count,
|
||||
center: H3.to_geo_coordinates(h3_index)
|
||||
}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,221 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Maps::H3HexagonCalculator, type: :service do
|
||||
let(:user) { create(:user) }
|
||||
let(:start_date) { Time.zone.parse('2024-01-01') }
|
||||
let(:end_date) { Time.zone.parse('2024-01-02') }
|
||||
let(:service) { described_class.new(user.id, start_date, end_date, 5) }
|
||||
|
||||
describe '#call' do
|
||||
context 'when user has no points' do
|
||||
it 'returns error response' do
|
||||
result = service.call
|
||||
|
||||
expect(result[:success]).to be false
|
||||
expect(result[:error]).to eq('No points found for the given date range')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user has points outside date range' do
|
||||
before do
|
||||
create(:point,
|
||||
user: user,
|
||||
latitude: 52.5200,
|
||||
longitude: 13.4050,
|
||||
lonlat: 'POINT(13.4050 52.5200)',
|
||||
timestamp: end_date.to_i + 1.hour) # Outside range
|
||||
end
|
||||
|
||||
it 'returns error response' do
|
||||
result = service.call
|
||||
|
||||
expect(result[:success]).to be false
|
||||
expect(result[:error]).to eq('No points found for the given date range')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user has valid points' do
|
||||
before do
|
||||
# Create points in Berlin area
|
||||
create(:point,
|
||||
user: user,
|
||||
latitude: 52.5200,
|
||||
longitude: 13.4050,
|
||||
lonlat: 'POINT(13.4050 52.5200)',
|
||||
timestamp: start_date.to_i + 1.hour)
|
||||
|
||||
create(:point,
|
||||
user: user,
|
||||
latitude: 52.5190,
|
||||
longitude: 13.4040,
|
||||
lonlat: 'POINT(13.4040 52.5190)',
|
||||
timestamp: start_date.to_i + 2.hours)
|
||||
|
||||
# Point outside date range
|
||||
create(:point,
|
||||
user: user,
|
||||
latitude: 52.5200,
|
||||
longitude: 13.4050,
|
||||
lonlat: 'POINT(13.4050 52.5200)',
|
||||
timestamp: end_date.to_i + 1.hour)
|
||||
end
|
||||
|
||||
it 'returns successful response with hexagon features' do
|
||||
result = service.call
|
||||
|
||||
expect(result[:success]).to be true
|
||||
expect(result[:data]).to have_key(:type)
|
||||
expect(result[:data][:type]).to eq('FeatureCollection')
|
||||
expect(result[:data]).to have_key(:features)
|
||||
expect(result[:data][:features]).to be_an(Array)
|
||||
expect(result[:data][:features]).not_to be_empty
|
||||
end
|
||||
|
||||
it 'creates proper GeoJSON features' do
|
||||
result = service.call
|
||||
feature = result[:data][:features].first
|
||||
|
||||
expect(feature).to have_key(:type)
|
||||
expect(feature[:type]).to eq('Feature')
|
||||
|
||||
expect(feature).to have_key(:geometry)
|
||||
expect(feature[:geometry][:type]).to eq('Polygon')
|
||||
expect(feature[:geometry][:coordinates]).to be_an(Array)
|
||||
expect(feature[:geometry][:coordinates].first).to be_an(Array)
|
||||
|
||||
expect(feature).to have_key(:properties)
|
||||
expect(feature[:properties]).to have_key(:h3_index)
|
||||
expect(feature[:properties]).to have_key(:point_count)
|
||||
expect(feature[:properties]).to have_key(:center)
|
||||
end
|
||||
|
||||
it 'only includes points within date range' do
|
||||
result = service.call
|
||||
|
||||
# Should only have features from the 2 points within range
|
||||
total_points = result[:data][:features].sum { |f| f[:properties][:point_count] }
|
||||
expect(total_points).to eq(2)
|
||||
end
|
||||
|
||||
it 'creates closed polygon coordinates' do
|
||||
result = service.call
|
||||
feature = result[:data][:features].first
|
||||
coordinates = feature[:geometry][:coordinates].first
|
||||
|
||||
# First and last coordinates should be the same (closed polygon)
|
||||
expect(coordinates.first).to eq(coordinates.last)
|
||||
|
||||
# Should have 7 coordinates (6 vertices + 1 to close)
|
||||
expect(coordinates.length).to eq(7)
|
||||
end
|
||||
|
||||
it 'counts points correctly per hexagon' do
|
||||
result = service.call
|
||||
|
||||
# Both points are very close, should likely be in same hexagon
|
||||
if result[:data][:features].length == 1
|
||||
expect(result[:data][:features].first[:properties][:point_count]).to eq(2)
|
||||
else
|
||||
# Or they might be in adjacent hexagons
|
||||
total_points = result[:data][:features].sum { |f| f[:properties][:point_count] }
|
||||
expect(total_points).to eq(2)
|
||||
end
|
||||
end
|
||||
|
||||
it 'includes H3 index as hex string' do
|
||||
result = service.call
|
||||
feature = result[:data][:features].first
|
||||
|
||||
h3_index = feature[:properties][:h3_index]
|
||||
expect(h3_index).to be_a(String)
|
||||
expect(h3_index).to match(/^[0-9a-f]+$/) # Hex string
|
||||
end
|
||||
|
||||
it 'includes center coordinates' do
|
||||
result = service.call
|
||||
feature = result[:data][:features].first
|
||||
|
||||
center = feature[:properties][:center]
|
||||
expect(center).to be_an(Array)
|
||||
expect(center.length).to eq(2)
|
||||
expect(center[0]).to be_between(52.0, 53.0) # Lat around Berlin
|
||||
expect(center[1]).to be_between(13.0, 14.0) # Lng around Berlin
|
||||
end
|
||||
end
|
||||
|
||||
context 'with different H3 resolution' do
|
||||
let(:service) { described_class.new(user.id, start_date, end_date, 7) }
|
||||
|
||||
before do
|
||||
create(:point,
|
||||
user: user,
|
||||
latitude: 52.5200,
|
||||
longitude: 13.4050,
|
||||
lonlat: 'POINT(13.4050 52.5200)',
|
||||
timestamp: start_date.to_i + 1.hour)
|
||||
end
|
||||
|
||||
it 'uses the specified resolution' do
|
||||
result = service.call
|
||||
|
||||
expect(result[:success]).to be true
|
||||
expect(result[:data][:features]).not_to be_empty
|
||||
|
||||
# Higher resolution should create different sized hexagons
|
||||
feature = result[:data][:features].first
|
||||
expect(feature[:properties][:h3_index]).to be_present
|
||||
end
|
||||
end
|
||||
|
||||
context 'when H3 operations fail' do
|
||||
before do
|
||||
create(:point,
|
||||
user: user,
|
||||
latitude: 52.5200,
|
||||
longitude: 13.4050,
|
||||
lonlat: 'POINT(13.4050 52.5200)',
|
||||
timestamp: start_date.to_i + 1.hour)
|
||||
|
||||
allow(H3).to receive(:from_geo_coordinates).and_raise(StandardError, 'H3 error')
|
||||
end
|
||||
|
||||
it 'returns error response' do
|
||||
result = service.call
|
||||
|
||||
expect(result[:success]).to be false
|
||||
expect(result[:error]).to eq('H3 error')
|
||||
end
|
||||
end
|
||||
|
||||
context 'with points from different users' do
|
||||
let(:other_user) { create(:user) }
|
||||
|
||||
before do
|
||||
# Points for target user
|
||||
create(:point,
|
||||
user: user,
|
||||
latitude: 52.5200,
|
||||
longitude: 13.4050,
|
||||
lonlat: 'POINT(13.4050 52.5200)',
|
||||
timestamp: start_date.to_i + 1.hour)
|
||||
|
||||
# Points for other user (should be ignored)
|
||||
create(:point,
|
||||
user: other_user,
|
||||
latitude: 52.5200,
|
||||
longitude: 13.4050,
|
||||
lonlat: 'POINT(13.4050 52.5200)',
|
||||
timestamp: start_date.to_i + 1.hour)
|
||||
end
|
||||
|
||||
it 'only includes points from specified user' do
|
||||
result = service.call
|
||||
|
||||
total_points = result[:data][:features].sum { |f| f[:properties][:point_count] }
|
||||
expect(total_points).to eq(1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in a new issue