123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- // SPDX-FileCopyrightText: Adam Evyčędo
- //
- // SPDX-License-Identifier: AGPL-3.0-or-later
- package traffic
- import (
- "apiote.xyz/p/szczanieckiej/config"
- "apiote.xyz/p/szczanieckiej/file"
- "fmt"
- "net/http"
- "path/filepath"
- "sort"
- "strings"
- "time"
- "golang.org/x/text/transform"
- )
- type Feed interface {
- fmt.Stringer
- ConvertVehicles() ([]Vehicle, error)
- GetVersions(time.Time, *time.Location) ([]Version, error)
- RealtimeFeeds() map[RealtimeFeedType]string
- Transformer() transform.Transformer
- Name() string
- Flags() FeedFlags
- FeedPrepareZip(string) error
- QRInfo() (string, QRLocation, string)
- getTimezone() *time.Location
- }
- type HeadsignSource uint
- const (
- HeadsignTripHeadsing HeadsignSource = iota
- HeadsignTripLastStop
- )
- type FeedFlags struct {
- Headsign HeadsignSource
- StopIdFormat string
- StopName string
- LineName string
- }
- func FeedPath(cfg config.Config, feed Feed) string {
- return filepath.Join(cfg.FeedsPath, feed.String())
- }
- func RegisterFeeds() map[string]Feed {
- return map[string]Feed{
- "poznan_ztm": PoznanZtm{
- client: http.Client{
- Timeout: 30 * time.Second,
- },
- },
- // "krakow_ztp": KrakowZtp{},
- "gzm_ztm": GzmZtm{},
- "berlin_vbb": BerlinVbb{},
- "brussels_stib_mivb": BrusselsStibMivb{},
- "calgary_transit": CalgaryTransit{},
- "rockhill_myride": RockHillMyRide{},
- "nl_ovapi": NlOvapi{},
- "jastrzebie-zdroj_mzk": JaztrzebieZdrojMZK{},
- "skp_bana": SkpBana{},
- }
- }
- func MakeVersion(s string) (Version, error) {
- version := Version{}
- versionDates := strings.Split(s, "_")
- if len(versionDates) != 2 {
- return version, fmt.Errorf("invalid version string %s, not /.*_.*/", s)
- }
- versionDates[0] += "000000"
- versionDates[1] += "235900"
- validFrom, err := time.Parse(ValidityFormatExtended, versionDates[0])
- if err != nil {
- return version, fmt.Errorf("invalid first part in %s: %w", s, err)
- }
- validTill, err := time.Parse(ValidityFormatExtended, versionDates[1])
- if err != nil {
- return version, fmt.Errorf("invalid second part in %s: %w", s, err)
- }
- version.ValidFrom = validFrom
- version.ValidTill = validTill
- return version, nil
- }
- func MakeVersionTimezone(s string, timezone *time.Location) (Version, error) {
- version := Version{}
- versionDates := strings.Split(s, "_")
- if len(versionDates) != 2 {
- return version, fmt.Errorf("invalid version string %s, not /.*_.*/", s)
- }
- versionDates[0] += "000000"
- versionDates[1] += "235900"
- validFrom, err := time.ParseInLocation(ValidityFormatExtended, versionDates[0], timezone)
- if err != nil {
- return version, fmt.Errorf("invalid first part in %s: %w", s, err)
- }
- validTill, err := time.ParseInLocation(ValidityFormatExtended, versionDates[1], timezone)
- if err != nil {
- return version, fmt.Errorf("invalid second part in %s: %w", s, err)
- }
- version.ValidFrom = validFrom
- version.ValidTill = validTill
- return version, nil
- }
- func ListVersions(cfg config.Config, f Feed) ([]string, error) {
- return file.ListVersions(FeedPath(cfg, f))
- }
- func ListVersionsTimezone(cfg config.Config, f Feed, timezone *time.Location) ([]Version, error) {
- versions := []Version{}
- validities, err := ListVersions(cfg, f)
- if err != nil {
- return versions, fmt.Errorf("while listing versions: %w", err)
- }
- for _, validity := range validities {
- version, err := MakeVersionTimezone(validity, timezone)
- if err != nil {
- return versions, fmt.Errorf("while making version of %s: %w", validity, err)
- }
- versions = append(versions, version)
- }
- return versions, nil
- }
- func FindValidVersions(versions []Version, now time.Time) []Version {
- result := []Version{}
- if len(versions) == 0 {
- return versions
- }
- if len(versions) == 1 {
- if versions[0].ValidTill.IsZero() || (now.Before(versions[0].ValidTill) && now.After(versions[0].ValidFrom)) {
- return versions
- } else {
- return []Version{}
- }
- }
- sort.Slice(versions, func(i, j int) bool {
- return versions[i].ValidFrom.After(versions[j].ValidFrom)
- })
- for _, version := range versions {
- if version.ValidTill.IsZero() || now.Before(version.ValidFrom) {
- result = append([]Version{version}, result...)
- continue
- }
- if now.After(version.ValidFrom) { // TODO and before validTill??
- result = append([]Version{version}, result...)
- break
- }
- }
- return result
- }
|