Commit Graph
32 Commits
Author SHA1 Message Date
atsunatsu 346803fe6e fix: normalize Maidenhead grid input to uppercase in mutual pass
- onStationAGrid/onStationBGrid store the trimmed upper-cased grid instead
  of the raw input (ol63 used to stay lowercase in the UI)
- drop the local latLonToGrid/gridToLatLon copies and reuse the domain
  QthConverter, removing the drift risk between two implementations
- inject computeDispatcher (default Dispatchers.Default, no behaviour
  change) so the pass computation is unit-testable on a test scheduler
- add MutualViewModelTest (15 cases): init prefill, grid/lat-lon linkage,
  error paths, main-list reuse, fallback search, sorting, clearError
2026-08-29 10:55:15 +08:00
atsunatsu cebe3b7ec4 refactor: move map access under passes 2026-08-22 18:35:53 +08:00
atsunatsu 12eed1d9a9 i18n: use string resources for mutual match page (zh/en) 2026-08-07 21:27:01 +08:00
atsunatsu b3859fbece i18n: translate '友台' to 'opposite' for clarity 2026-08-07 20:06:43 +08:00
atsunatsu 80a58bed61 i18n: localize mutual match page to English 2026-08-07 19:53:36 +08:00
atsunatsu a7b41c95c7 fix: improve match header and daily sun times
Match page UI:
- Always show a meaningful status line in the top bar instead of leaving the second row blank on first entry.
- Add a compact status chip for waiting, calculating, result, no-match, and error states.
- Remove the duplicate intro card so the first screen starts directly with station inputs.

Pass list sun times:
- Compute sunrise/sunset from each visible date group's 00:00 in the selected timezone.
- Avoid using an arbitrary pass AOS as the rise/set search start, which could jump later-day headers to the following day's events.
2026-08-03 21:38:57 +08:00
atsunatsu 1813e1bfa4 fix: refine mutual pass matching and radar overlay 2026-08-03 13:04:42 +08:00
atsunatsu 7e90071c4d fix: revert radar pager to Transceivers tab, default minElev to 0
- Radar pager now defaults to Transceivers tab (initialPage=0)
- Transceivers don't auto-expand (selectedUuid defaults to null)
- Mutual page default minElev changed from settings value to 0.0
- Display filters out portions below the minElev threshold
2026-08-03 03:58:45 +08:00
atsunatsu d1cc944be2 feat: filter mutual page curves to minElev window (satlover.de style)
Elevation curve chart and mutual radar plot now only show the portion
where both stations are above their respective minimum elevation.
The curves are filtered at display time, the pass search still uses
the 0° horizon boundary for consistency with the Passes page.
2026-08-03 03:47:25 +08:00
atsunatsu fb28283679 feat: default pager to SSTV, remove radar plot drag, filter B track by elevation>0 2026-08-03 03:44:37 +08:00
atsunatsu 81ae8772d2 feat: add 'current exact position' button for station A
Removed the automatic posA=stationPos override. Added a button
'当前精确位置' below the grid input that fills in the exact station
position from settings (lat/lon + grid). Users can now freely edit
the position fields and use the button when they want the exact
position.
2026-08-03 03:32:03 +08:00
atsunatsu 571145838d fix: gridToLatLon normalization bug + bidirectional grid/latlon sync
Root cause: gridToLatLon used (lon+180)%360-180 and (lat+90)%180-90
for normalization, treating grid values as from prime meridian/equator
when they are actually from IDL/South Pole. A 6-char grid like OL62AA
(112°E, 22°N) was returning -67.96°, -67.98° (Atlantic Ocean).

Also added bidirectional sync: entering a grid auto-fills lat/lon,
entering lat/lon auto-fills the 6-char grid, so users can verify.
2026-08-03 03:27:15 +08:00
atsunatsu 017b178f2e fix: use refineEdge with exact station position to get correct AOS/LOS boundaries 2026-08-03 03:15:39 +08:00
atsunatsu 670444858c fix: use getElevation for elevation sampling (same function as getLeoPass)
getFullPosition and getElevation both call calculateObs internally,
but the elevation values reported by the user (-60°) suggest they may
differ. Now elevation is computed via getElevation (same as getLeoPass),
while getFullPosition is only used for azimuth.
2026-08-03 03:13:11 +08:00
atsunatsu 7bdff5df81 fix: use passes list with corrected station position, fallback to independent search 2026-08-03 03:08:35 +08:00
atsunatsu df083840ac fix: use independent search algorithm directly, no passes list reuse
The passes list AOS/LOS times can be stale or computed for a different
station position, causing elevation curves to show -60° at pass start.
The independent search (refineEdge + sampleMutualPass) always computes
elevation for the actual positions. With posA now set to the exact
station position, the pass times should match the main page.
2026-08-03 03:03:08 +08:00
atsunatsu a0279bac17 fix: use pass AOS/LOS times directly without refineEdge
The refineEdge function re-computed boundaries using the grid-center
position (posA), which differs from the exact station position that
the passes list was computed with. This caused all passes to be
filtered out. Now we trust the pass list's AOS/LOS times directly
and just sample the elevation/azimuth curves.
2026-08-03 02:47:09 +08:00
atsunatsu 3d630041e1 chore: add debug info when mutual pass search finds nothing
Shows pass count and satellite count in the error message to help
diagnose why the main pass list yields no results.
2026-08-03 02:27:01 +08:00
atsunatsu ea92d3c150 fix: add fallback pass search when main pass list yields no results
If the main pass list (satelliteRepo.passes) is empty or the common
window check filters everything out, fall back to the independent
search algorithm so the user always gets results.
2026-08-03 02:23:51 +08:00
atsunatsu 86ee3dcbac fix: reuse main page pass list for mutual search
findMutualPasses was computing passes independently with its own
search algorithm, which produced different results from the main
page's getLeoPass. Now it directly reuses satelliteRepo.passes,
which is the same list shown on the main passes page. The only
additional computation is refining the common window for station B
and sampling elevation/azimuth curves.
2026-08-03 02:16:15 +08:00
atsunatsu 43788ba7a7 fix: mutual pass search now matches main radar pass definition
Root cause: mutual search used the min-elevation threshold (default 10°)
as the AOS/LOS boundary, while the main radar uses the 0° horizon
(getLeoPass). With identical stations the windows therefore never
matched. Also, an in-progress pass was counted as a new one.

