Implement multi-frame radar capture with configurable cropping

- Capture all 7 radar frames (0-6) instead of single screenshot
- Store frames in folder-based cache structure with metadata
- Extract and store minutesAgo for each frame from page display
- Add configurable screenshot cropping (default: 200px left/right)
- Fix step numbering to use whole numbers (1-22)
- Add scrubber position verification before frame capture
- Handle modal overlay blocking step forward button clicks
- Only create debug folders when scraping is actually needed
- Update API endpoints to return JSON with frame URLs
- Add separate endpoints for individual frame images
This commit is contained in:
2025-12-07 12:51:44 +10:00
parent f6366bf346
commit 41e1f6d685
16 changed files with 950 additions and 171 deletions
+55 -6
View File
@@ -5,9 +5,58 @@ namespace BomLocalService.Utilities;
public static class ResponseBuilder
{
/// <summary>
/// Creates a RadarScreenshotResponse from a file path and metadata
/// Creates a RadarResponse from a cache folder path, frames, and metadata
/// </summary>
public static RadarScreenshotResponse CreateRadarScreenshotResponse(
public static RadarResponse CreateRadarResponse(
string cacheFolderPath,
List<RadarFrame> frames,
LastUpdatedInfo? metadata = null,
string? suburb = null,
string? state = null)
{
var folderInfo = new DirectoryInfo(cacheFolderPath);
var lastWriteTime = folderInfo.Exists
? folderInfo.LastWriteTime
: DateTime.UtcNow;
// Generate URLs for each frame if suburb and state are provided
if (!string.IsNullOrEmpty(suburb) && !string.IsNullOrEmpty(state))
{
var encodedSuburb = Uri.EscapeDataString(suburb);
var encodedState = Uri.EscapeDataString(state);
foreach (var frame in frames)
{
frame.ImageUrl = $"/api/radar/{encodedSuburb}/{encodedState}/frame/{frame.FrameIndex}";
}
}
if (metadata == null)
{
return new RadarResponse
{
Frames = frames,
LastUpdated = lastWriteTime,
ObservationTime = DateTime.UtcNow,
ForecastTime = DateTime.UtcNow
};
}
return new RadarResponse
{
Frames = frames,
LastUpdated = lastWriteTime,
ObservationTime = metadata.ObservationTime,
ForecastTime = metadata.ForecastTime,
WeatherStation = metadata.WeatherStation,
Distance = metadata.Distance
};
}
/// <summary>
/// Legacy method for backward compatibility - creates response with single frame
/// </summary>
[Obsolete("Use CreateRadarResponse with cacheFolderPath and frames")]
public static RadarResponse CreateRadarResponse(
string imagePath,
LastUpdatedInfo? metadata = null)
{
@@ -17,18 +66,18 @@ public static class ResponseBuilder
if (metadata == null)
{
return new RadarScreenshotResponse
return new RadarResponse
{
ImagePath = imagePath,
Frames = new List<RadarFrame>(),
LastUpdated = lastWriteTime,
ObservationTime = DateTime.UtcNow,
ForecastTime = DateTime.UtcNow
};
}
return new RadarScreenshotResponse
return new RadarResponse
{
ImagePath = imagePath,
Frames = new List<RadarFrame>(),
LastUpdated = lastWriteTime,
ObservationTime = metadata.ObservationTime,
ForecastTime = metadata.ForecastTime,