Move documentation to docs/ directory and improve terminology

- Move ARCHITECTURE.md and CLAUDE.md to docs/ directory
- Replace "real-time" terminology with accurate "low-latency" and "high-performance"
- Update README to reflect correct performance characteristics
- Add comprehensive ICAO country database with SQLite backend
- Fix display options positioning and functionality
- Add map scale controls and improved range ring visibility
- Enhance aircraft marker orientation and trail management

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ole-Morten Duesund 2025-08-24 16:24:46 +02:00
commit 20bdcf54ec
15 changed files with 746 additions and 67 deletions

View file

@ -26,6 +26,7 @@ import (
"sync"
"time"
"skyview/internal/icao"
"skyview/internal/modes"
)
@ -72,6 +73,9 @@ type AircraftState struct {
MLATSources []string `json:"mlat_sources"` // Sources providing MLAT position data
PositionSource string `json:"position_source"` // Source providing current position
UpdateRate float64 `json:"update_rate"` // Recent updates per second
Country string `json:"country"` // Country of registration
CountryCode string `json:"country_code"` // ISO country code
Flag string `json:"flag"` // Country flag emoji
}
// MarshalJSON provides custom JSON marshaling for AircraftState to format ICAO24 as hex.
@ -221,6 +225,7 @@ type SpeedPoint struct {
type Merger struct {
aircraft map[uint32]*AircraftState // ICAO24 -> merged aircraft state
sources map[string]*Source // Source ID -> source information
icaoDB *icao.Database // ICAO country lookup database
mu sync.RWMutex // Protects all maps and slices
historyLimit int // Maximum history points to retain
staleTimeout time.Duration // Time before aircraft considered stale (15 seconds)
@ -242,14 +247,20 @@ type updateMetric struct {
// - Update metrics tracking enabled
//
// The merger is ready for immediate use after creation.
func NewMerger() *Merger {
func NewMerger() (*Merger, error) {
icaoDB, err := icao.NewDatabase()
if err != nil {
return nil, fmt.Errorf("failed to initialize ICAO database: %w", err)
}
return &Merger{
aircraft: make(map[uint32]*AircraftState),
sources: make(map[string]*Source),
icaoDB: icaoDB,
historyLimit: 500,
staleTimeout: 15 * time.Second, // Aircraft timeout - reasonable for ADS-B tracking
updateMetrics: make(map[uint32]*updateMetric),
}
}, nil
}
// AddSource registers a new data source with the merger.
@ -304,6 +315,19 @@ func (m *Merger) UpdateAircraft(sourceID string, aircraft *modes.Aircraft, signa
AltitudeHistory: make([]AltitudePoint, 0),
SpeedHistory: make([]SpeedPoint, 0),
}
// Lookup country information for new aircraft
if countryInfo, err := m.icaoDB.LookupCountry(fmt.Sprintf("%06X", aircraft.ICAO24)); err == nil {
state.Country = countryInfo.Country
state.CountryCode = countryInfo.CountryCode
state.Flag = countryInfo.Flag
} else {
// Fallback to unknown if lookup fails
state.Country = "Unknown"
state.CountryCode = "XX"
state.Flag = "🏳️"
}
m.aircraft[aircraft.ICAO24] = state
m.updateMetrics[aircraft.ICAO24] = &updateMetric{
updates: make([]time.Time, 0),
@ -777,3 +801,14 @@ func calculateDistanceBearing(lat1, lon1, lat2, lon2 float64) (float64, float64)
return distance, bearing
}
// Close closes the merger and releases resources
func (m *Merger) Close() error {
m.mu.Lock()
defer m.mu.Unlock()
if m.icaoDB != nil {
return m.icaoDB.Close()
}
return nil
}