Files
satellite-provider/SatelliteProvider.Services.RouteManagement/RouteSummaryWriter.cs
T
Oleksandr Bezdieniezhnykh 6f23120c49 [AZ-364] [AZ-360] Refactor C11+C08: decompose RouteProcessingService
Extracts RouteRegionMatcher, RouteCsvWriter, RouteSummaryWriter,
RouteImageRenderer, TilesZipBuilder, RegionFileCleaner from the
~750-LOC RouteProcessingService god-class. Moves TileInfo to its
own file as a sealed record. Replaces IServiceProvider scope-
locator with a direct IRegionService injection (folds AZ-360 / C08).
Updates DI registration and tests.

Tests: 133 / 133 unit + 5 / 5 smoke green; integration suite exit 0.
Pixel-equivalent stitched route image and byte-equivalent CSV /
summary / ZIP outputs verified through the smoke run.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-11 03:12:49 +03:00

77 lines
3.1 KiB
C#

using System.Text;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using SatelliteProvider.Common.Configs;
using SatelliteProvider.DataAccess.Models;
namespace SatelliteProvider.Services.RouteManagement;
// AZ-364 / C11: extracted from RouteProcessingService.GenerateRouteSummaryAsync.
// Owns the route_<id>_summary.txt path and the StringBuilder block that
// describes the route, tile statistics, and produced files. Output content
// preserved verbatim to satisfy AC-2 (byte-identical for existing scenarios).
public class RouteSummaryWriter
{
private readonly StorageConfig _storageConfig;
private readonly ILogger<RouteSummaryWriter> _logger;
public RouteSummaryWriter(IOptions<StorageConfig> storageConfig, ILogger<RouteSummaryWriter> logger)
{
ArgumentNullException.ThrowIfNull(storageConfig);
_storageConfig = storageConfig.Value;
_logger = logger;
}
public async Task<string> WriteAsync(
RouteEntity route,
int uniqueTiles,
int totalTilesFromRegions,
int duplicateTiles,
string? tilesZipPath,
CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(route);
Directory.CreateDirectory(_storageConfig.ReadyDirectory);
var filePath = Path.Combine(_storageConfig.ReadyDirectory, $"route_{route.Id}_summary.txt");
var summary = new StringBuilder();
summary.AppendLine("Route Maps Summary");
summary.AppendLine("==================");
summary.AppendLine($"Route ID: {route.Id}");
summary.AppendLine($"Route Name: {route.Name}");
if (!string.IsNullOrEmpty(route.Description))
{
summary.AppendLine($"Description: {route.Description}");
}
summary.AppendLine($"Total Points: {route.TotalPoints}");
summary.AppendLine($"Total Distance: {route.TotalDistanceMeters:F2} meters");
summary.AppendLine($"Region Size: {route.RegionSizeMeters:F0} meters");
summary.AppendLine($"Zoom Level: {route.ZoomLevel}");
summary.AppendLine();
summary.AppendLine("Tile Statistics:");
summary.AppendLine($"- Unique Tiles: {uniqueTiles}");
summary.AppendLine($"- Total Tiles from Regions: {totalTilesFromRegions}");
summary.AppendLine($"- Duplicate Tiles (overlap): {duplicateTiles}");
summary.AppendLine();
summary.AppendLine("Files Created:");
summary.AppendLine($"- CSV: route_{route.Id}_ready.csv");
summary.AppendLine($"- Summary: route_{route.Id}_summary.txt");
if (route.RequestMaps)
{
summary.AppendLine($"- Stitched Map: route_{route.Id}_stitched.jpg");
}
if (tilesZipPath != null)
{
summary.AppendLine($"- Tiles ZIP: route_{route.Id}_tiles.zip");
}
summary.AppendLine();
summary.AppendLine($"Completed: {DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC");
await File.WriteAllTextAsync(filePath, summary.ToString(), cancellationToken);
_logger.LogInformation("Route summary generated: {FilePath}", filePath);
return filePath;
}
}