package airports import ( "sort" ) // StationNeighbor represents a neighboring station that can be used as a fallback // when the main station is closed. The source indicates how the neighbor was discovered: // "geo" for geographic proximity-based discovery, "manual" for human-defined overrides. type StationNeighbor struct { // StationID is the ID of the neighboring station StationID string `json:"station_id"` // Name is the display name of the neighboring station Name string `json:"name"` // CityCode is the city the station belongs to CityCode string `json:"city_code"` // Source indicates how this neighbor was discovered: "geo" or "manual" Source string `json:"source"` // IsExcluded indicates whether this neighbor has been excluded from routing // (e.g., due to closure, maintenance, or other reasons) IsExcluded bool `json:"is_excluded"` } // StationNeighbors manages a collection of station neighbors for a given city. // It supports both geo-discovered and manually-defined neighbors. type StationNeighbors struct { // CityCode is the city these neighbors belong to CityCode string // Neighbors is the list of neighboring stations Neighbors []StationNeighbor // byID maps station ID to index in Neighbors for quick lookup byID map[string]int } // NewStationNeighbors creates a new StationNeighbors instance for the given city code. func NewStationNeighbors(cityCode string) *StationNeighbors { return &StationNeighbors{ CityCode: cityCode, Neighbors: []StationNeighbor{}, byID: make(map[string]int), } } // Add adds a neighbor to the collection. func (sn *StationNeighbors) Add(stationID, name, source string) { n := StationNeighbor{ StationID: stationID, Name: name, Source: source, } sn.Neighbors = append(sn.Neighbors, n) sn.byID[stationID] = len(sn.Neighbors) - 1 } // MarkExcluded marks a neighbor as excluded from routing. func (sn *StationNeighbors) MarkExcluded(stationID string) { if idx, ok := sn.byID[stationID]; ok { sn.Neighbors[idx].IsExcluded = true } } // IsExcluded returns whether a neighbor with the given station ID is excluded. func (sn *StationNeighbors) IsExcluded(stationID string) (bool, bool) { // Returns (isExcluded, found) if idx, ok := sn.byID[stationID]; ok { return sn.Neighbors[idx].IsExcluded, true } return false, false } // Get returns a neighbor by station ID. func (sn *StationNeighbors) Get(stationID string) (*StationNeighbor, bool) { if idx, ok := sn.byID[stationID]; ok { return &sn.Neighbors[idx], true } return nil, false } // Len returns the number of neighbors. func (sn *StationNeighbors) Len() int { return len(sn.Neighbors) } // Sort sorts neighbors by name. func (sn *StationNeighbors) Sort() { sort.Slice(sn.Neighbors, func(i, j int) bool { return sn.Neighbors[i].Name < sn.Neighbors[j].Name }) } // GetNonExcluded returns neighbors that are not excluded. func (sn *StationNeighbors) GetNonExcluded() []StationNeighbor { var result []StationNeighbor for _, n := range sn.Neighbors { if !n.IsExcluded { result = append(result, n) } } return result }