mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-04-22 11:36:38 +00:00
route in progress, region stitching is disabled by default
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
CREATE TABLE routes (
|
||||
id UUID PRIMARY KEY,
|
||||
name VARCHAR(200) NOT NULL,
|
||||
description TEXT,
|
||||
region_size_meters DOUBLE PRECISION NOT NULL,
|
||||
zoom_level INT NOT NULL,
|
||||
total_distance_meters DOUBLE PRECISION NOT NULL,
|
||||
total_points INT NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
CREATE TABLE route_points (
|
||||
id UUID PRIMARY KEY,
|
||||
route_id UUID NOT NULL REFERENCES routes(id) ON DELETE CASCADE,
|
||||
sequence_number INT NOT NULL,
|
||||
latitude DOUBLE PRECISION NOT NULL,
|
||||
longitude DOUBLE PRECISION NOT NULL,
|
||||
point_type VARCHAR(20) NOT NULL,
|
||||
segment_index INT NOT NULL,
|
||||
distance_from_previous DOUBLE PRECISION,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
UNIQUE(route_id, sequence_number)
|
||||
);
|
||||
|
||||
CREATE TABLE route_regions (
|
||||
route_id UUID NOT NULL REFERENCES routes(id) ON DELETE CASCADE,
|
||||
region_id UUID NOT NULL REFERENCES regions(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (route_id, region_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_route_points_route ON route_points(route_id, sequence_number);
|
||||
CREATE INDEX idx_route_points_coords ON route_points(latitude, longitude);
|
||||
CREATE INDEX idx_route_regions_route ON route_regions(route_id);
|
||||
CREATE INDEX idx_route_regions_region ON route_regions(region_id);
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE regions ADD COLUMN stitch_tiles BOOLEAN NOT NULL DEFAULT false;
|
||||
|
||||
@@ -12,6 +12,7 @@ public class RegionEntity
|
||||
public string? SummaryFilePath { get; set; }
|
||||
public int TilesDownloaded { get; set; }
|
||||
public int TilesReused { get; set; }
|
||||
public bool StitchTiles { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace SatelliteProvider.DataAccess.Models;
|
||||
|
||||
public class RouteEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string? Description { get; set; }
|
||||
public double RegionSizeMeters { get; set; }
|
||||
public int ZoomLevel { get; set; }
|
||||
public double TotalDistanceMeters { get; set; }
|
||||
public int TotalPoints { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
public DateTime UpdatedAt { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace SatelliteProvider.DataAccess.Models;
|
||||
|
||||
public class RoutePointEntity
|
||||
{
|
||||
public Guid Id { get; set; }
|
||||
public Guid RouteId { get; set; }
|
||||
public int SequenceNumber { get; set; }
|
||||
public double Latitude { get; set; }
|
||||
public double Longitude { get; set; }
|
||||
public string PointType { get; set; } = string.Empty;
|
||||
public int SegmentIndex { get; set; }
|
||||
public double? DistanceFromPrevious { get; set; }
|
||||
public DateTime CreatedAt { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using SatelliteProvider.DataAccess.Models;
|
||||
|
||||
namespace SatelliteProvider.DataAccess.Repositories;
|
||||
|
||||
public interface IRouteRepository
|
||||
{
|
||||
Task<RouteEntity?> GetByIdAsync(Guid id);
|
||||
Task<IEnumerable<RoutePointEntity>> GetRoutePointsAsync(Guid routeId);
|
||||
Task<Guid> InsertRouteAsync(RouteEntity route);
|
||||
Task InsertRoutePointsAsync(IEnumerable<RoutePointEntity> points);
|
||||
Task<int> UpdateRouteAsync(RouteEntity route);
|
||||
Task<int> DeleteRouteAsync(Guid id);
|
||||
Task LinkRouteToRegionAsync(Guid routeId, Guid regionId);
|
||||
Task<IEnumerable<Guid>> GetRegionIdsByRouteAsync(Guid routeId);
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ public class RegionRepository : IRegionRepository
|
||||
zoom_level as ZoomLevel, status,
|
||||
csv_file_path as CsvFilePath, summary_file_path as SummaryFilePath,
|
||||
tiles_downloaded as TilesDownloaded, tiles_reused as TilesReused,
|
||||
stitch_tiles as StitchTiles,
|
||||
created_at as CreatedAt, updated_at as UpdatedAt
|
||||
FROM regions
|
||||
WHERE id = @Id";
|
||||
@@ -36,6 +37,7 @@ public class RegionRepository : IRegionRepository
|
||||
zoom_level as ZoomLevel, status,
|
||||
csv_file_path as CsvFilePath, summary_file_path as SummaryFilePath,
|
||||
tiles_downloaded as TilesDownloaded, tiles_reused as TilesReused,
|
||||
stitch_tiles as StitchTiles,
|
||||
created_at as CreatedAt, updated_at as UpdatedAt
|
||||
FROM regions
|
||||
WHERE status = @Status
|
||||
@@ -50,10 +52,12 @@ public class RegionRepository : IRegionRepository
|
||||
const string sql = @"
|
||||
INSERT INTO regions (id, latitude, longitude, size_meters, zoom_level,
|
||||
status, csv_file_path, summary_file_path,
|
||||
tiles_downloaded, tiles_reused, created_at, updated_at)
|
||||
tiles_downloaded, tiles_reused, stitch_tiles,
|
||||
created_at, updated_at)
|
||||
VALUES (@Id, @Latitude, @Longitude, @SizeMeters, @ZoomLevel,
|
||||
@Status, @CsvFilePath, @SummaryFilePath,
|
||||
@TilesDownloaded, @TilesReused, @CreatedAt, @UpdatedAt)
|
||||
@TilesDownloaded, @TilesReused, @StitchTiles,
|
||||
@CreatedAt, @UpdatedAt)
|
||||
RETURNING id";
|
||||
|
||||
return await connection.ExecuteScalarAsync<Guid>(sql, region);
|
||||
@@ -73,6 +77,7 @@ public class RegionRepository : IRegionRepository
|
||||
summary_file_path = @SummaryFilePath,
|
||||
tiles_downloaded = @TilesDownloaded,
|
||||
tiles_reused = @TilesReused,
|
||||
stitch_tiles = @StitchTiles,
|
||||
updated_at = @UpdatedAt
|
||||
WHERE id = @Id";
|
||||
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
using Dapper;
|
||||
using Npgsql;
|
||||
using SatelliteProvider.DataAccess.Models;
|
||||
|
||||
namespace SatelliteProvider.DataAccess.Repositories;
|
||||
|
||||
public class RouteRepository : IRouteRepository
|
||||
{
|
||||
private readonly string _connectionString;
|
||||
|
||||
public RouteRepository(string connectionString)
|
||||
{
|
||||
_connectionString = connectionString;
|
||||
}
|
||||
|
||||
public async Task<RouteEntity?> GetByIdAsync(Guid id)
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString);
|
||||
const string sql = @"
|
||||
SELECT id, name, description, region_size_meters as RegionSizeMeters,
|
||||
zoom_level as ZoomLevel, total_distance_meters as TotalDistanceMeters,
|
||||
total_points as TotalPoints, created_at as CreatedAt, updated_at as UpdatedAt
|
||||
FROM routes
|
||||
WHERE id = @Id";
|
||||
|
||||
return await connection.QuerySingleOrDefaultAsync<RouteEntity>(sql, new { Id = id });
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<RoutePointEntity>> GetRoutePointsAsync(Guid routeId)
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString);
|
||||
const string sql = @"
|
||||
SELECT id, route_id as RouteId, sequence_number as SequenceNumber,
|
||||
latitude, longitude, point_type as PointType, segment_index as SegmentIndex,
|
||||
distance_from_previous as DistanceFromPrevious, created_at as CreatedAt
|
||||
FROM route_points
|
||||
WHERE route_id = @RouteId
|
||||
ORDER BY sequence_number";
|
||||
|
||||
return await connection.QueryAsync<RoutePointEntity>(sql, new { RouteId = routeId });
|
||||
}
|
||||
|
||||
public async Task<Guid> InsertRouteAsync(RouteEntity route)
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString);
|
||||
const string sql = @"
|
||||
INSERT INTO routes (id, name, description, region_size_meters, zoom_level,
|
||||
total_distance_meters, total_points, created_at, updated_at)
|
||||
VALUES (@Id, @Name, @Description, @RegionSizeMeters, @ZoomLevel,
|
||||
@TotalDistanceMeters, @TotalPoints, @CreatedAt, @UpdatedAt)
|
||||
RETURNING id";
|
||||
|
||||
return await connection.ExecuteScalarAsync<Guid>(sql, route);
|
||||
}
|
||||
|
||||
public async Task InsertRoutePointsAsync(IEnumerable<RoutePointEntity> points)
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString);
|
||||
const string sql = @"
|
||||
INSERT INTO route_points (id, route_id, sequence_number, latitude, longitude,
|
||||
point_type, segment_index, distance_from_previous, created_at)
|
||||
VALUES (@Id, @RouteId, @SequenceNumber, @Latitude, @Longitude,
|
||||
@PointType, @SegmentIndex, @DistanceFromPrevious, @CreatedAt)";
|
||||
|
||||
await connection.ExecuteAsync(sql, points);
|
||||
}
|
||||
|
||||
public async Task<int> UpdateRouteAsync(RouteEntity route)
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString);
|
||||
const string sql = @"
|
||||
UPDATE routes
|
||||
SET name = @Name,
|
||||
description = @Description,
|
||||
region_size_meters = @RegionSizeMeters,
|
||||
zoom_level = @ZoomLevel,
|
||||
total_distance_meters = @TotalDistanceMeters,
|
||||
total_points = @TotalPoints,
|
||||
updated_at = @UpdatedAt
|
||||
WHERE id = @Id";
|
||||
|
||||
return await connection.ExecuteAsync(sql, route);
|
||||
}
|
||||
|
||||
public async Task<int> DeleteRouteAsync(Guid id)
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString);
|
||||
const string sql = "DELETE FROM routes WHERE id = @Id";
|
||||
return await connection.ExecuteAsync(sql, new { Id = id });
|
||||
}
|
||||
|
||||
public async Task LinkRouteToRegionAsync(Guid routeId, Guid regionId)
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString);
|
||||
const string sql = @"
|
||||
INSERT INTO route_regions (route_id, region_id, created_at)
|
||||
VALUES (@RouteId, @RegionId, @CreatedAt)
|
||||
ON CONFLICT (route_id, region_id) DO NOTHING";
|
||||
|
||||
await connection.ExecuteAsync(sql, new { RouteId = routeId, RegionId = regionId, CreatedAt = DateTime.UtcNow });
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Guid>> GetRegionIdsByRouteAsync(Guid routeId)
|
||||
{
|
||||
using var connection = new NpgsqlConnection(_connectionString);
|
||||
const string sql = @"
|
||||
SELECT region_id
|
||||
FROM route_regions
|
||||
WHERE route_id = @RouteId";
|
||||
|
||||
return await connection.QueryAsync<Guid>(sql, new { RouteId = routeId });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user