- AOS/LOS boundaries now at the 0° horizon (refined to 1s)
- Skip in-progress mutual windows at search start (like getLeoPass)
- Filter requires BOTH stations to reach their min elevation
- Default min elevation follows the main radar passes setting
2026-08-03 02:04:13 +08:00
atsunatsu 1a3f1bb34c fix: radar track rendering bugs
- Elevation ring labels were inverted (90/60/30 from outer to inner);
  now 30/60/90 correctly from outer ring to center
- Split track paths at the 0/360° azimuth wrap in both MutualRadarView
  and main RadarView, so passes crossing due north no longer draw a
  line straight across the plot
2026-08-03 01:53:37 +08:00
atsunatsu 28fa373db0 feat: bidirectional drag sync between elevation curve and radar track
- ElevationCurveChart is now controlled (progress + onProgressChange)
- MutualRadarView shows shared time-cursor positions for both stations
  and is draggable/tappable to move the cursor
- MutualPassCard owns a single dragProgress feeding both charts, so
  dragging either chart moves the other in sync
2026-08-03 00:58:09 +08:00
atsunatsu 4ca33c37ad feat: keep mutual state across nav + overlay station-B track on main radar
- MutualViewModel is Activity-scoped, so returning from Radar keeps query results
- TrackSampleData gains time field for live cut-off
- Removed standalone mutual card from radar page
- RadarViewCompose draws optional dashed station-B track + current dot
- RadarScreen builds trackB from mutual data up to current time
2026-08-03 00:55:05 +08:00
atsunatsu bd42e643ea feat: dual-station radar track plot (satlover/satmatch style)
- MutualPass now carries TrackSample (azimuth/elevation for both stations)
- New MutualRadarView: polar plot with elevation rings (30/60/90),
  cardinal spokes, solid A-track vs dashed B-track, AOS/LOS markers
- Shown in expanded mutual pass card and radar page mutual card
2026-08-03 00:21:20 +08:00
atsunatsu 4baf3821e5 fix: elevation curve x-axis float precision loss
Absolute epoch millis (~1.7e12) exceeds Float precision (ULP ~131s
at that magnitude), so 5s-spaced samples collapsed onto identical
x coordinates, producing a stepped/jagged curve. Use Long relative
time deltas (sample - start) before converting to Float.
2026-08-02 23:36:59 +08:00
atsunatsu d7e1ce11c9 fix: smooth dual-station elevation curve
- Fix cubic Bezier control points (proper Catmull-Rom to Bezier conversion)
- Refine AOS/LOS more robustly by walking from edge into the pass window
- Still 5s sampling for smooth curves
2026-08-02 23:07:28 +08:00
atsunatsu f272e268ab fix: smooth elevation curves using cubic Bezier instead of lineTo
Replace Path.lineTo() with Path.cubicTo() using Catmull-Rom
to Bezier conversion for smooth elevation curves.
2026-08-02 22:10:17 +08:00
atsunatsu e59507a4d3 fix: smoother elevation curves with refined AOS/LOS and 5s sampling
- Reduce sample interval from 10s to 5s for smoother curves
- Add refineEdge() to find exact AOS/LOS at 1s resolution
- Curve now starts/ends at the correct horizon-crossing points
2026-08-02 21:59:51 +08:00
atsunatsu 0bae306312 fix: default station A grid, find all mutual passes, color toArgb()
- Pre-fill station A grid from settingsRepo.stationPosition
- Find ALL mutual passes per satellite (not just first)
- Fix Color.hashCode() -> Color.toArgb() for native canvas paint
- Use 2min gap between pass searches to avoid duplicates
2026-08-02 21:44:31 +08:00
atsunatsu 65f61a5147 fix: mutual pass elevation unit (radians->degrees) + grid input
Bug: OrbitalObject.getElevation() returns radians, but
MutualViewModel was comparing it directly with degree values
from the slider (10-90), causing no matches to be found.

Fix: add elevationDeg() helper that converts to degrees.

Also add Maidenhead grid square input support (4/6/8 chars)
alongside existing lat/lon fields. Grid takes priority when
filled.
2026-08-02 21:36:44 +08:00
atsunatsu 1064dc739e feat: add mutual pass query with dual-station elevation curve
Port satlover.de dual-station pass matching feature:
- New feature/mutual module with mutual pass data model
- MutualViewModel: compute overlapping passes for two stations
- ElevationCurveChart: Canvas-based dual elevation curve with drag
- MutualScreen: input form + results with expandable cards
- Navigation: add Mutual tab to bottom navigation bar
- i18n: add Chinese/English strings for new feature
2026-08-02 21:22:42 +08:00