some custom stuff

This commit is contained in:
2025-11-15 00:23:48 +01:00
parent 4dbbd30d4d
commit c189e3f59a
19 changed files with 1116 additions and 831 deletions

217
cmd/planner/csa.go Normal file
View File

@@ -0,0 +1,217 @@
package main
// import (
// "sort"
// "time"
// "git.tornberg.me/go-gtfs/pkg/reader"
// "git.tornberg.me/go-gtfs/pkg/types"
// )
// // Connection represents a single leg of a trip between two stops.
// type CSAConnection struct {
// DepartureStopID string
// ArrivalStopID string
// DepartureTime types.SecondsAfterMidnight
// ArrivalTime types.SecondsAfterMidnight
// TripID string
// }
// // CSAPlanner uses the Connection Scan Algorithm for routing.
// type CSAPlanner struct {
// *reader.TripData
// connections []CSAConnection
// }
// // NewCSAPlanner creates and preprocesses data for the Connection Scan Algorithm.
// func NewCSAPlanner(data *reader.TripData) *CSAPlanner {
// p := &CSAPlanner{
// TripData: data,
// }
// p.preprocess()
// return p
// }
// // preprocess creates a sorted list of all connections.
// func (p *CSAPlanner) preprocess() {
// p.connections = make([]CSAConnection, 0)
// for tripID, trip := range p.Trips {
// sts := trip.Stops
// sort.Slice(sts, func(i, j int) bool {
// return sts[i].StopSequence < sts[j].StopSequence
// })
// for i := 0; i < len(sts)-1; i++ {
// from := sts[i]
// to := sts[i+1]
// if from.DepartureTime < to.ArrivalTime {
// p.connections = append(p.connections, CSAConnection{
// DepartureStopID: from.StopId,
// ArrivalStopID: to.StopId,
// DepartureTime: from.DepartureTime,
// ArrivalTime: to.ArrivalTime,
// TripID: tripID,
// })
// }
// }
// }
// // Sort connections by departure time, which is crucial for the algorithm.
// sort.Slice(p.connections, func(i, j int) bool {
// return p.connections[i].DepartureTime < p.connections[j].DepartureTime
// })
// }
// // FindRoute finds the best route using the Connection Scan Algorithm.
// func (p *CSAPlanner) FindRoute(startStopID, endStopID string, when time.Time) *Route {
// earliestArrival := make(map[string]time.Time)
// journeyPointers := make(map[string]CSAConnection) // To reconstruct the path
// startTime := types.AsSecondsAfterMidnight(when)
// day := when.Truncate(24 * time.Hour)
// // Initialize earliest arrival times
// for stopID := range p.Stops {
// earliestArrival[stopID] = time.Time{} // Zero time represents infinity
// }
// earliestArrival[startStopID] = when
// // Find the starting point in the connections array
// firstConnectionIdx := sort.Search(len(p.connections), func(i int) bool {
// return p.connections[i].DepartureTime >= startTime
// })
// // Scan through connections
// for i := firstConnectionIdx; i < len(p.connections); i++ {
// conn := p.connections[i]
// depStopArrival, reachable := earliestArrival[conn.DepartureStopID]
// if !reachable || depStopArrival.IsZero() {
// continue // Cannot reach the departure stop of this connection yet
// }
// connDepartureTime := day.Add(time.Duration(conn.DepartureTime) * time.Second)
// if connDepartureTime.Before(depStopArrival) {
// connDepartureTime = connDepartureTime.Add(24 * time.Hour) // Next day
// }
// if !depStopArrival.IsZero() && connDepartureTime.After(depStopArrival) {
// // We can catch this connection
// connArrivalTime := day.Add(time.Duration(conn.ArrivalTime) * time.Second)
// if connArrivalTime.Before(connDepartureTime) {
// connArrivalTime = connArrivalTime.Add(24 * time.Hour)
// }
// // Check if this connection offers a better arrival time at the destination stop
// currentBestArrival, hasArrival := earliestArrival[conn.ArrivalStopID]
// if !hasArrival || currentBestArrival.IsZero() || connArrivalTime.Before(currentBestArrival) {
// earliestArrival[conn.ArrivalStopID] = connArrivalTime
// journeyPointers[conn.ArrivalStopID] = conn
// }
// }
// }
// // Reconstruct the path if the destination was reached
// if _, ok := journeyPointers[endStopID]; !ok {
// return nil // No path found
// }
// return p.reconstructCSAPath(startStopID, endStopID, journeyPointers)
// }
// // reconstructCSAPath builds the route from the journey pointers.
// func (p *CSAPlanner) reconstructCSAPath(startStopID, endStopID string, pointers map[string]CSAConnection) *Route {
// var path []CSAConnection
// currentStopID := endStopID
// for currentStopID != startStopID {
// conn, ok := pointers[currentStopID]
// if !ok {
// break // Should not happen if a path was found
// }
// path = append([]CSAConnection{conn}, path...)
// currentStopID = conn.DepartureStopID
// }
// if len(path) == 0 {
// return nil
// }
// // Group connections into legs
// var legs []Leg
// if len(path) > 0 {
// currentLeg := p.connectionToLeg(path[0])
// for i := 1; i < len(path); i++ {
// if path[i].TripID == currentLeg.TripID {
// // Continue the current leg
// currentLeg.To = path[i].ArrivalStopID
// currentLeg.ToStop = p.GetStop(currentLeg.To)
// currentLeg.Stops = append(currentLeg.Stops, currentLeg.To)
// } else {
// // New leg
// legs = append(legs, *currentLeg)
// currentLeg = p.connectionToLeg(path[i])
// }
// }
// legs = append(legs, *currentLeg)
// }
// return &Route{Legs: legs}
// }
// func (p *CSAPlanner) connectionToLeg(conn CSAConnection) *Leg {
// trip := p.GetTrip(conn.TripID)
// route := p.GetRoute(trip.RouteId)
// return &Leg{
// TripID: conn.TripID,
// From: conn.DepartureStopID,
// To: conn.ArrivalStopID,
// FromStop: p.GetStop(conn.DepartureStopID),
// ToStop: p.GetStop(conn.ArrivalStopID),
// Trip: trip,
// Agency: p.GetAgency(route.AgencyID),
// Route: route,
// Stops: []string{conn.DepartureStopID, conn.ArrivalStopID},
// }
// }
// func (p *CSAPlanner) GetRoute(routeId string) *types.Route {
// if routeId == "" {
// return nil
// }
// route, ok := p.Routes[routeId]
// if !ok {
// return nil
// }
// return route
// }
// func (p *CSAPlanner) GetAgency(agencyId string) *types.Agency {
// if agencyId == "" {
// return nil
// }
// agency, ok := p.Agencies[agencyId]
// if !ok {
// return nil
// }
// return agency
// }
// func (p *CSAPlanner) GetTrip(tripId string) *types.Trip {
// if tripId == "" {
// return nil
// }
// trip, ok := p.Trips[tripId]
// if !ok {
// return nil
// }
// return trip
// }
// func (p *CSAPlanner) GetStop(stopID string) *types.Stop {
// if stopID == "" {
// return nil
// }
// stop, ok := p.Stops[stopID]
// if !ok {
// return nil
// }
// return stop
// }