trips.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // SPDX-FileCopyrightText: Adam Evyčędo
  2. //
  3. // SPDX-License-Identifier: AGPL-3.0-or-later
  4. package traffic
  5. import (
  6. "fmt"
  7. "os"
  8. "path/filepath"
  9. "git.sr.ht/~sircmpwn/go-bare"
  10. "notabug.org/apiote/gott"
  11. )
  12. func openTrips(context Context) (*os.File, error) {
  13. fileName := filepath.Join(context.DataHome, context.FeedID, string(context.Version), "trips.bare")
  14. return os.Open(fileName)
  15. }
  16. func GetTripsByOffset(offsets []uint, context Context, filter func(Trip) bool) (map[uint]Trip, error) {
  17. trips := map[uint]Trip{}
  18. file, err := os.Open(filepath.Join(context.DataHome, context.FeedID, string(context.Version), "trips.bare"))
  19. if err != nil {
  20. return trips, fmt.Errorf("while opening file: %w", err)
  21. }
  22. defer file.Close()
  23. offsetsSet := map[uint]struct{}{}
  24. for _, offset := range offsets {
  25. offsetsSet[offset] = struct{}{}
  26. }
  27. for offset := range offsetsSet {
  28. _, err = file.Seek(int64(offset), 0)
  29. if err != nil {
  30. return trips, fmt.Errorf("while seeking to %d: %w", offset, err)
  31. }
  32. trip := Trip{}
  33. err = bare.UnmarshalReader(file, &trip)
  34. if err != nil {
  35. return trips, fmt.Errorf("while unmarshalling at %d: %w", offset, err)
  36. }
  37. if filter(trip) {
  38. trips[offset] = trip
  39. }
  40. }
  41. return trips, nil
  42. }
  43. func GetTripByOffset(file *os.File, offset uint, context Context) (Trip, error) {
  44. result := _Result{
  45. file: file,
  46. Offset: offset,
  47. }
  48. r, e := gott.NewResult(result).
  49. Bind(seek).
  50. Bind(unmarshalTrip).
  51. Finish()
  52. if e != nil {
  53. return Trip{}, e
  54. } else {
  55. return r.(_Result).Trip, nil
  56. }
  57. }
  58. func GetTrips(ids []string, ctx Context, traffic *Traffic) (map[string]Trip, error) {
  59. trips := map[string]Trip{}
  60. file, err := openTrips(ctx)
  61. if err != nil {
  62. return trips, fmt.Errorf("while opening trips: %w", err)
  63. }
  64. defer file.Close()
  65. tripOffsets := map[string]struct{}{}
  66. for _, id := range ids {
  67. tripOffsets[id] = struct{}{}
  68. }
  69. tripIndex := traffic.TripIndexes[ctx.FeedID][ctx.Version]
  70. for _, o := range tripIndex {
  71. if _, ok := tripOffsets[o.Name]; ok {
  72. trip, err := GetTripByOffset(file, o.Offsets[0], ctx)
  73. if err != nil {
  74. return trips, fmt.Errorf("while getting trip %s: %w", o.Name, err)
  75. }
  76. trips[trip.Id] = trip
  77. }
  78. }
  79. return trips, nil
  80. }
  81. func GetTrip(file *os.File, id string, context Context, traffic *Traffic) (Trip, error) {
  82. tripIndex := traffic.TripIndexes[context.FeedID][context.Version]
  83. for _, o := range tripIndex {
  84. if o.Name == id {
  85. return GetTripByOffset(file, o.Offsets[0], context)
  86. }
  87. }
  88. return Trip{}, fmt.Errorf("trip by id %s not found", id)
  89. }
  90. func unmarshalDepartures(input ...interface{}) (interface{}, error) {
  91. result := input[0].(_Result)
  92. result.DeparturesSchedule = []Departure{}
  93. err := bare.UnmarshalReader(result.file, &result.DeparturesSchedule)
  94. result.file.Close()
  95. return result, err
  96. }