feat: Implement lazy hub expansion depth limiting with transfer depth limit of 5 (Task 14)
This commit is contained in:
100
internal/airports/airports.go
Normal file
100
internal/airports/airports.go
Normal file
@@ -0,0 +1,100 @@
|
||||
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
|
||||
}
|
||||
Reference in New Issue
Block a user