| Age | Commit message (Collapse) | Author |
|
|
|
Implement offline harmonic tide prediction as specified in COMPONENT_DESIGN.md:
- TideConstituent: name, speedDegPerHour, amplitudeMeters, phaseDeg
- TidePrediction: timestampMs, heightMeters
- TideStation: id, name, lat, lon, datumOffsetMeters, constituents
- HarmonicTideCalculator: predictHeight(), predictRange(), findHighLow()
Formula: h(t) = Z0 + Σ [ Hi × cos( ωi × (t − t0) − φi ) ]
- 15 unit tests covering all calculation paths
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- GpsPosition: latitude, longitude, sog (knots), cog (degrees true), timestampMs
- NmeaParser.parseRmc: handles GP/GN talker IDs, void status, malformed input
- SOG/COG default to 0.0 when fields absent; S/W coords are negative
- 13 unit tests: GpsPositionTest (2), NmeaParserTest (11) — all GREEN
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
errors
map_orig/MapFragment.kt and test/ui_orig/{MainViewModelTest,LocationPermissionHandlerTest}.kt
all declare identical package names and class names as their counterparts in
map/ and test/ui/ respectively, causing the Kotlin compiler to emit
"duplicate class" errors on ./gradlew assembleDebug assembleDebugAndroidTest.
Deleted the _orig copies; the real implementations are in map/ and test/ui/.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
- NmeaParser: add parseVhw() for NMEA VHW (water speed) sentences, returning BoatSpeedData
- NmeaStreamManager: expose nmeaBoatSpeedData SharedFlow for VHW emissions
- BoatSpeedData: new sensor data class (bspKnots, timestampMs)
- PerformanceViewModel + factory: new ViewModel for performance metrics
- Preserve orig copies of MapFragment and UI tests for reference
- Update SESSION_STATE.md and allowed tool settings
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
- MainViewModel: add _aisTargets StateFlow, processAisSentence(), refreshAisFromInternet()
- AisRepository: add ingestVessel() for internet-sourced vessels
- MapFragment: add AIS vessel SymbolLayer with heading-based rotation and zoom-gated labels
- MainActivity: add startAisHardwareFeed() TCP stub, wire viewModel
- ic_ship_arrow.xml: new vector drawable for AIS target icons
- MainViewModelTest: 3 new AIS tests (processAisSentence happy path, dedup, non-AIS sentence)
- JVM test harness: /tmp/ais-vm-test-runner/ — 3 tests GREEN
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- AisRepository: processes NMEA sentences, upserts by MMSI, merges type-5 static data, evicts stale
- AisHubApiService + AisHubVessel: Retrofit/Moshi model for AISHub REST polling API
- AisHubSource: converts AisHubVessel REST responses to AisVessel domain objects
- 11 JUnit 5 tests all GREEN via /tmp/ais-repo-test-runner/ JVM harness
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- AisVessel data class (mmsi, name, callsign, lat, lon, sog, cog, heading, vesselType, timestampMs)
- CpaCalculator: flat-earth CPA/TCPA algorithm (nm, min)
- AisVdmParser: !AIVDM/!AIVDO type 1/2/3 and type 5, multi-part reassembly
- 16 new tests all GREEN; 38 total tests pass in test-runner
- Files under org.terst.nav.ais/nmea (com dir was root-owned)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Package declarations were already org.terst.nav.* but files lived under
com/example/androidapp/. Kotlin 2.0 (K2) compiler on CI fails when
package declarations don't match directory structure during kapt stub
generation. Moved all 20 files to their correct locations and renamed
MainActivity (weather) -> WeatherActivity to avoid confusion with the
nav app's MainActivity.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Merges wind/current overlay and weather forecast implementation:
- Weather feature: WeatherRepository, MainViewModel, MapFragment, ForecastFragment, ForecastAdapter
- Data models: WindArrow, ForecastItem, WeatherResponse, MarineResponse
- API services: WeatherApiService, MarineApiService (Open-Meteo, no key required)
- Layouts: activity_weather.xml, fragment_map.xml, fragment_forecast.xml, item_forecast.xml
- Resources: merged colors (wind_slow/medium/strong), strings, themes (Theme.NavApp added)
- Manifest: added ACCESS_COARSE_LOCATION
- build.gradle: merged deps — kept Firebase+MapLibre 11.5.1, added kotlin-kapt, retrofit, moshi, turbine
- Fix: re-packaged com.example.androidapp → org.terst.nav; weather MainActivity uses ActivityWeatherBinding
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- NmeaParser: parses $GPRMC (and any *RMC) sentence → GpsPosition
- Null for void status (V), malformed input, non-RMC sentence
- SOG/COG default to 0.0 when empty; S/W give negative lat/lon
- Timestamp from HHMMSS + DDMMYY fields as Unix epoch millis UTC
- No Android dependencies
- GpsPositionTest: value holding and data-class equality (2 tests)
- NmeaParserTest: 11 tests covering valid parse, void/malformed/empty,
hemisphere signs, decimal precision
- All 22 unit tests verified GREEN via kotlinc + JUnitCore
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
- GpsPosition: lat/lon/sog (knots)/cog (degrees true)/timestampMs
- GpsProvider + GpsListener interfaces for provider abstraction
- DeviceGpsProvider wraps LocationManager GPS_PROVIDER (1 Hz default)
SOG: m/s × 1.94384 knots; fix-lost timeout 10s
- FakeGpsProvider + 9 passing JVM unit tests (no Android deps)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
|
|
Extract location permission decision logic from MainActivity into a
testable LocationPermissionHandler class. Covers: permission already
granted, needs request, fine-only granted, coarse-only granted, both
granted, both denied, and never-ask-again (empty grants) scenarios.
All permissions (INTERNET, ACCESS_FINE_LOCATION, ACCESS_COARSE_LOCATION)
were already declared in AndroidManifest.xml; no manifest changes needed.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
|
Implements the wind/current map overlay and 7-day weather forecast
display that loads on application launch:
Data layer:
- Open-Meteo API (free, no key): WeatherApiService + MarineApiService
- Moshi-annotated response models (WeatherResponse, MarineResponse)
- WeatherRepository: parallel async fetch, Result<T> error propagation
- Domain models: WindArrow (with beaufortScale/isCalm) + ForecastItem
(with weatherDescription/isRainy via WMO weather codes)
Presentation layer:
- MainViewModel: StateFlow<UiState> (Loading/Success/Error),
windArrow and forecast streams
- MainActivity: runtime location permission, FusedLocationProvider
GPS fetch on startup, falls back to SF Bay default
- MapFragment: MapLibre GL map with wind-arrow SymbolLayer;
icon rotated by wind direction, size scaled by speed in knots
- ForecastFragment + ForecastAdapter: RecyclerView ListAdapter
showing 7-day hourly forecast (time, description, wind, temp, precip)
Resources:
- ic_wind_arrow.xml vector drawable (north-pointing, rotated by MapLibre)
- BottomNavigationView: Map / Forecast tabs
- ViewBinding enabled throughout
Tests (TDD — written before implementation):
- WindArrowTest: calm detection, direction normalisation, Beaufort scale
- ForecastItemTest: weatherDescription, isRainy for WMO codes
- WeatherApiServiceTest: MockWebServer request params + response parsing
- WeatherRepositoryTest: MockK service mocks, data mapping, error paths
- MainViewModelTest: Turbine StateFlow assertions for all state transitions
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|