mirror of
https://github.com/azaion/satellite-provider.git
synced 2026-06-22 15:41:13 +00:00
[AZ-375] [AZ-377] HashSet tile lookup + consolidate Earth constants
Batch 24 of 03-code-quality-refactoring run; closes the run. AZ-375 (C22): GoogleMapsDownloaderV2.DownloadTilesGridAsync now builds a HashSet<(int X, int Y, int Z)> once from existingTiles and tests Contains((x, y, zoomLevel)) per cell. Removes the per-cell FirstOrDefault tolerance scan and the unused _processingConfig .LatLonTolerance reference at this site. AZ-377 (C24): promote Earth + tile-pixel constants to a single home. GeoUtils now exposes EarthRadiusMeters, EarthEquatorial CircumferenceMeters, MetersPerDegreeLatitude as public const. MapConfig adds DefaultTileSizePixels (const) wired as the TileSizePixels property default. TileRepository and Google MapsDownloaderV2 read those constants instead of duplicating the literals 6378137, 40075016.686, 111000.0, and 256. Tests: +6 new (DownloaderRefactorTests, extended GeoUtils RefactorTests). 200/200 unit tests pass. Cumulative K=3 review (batches 22-24): PASS_WITH_WARNINGS, 4 Low findings only — see _docs/03_implementation/reviews/cumulative_review_22-24.md. Tooling fix: scripts/run-tests.sh --unit-only path now restores before testing (was failing on SixLabors resolution in clean container). Stripped stray BOM from MapConfig.cs to satisfy the .editorconfig charset gate. Updates _dependencies_table.md to reflect all 27 03-code-quality- refactoring tasks done; updates _autodev_state.md to refactor phase 5 (test-sync). Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
# Refactor: O(N) existing-tile lookup via HashSet
|
||||
|
||||
**Task**: AZ-375_refactor_on_existing_tile_lookup
|
||||
**Name**: HashSet-backed existing-tile membership test
|
||||
**Description**: Replace the linear-scan tolerance check in `GoogleMapsDownloaderV2.DownloadTilesGridAsync` with a `HashSet<(int x, int y, int z)>` lookup keyed on integer tile coordinates.
|
||||
**Complexity**: 2 points
|
||||
**Dependencies**: AZ-371 (C18) — the remaining `0.0001` tolerance becomes a config value where it actually applies (geofence polygon check)
|
||||
**Component**: Services.TileDownloader
|
||||
**Tracker**: AZ-375
|
||||
**Epic**: AZ-350
|
||||
|
||||
## Problem
|
||||
|
||||
`SatelliteProvider.Services.TileDownloader/GoogleMapsDownloaderV2.cs:245-265` does `existingTiles.FirstOrDefault(t => Math.Abs(t.Latitude - tileCenter.Lat) < 0.0001 && Math.Abs(t.Longitude - tileCenter.Lon) < 0.0001 && t.ZoomLevel == zoomLevel)` per grid cell. That's a linear scan per cell — fine for ~16 tiles, quadratic for big regions. The tolerance is also redundant: tile coordinates at a fixed zoom are integers, so an exact tuple compare is correct.
|
||||
|
||||
## Outcome
|
||||
|
||||
- O(N) lookup via `HashSet<(int TileX, int TileY, int Zoom)>`.
|
||||
- The magic `0.0001` tolerance at this site is gone (the other site — geofence polygon at `RouteService.cs:154` — is a real lat/lon tolerance and stays as config).
|
||||
- Behavior identical for any input that already produces correct output.
|
||||
- 37 unit + 5 smoke tests stay green.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Compute the integer `(TileX, TileY, Zoom)` for each row in `existingTiles` once, building the HashSet.
|
||||
- Replace the per-cell `FirstOrDefault` with `set.Contains((tileX, tileY, zoom))`.
|
||||
- Remove the unused `0.0001` literal at this site.
|
||||
|
||||
### Excluded
|
||||
- Touching the geofence polygon tolerance check.
|
||||
- Changing how `existingTiles` is fetched.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: HashSet membership replaces FirstOrDefault**
|
||||
Given the post-refactor source
|
||||
When `DownloadTilesGridAsync` is inspected
|
||||
Then it builds a HashSet once and tests membership per cell.
|
||||
|
||||
**AC-2: Magic 0.0001 removed at this site**
|
||||
Given the post-refactor `GoogleMapsDownloaderV2.cs`
|
||||
When grepped for `0.0001`
|
||||
Then matches are confined to non-tile-lookup contexts (or absent).
|
||||
|
||||
**AC-3: Tests stay green**
|
||||
Given the post-refactor build
|
||||
When `scripts/run-tests.sh --smoke` runs
|
||||
Then all 37 unit + 5 smoke scenarios pass.
|
||||
|
||||
## Constraints
|
||||
|
||||
- For inputs that produce correct output today, behavior is identical.
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
**Risk 1: existingTiles' lat/lon don't quantize cleanly back to integer tile coords**
|
||||
- *Risk*: floating-point drift could mean two rows for "the same tile" produce different integer coords.
|
||||
- *Mitigation*: convert via the same lat/lon→tile formula used to write them; if quantization concerns surface, add a regression test.
|
||||
|
||||
Full change entry: `_docs/04_refactoring/03-code-quality-refactoring/list-of-changes.md` (C22).
|
||||
@@ -0,0 +1,68 @@
|
||||
# Refactor: consolidate Earth-geometry constants and magic 111000
|
||||
|
||||
**Task**: AZ-377_refactor_consolidate_earth_constants
|
||||
**Name**: Single home for Earth + tile-pixel constants
|
||||
**Description**: Move Earth-geometry constants (`EarthRadiusMeters`, `EarthEquatorialCircumferenceMeters`, `MetersPerDegreeLatitude`) to `GeoUtils`; move `TileSizePixels` to `MapConfig`. Replace duplicate literals at all sites.
|
||||
**Complexity**: 2 points
|
||||
**Dependencies**: AZ-371 (C18 — TileSizePixels move into config)
|
||||
**Component**: Common + DataAccess + Services.TileDownloader
|
||||
**Tracker**: AZ-377
|
||||
**Epic**: AZ-350
|
||||
|
||||
## Problem
|
||||
|
||||
Three Earth-related constants drift across the codebase:
|
||||
- `GeoUtils.EARTH_RADIUS = 6378137` (m).
|
||||
- `GoogleMapsDownloaderV2.CalculateTileSizeInMeters: EARTH_CIRCUMFERENCE_METERS = 40075016.686`.
|
||||
- `TileRepository.GetTilesByRegionAsync: EARTH_CIRCUMFERENCE_METERS = 40075016.686` (duplicate).
|
||||
- `TileRepository.GetTilesByRegionAsync: 111000.0` (meters per degree latitude approximation, twice).
|
||||
- `TILE_SIZE_PIXELS = 256` at three sites (`TileRepository:83`, `GoogleMapsDownloaderV2:18`, `TileService:152`).
|
||||
|
||||
## Outcome
|
||||
|
||||
- Earth constants are named `public const`s on `GeoUtils` (or a sibling `GeoConstants` class).
|
||||
- Per-degree-latitude approximation has a single named source.
|
||||
- `TileSizePixels` lives on `MapConfig` (per C18).
|
||||
- All duplicate literal sites use the named constants.
|
||||
- Numerically identical results.
|
||||
- 37 unit + 5 smoke tests stay green.
|
||||
|
||||
## Scope
|
||||
|
||||
### Included
|
||||
- Add `public const double EarthRadiusMeters = 6378137d;`, `public const double EarthEquatorialCircumferenceMeters = 40075016.686d;`, `public const double MetersPerDegreeLatitude = 111000d;` (or refine to a more precise value if the existing usage allows).
|
||||
- Replace literal sites with the named constants.
|
||||
- Move `TileSizePixels` to `MapConfig` (depend on C18).
|
||||
|
||||
### Excluded
|
||||
- Switching to a different Earth model (e.g., WGS84 with full geodesic).
|
||||
- Refining constants beyond what's already in code.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
**AC-1: One source per constant**
|
||||
Given the post-refactor source
|
||||
When grepped for `6378137`, `40075016.686`, `111000`, and (after C18) `256`
|
||||
Then matches are confined to the named-constant declarations or `appsettings.json` defaults.
|
||||
|
||||
**AC-2: Numerically identical results**
|
||||
Given the existing region/route scenarios
|
||||
When the post-refactor code runs
|
||||
Then computed distances and tile-size results are byte-for-byte identical (within IEEE 754 tolerance).
|
||||
|
||||
**AC-3: Tests stay green**
|
||||
Given the post-refactor build
|
||||
When `scripts/run-tests.sh --smoke` runs
|
||||
Then all 37 unit + 5 smoke scenarios pass.
|
||||
|
||||
## Constraints
|
||||
|
||||
- No numerical drift — use the same literal values as before.
|
||||
|
||||
## Risks & Mitigation
|
||||
|
||||
**Risk 1: ordering with C18**
|
||||
- *Risk*: `TileSizePixels` move depends on C18 landing first.
|
||||
- *Mitigation*: this ticket declares C18 as a dependency.
|
||||
|
||||
Full change entry: `_docs/04_refactoring/03-code-quality-refactoring/list-of-changes.md` (C24).
|
||||
Reference in New Issue
Block a user