123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- // SPDX-FileCopyrightText: Adam Evyčędo
- //
- // SPDX-License-Identifier: AGPL-3.0-or-later
- package traffic
- import (
- pb "apiote.xyz/p/szczanieckiej/gtfs_rt/transit_realtime"
- "log"
- "sync"
- "time"
- "golang.org/x/text/language"
- )
- type BlockingError struct {
- cause error
- }
- func (e BlockingError) Error() string {
- return e.cause.Error()
- }
- type Alerts struct {
- ByLine map[string][]uint
- ByTrip map[string][]uint
- ByLineType map[LineType][]uint
- ByStop map[string][]uint
- ByAgency map[string][]uint
- Alerts []Alert
- }
- type SpecificAlert struct {
- Header string
- Description string
- URL string
- Cause AlertCause
- Effect AlertEffect
- }
- type Alert struct {
- TimeRanges [][2]time.Time
- Headers map[language.Tag]string
- Descriptions map[language.Tag]string
- URLs map[language.Tag]string
- Cause AlertCause
- Effect AlertEffect
- }
- type AlertCause uint
- const (
- CAUSE_UNKNOWN AlertCause = 0
- CAUSE_OTHER AlertCause = 1
- CAUSE_TECHNICAL_PROBLEM AlertCause = 2
- CAUSE_STRIKE AlertCause = 3
- CAUSE_DEMONSTRATION AlertCause = 4
- CAUSE_ACCIDENT AlertCause = 5
- CAUSE_HOLIDAY AlertCause = 6
- CAUSE_WEATHER AlertCause = 7
- CAUSE_MAINTENANCE AlertCause = 8
- CAUSE_CONSTRUCTION AlertCause = 9
- CAUSE_POLICE_ACTIVITY AlertCause = 10
- CAUSE_MEDICAL_EMERGENCY AlertCause = 11
- )
- func alertCauseOfGtfs(v *pb.Alert_Cause) AlertCause {
- switch v {
- case pb.Alert_UNKNOWN_CAUSE.Enum():
- return CAUSE_UNKNOWN
- case pb.Alert_OTHER_CAUSE.Enum():
- return CAUSE_OTHER
- case pb.Alert_TECHNICAL_PROBLEM.Enum():
- return CAUSE_TECHNICAL_PROBLEM
- case pb.Alert_STRIKE.Enum():
- return CAUSE_STRIKE
- case pb.Alert_DEMONSTRATION.Enum():
- return CAUSE_DEMONSTRATION
- case pb.Alert_ACCIDENT.Enum():
- return CAUSE_ACCIDENT
- case pb.Alert_HOLIDAY.Enum():
- return CAUSE_HOLIDAY
- case pb.Alert_WEATHER.Enum():
- return CAUSE_WEATHER
- case pb.Alert_MAINTENANCE.Enum():
- return CAUSE_MAINTENANCE
- case pb.Alert_CONSTRUCTION.Enum():
- return CAUSE_CONSTRUCTION
- case pb.Alert_POLICE_ACTIVITY.Enum():
- return CAUSE_POLICE_ACTIVITY
- case pb.Alert_MEDICAL_EMERGENCY.Enum():
- return CAUSE_MEDICAL_EMERGENCY
- default:
- return CAUSE_UNKNOWN
- }
- }
- type AlertEffect uint
- const (
- EFFECT_UNKNOWN AlertEffect = 0
- EFFECT_OTHER AlertEffect = 1
- EFFECT_NO_SERVICE AlertEffect = 2
- EFFECT_REDUCED_SERVICE AlertEffect = 3
- EFFECT_SIGNIFICANT_DELAYS AlertEffect = 4
- EFFECT_DETOUR AlertEffect = 5
- EFFECT_ADDITIONAL_SERVICE AlertEffect = 6
- EFFECT_MODIFIED_SERVICE AlertEffect = 7
- EFFECT_STOP_MOVED AlertEffect = 8
- EFFECT_NONE AlertEffect = 9
- EFFECT_ACCESSIBILITY_ISSUE AlertEffect = 10
- )
- func alertEffectOfGtfs(v *pb.Alert_Effect) AlertEffect {
- switch v {
- case pb.Alert_UNKNOWN_EFFECT.Enum():
- return EFFECT_UNKNOWN
- case pb.Alert_OTHER_EFFECT.Enum():
- return EFFECT_OTHER
- case pb.Alert_NO_SERVICE.Enum():
- return EFFECT_NO_SERVICE
- case pb.Alert_REDUCED_SERVICE.Enum():
- return EFFECT_REDUCED_SERVICE
- case pb.Alert_SIGNIFICANT_DELAYS.Enum():
- return EFFECT_SIGNIFICANT_DELAYS
- case pb.Alert_DETOUR.Enum():
- return EFFECT_DETOUR
- case pb.Alert_ADDITIONAL_SERVICE.Enum():
- return EFFECT_ADDITIONAL_SERVICE
- case pb.Alert_MODIFIED_SERVICE.Enum():
- return EFFECT_MODIFIED_SERVICE
- case pb.Alert_STOP_MOVED.Enum():
- return EFFECT_STOP_MOVED
- case pb.Alert_NO_EFFECT.Enum():
- return EFFECT_NONE
- case pb.Alert_ACCESSIBILITY_ISSUE.Enum():
- return EFFECT_ACCESSIBILITY_ISSUE
- default:
- return EFFECT_UNKNOWN
- }
- }
- // ............ feedID trip/stop
- var updates map[string]map[string][]Update
- var alerts map[string]Alerts
- var vehicleStatuses map[string]map[string]VehicleStatus
- var cacheMx sync.Mutex
- func GetAlerts(stopID, stopCode string, tripOffset int, ctx Context, t *Traffic, languages []language.Tag) []SpecificAlert {
- feedInfo, err := getFeedInfo(ctx.DataHome, ctx.FeedID, ctx.Version)
- if err != nil {
- log.Printf("while getting feedInfo: %v\n", err)
- feedInfo = FeedInfo{}
- }
- var function func(string, string, string, Context, *Traffic) ([]Alert, error)
- if feedInfo.Name != "" {
- if _, ok := feedInfo.RealtimeFeeds[ALERTS]; ok {
- function = getGtfsRealtimeAlerts
- } else if isLuaAlertsScript(ctx) {
- function = getLuaRealtimeAlerts
- } else {
- return []SpecificAlert{}
- }
- }
- tripID := ""
- if tripOffset > 0 {
- file, err := openTrips(ctx)
- if err != nil {
- log.Printf("while opening trips: %v\n", err)
- return []SpecificAlert{}
- }
- defer file.Close()
- trip, err := GetTripByOffset(file, uint(tripOffset), ctx)
- if err != nil {
- log.Printf("while getting trip: %v\n", err)
- return []SpecificAlert{}
- }
- tripID = trip.Id
- }
- if function != nil {
- alerts, err := function(stopID, stopCode, tripID, ctx, t)
- if err != nil {
- log.Printf("while getting alerts: %v\n", err)
- return []SpecificAlert{}
- }
- return selectSpecificAlerts(alerts, languages)
- }
- return []SpecificAlert{}
- }
- func getVehiclePositions(ctx Context, t *Traffic, lb, rt Position) []VehicleStatus {
- feedInfo, err := getFeedInfo(ctx.DataHome, ctx.FeedID, ctx.Version)
- if err != nil {
- log.Printf("while getting feedInfo: %v\n", err)
- feedInfo = FeedInfo{}
- }
- var function func(Context, Position, Position) ([]VehicleStatus, error)
- if feedInfo.Name != "" {
- if _, ok := feedInfo.RealtimeFeeds[VEHICLE_POSITIONS]; ok {
- function = getGtfsRealtimeVehicles
- } else if isLuaVehiclesScript(ctx) {
- function = getLuaRealtimeVehicles
- }
- }
- if function != nil {
- statuses, err := function(ctx, lb, rt)
- if err != nil {
- log.Printf("while getting vehicle positions: %v\n", err)
- return []VehicleStatus{}
- }
- file, err := openTrips(ctx)
- if err != nil {
- log.Printf("while opening trips file: %v", err)
- return []VehicleStatus{}
- }
- defer file.Close()
- statusesWithLine := make([]VehicleStatus, len(statuses))
- tripIDs := []string{}
- for i, status := range statuses {
- if status.LineID != "" && status.Headsign != "" {
- statusesWithLine[i] = status
- } else {
- tripIDs = append(tripIDs, status.TripID)
- }
- }
- trips, err := GetTrips(tripIDs, ctx, t)
- if err != nil {
- log.Printf("while getting trips file: %v", err)
- return []VehicleStatus{}
- }
- for i, status := range statuses {
- if status.LineID == "" || status.Headsign == "" {
- trip := trips[status.TripID]
- status.LineID = trip.LineID
- status.Headsign = trip.Headsign
- statusesWithLine[i] = status
- }
- }
- return statusesWithLine
- }
- return []VehicleStatus{}
- }
|