poznan_ztm.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // SPDX-FileCopyrightText: Adam Evyčędo
  2. //
  3. // SPDX-License-Identifier: AGPL-3.0-or-later
  4. package traffic
  5. import (
  6. "apiote.xyz/p/szczanieckiej/config"
  7. "apiote.xyz/p/szczanieckiej/transformers"
  8. "encoding/csv"
  9. "fmt"
  10. "io"
  11. "net/http"
  12. "regexp"
  13. "strings"
  14. "time"
  15. "golang.org/x/text/transform"
  16. )
  17. type HtmlSelector struct {
  18. tag string
  19. id string
  20. class string
  21. }
  22. type PoznanZtm struct {
  23. client http.Client
  24. }
  25. func (PoznanZtm) getTimezone() *time.Location {
  26. l, _ := time.LoadLocation("Europe/Warsaw")
  27. return l
  28. }
  29. func (z PoznanZtm) ConvertVehicles() ([]Vehicle, error) {
  30. vehicles := []Vehicle{}
  31. url := "https://ztm.poznan.pl/pl/dla-deweloperow/getGtfsRtFile/?file=vehicle_dictionary.csv"
  32. response, err := z.client.Get(url)
  33. if err != nil {
  34. return vehicles, fmt.Errorf("ConvertVehicles: cannot GET ‘%s’: %w", url, err)
  35. }
  36. r := csv.NewReader(response.Body)
  37. r.Comma = ','
  38. header, err := r.Read()
  39. if err != nil {
  40. fmt.Println("Header read error")
  41. return vehicles, err
  42. }
  43. fields := map[string]int{}
  44. for i, headerField := range header {
  45. fields[headerField] = i
  46. }
  47. for {
  48. record, err := r.Read()
  49. if err == io.EOF {
  50. break
  51. }
  52. if err != nil {
  53. return vehicles, err
  54. }
  55. var capabilites uint16 = 0
  56. if record[fields["ramp"]] == "1" {
  57. capabilites |= 0b0001
  58. }
  59. if record[fields["hf_lf_le"]] == "1" {
  60. capabilites |= 0b0010
  61. }
  62. if record[fields["hf_lf_le"]] == "2" {
  63. capabilites |= 0b0001_0000_0000
  64. }
  65. if record[fields["air_conditioner"]] == "1" {
  66. capabilites |= 0b0100
  67. }
  68. if record[fields["place_for_transp_bicycles"]] == "1" {
  69. capabilites |= 0b1000
  70. }
  71. if record[fields["voice_announcement_sys"]] == "1" {
  72. capabilites |= 0b0001_0000
  73. }
  74. if record[fields["ticket_machine"]] == "1" {
  75. capabilites |= 0b0010_0000
  76. }
  77. if record[fields["ticket_sales_by_the_driver"]] == "1" {
  78. capabilites |= 0b0100_0000
  79. }
  80. if record[fields["usb_charger"]] == "1" {
  81. capabilites |= 0b1000_0000
  82. }
  83. vehicles = append(vehicles, Vehicle{
  84. Id: record[0],
  85. Capabilities: capabilites,
  86. })
  87. }
  88. return vehicles, nil
  89. }
  90. func (z PoznanZtm) GetVersions(date time.Time, timezone *time.Location) ([]Version, error) {
  91. url := "https://www.ztm.poznan.pl/otwarte-dane/gtfsfiles/"
  92. response, err := z.client.Get(url)
  93. if err != nil {
  94. return []Version{}, fmt.Errorf("GetVersions: cannot GET ‘%s’: %w", url, err)
  95. }
  96. doc, err := io.ReadAll(response.Body)
  97. if err != nil {
  98. return []Version{}, fmt.Errorf("GetVersions: cannot read whole html: %w", err)
  99. }
  100. regex, err := regexp.Compile("[0-9]{8}_[0-9]{8}\\.zip")
  101. versionStrings := regex.FindAllString(string(doc), -1)
  102. versionsSet := map[string]struct{}{}
  103. for _, v := range versionStrings {
  104. versionsSet[v] = struct{}{}
  105. }
  106. versions := []Version{}
  107. for v := range versionsSet {
  108. validityString := strings.Replace(v, ".zip", "", 1)
  109. version, err := MakeVersionTimezone(validityString, timezone)
  110. if err != nil {
  111. return nil, err
  112. }
  113. version.Link = "https://ztm.poznan.pl/pl/dla-deweloperow/getGTFSFile/?file=" + v
  114. versions = append(versions, version)
  115. }
  116. return versions, nil
  117. }
  118. func (PoznanZtm) String() string {
  119. return "poznan_ztm"
  120. }
  121. func (PoznanZtm) RealtimeFeeds() map[RealtimeFeedType]string {
  122. return map[RealtimeFeedType]string{
  123. TRIP_UPDATES: "https://ztm.poznan.pl/pl/dla-deweloperow/getGtfsRtFile/?file=feeds.pb",
  124. VEHICLE_POSITIONS: "https://ztm.poznan.pl/pl/dla-deweloperow/getGtfsRtFile/?file=feeds.pb",
  125. }
  126. }
  127. func (PoznanZtm) LuaUpdatesScript(config.Auth) string {
  128. return ""
  129. }
  130. func (PoznanZtm) Transformer() transform.Transformer {
  131. return transformers.TransformerPL
  132. }
  133. func (PoznanZtm) Name() string {
  134. return "Poznań ZTM"
  135. }
  136. func (PoznanZtm) Flags() FeedFlags {
  137. return FeedFlags{
  138. Headsign: HeadsignTripHeadsing,
  139. StopIdFormat: "{{stop_code}}",
  140. StopName: "{{stop_name}} [{{stop_code}}]",
  141. LineName: "{{route_short_name}}",
  142. }
  143. }
  144. func (PoznanZtm) FeedPrepareZip(path string) error {
  145. return nil
  146. }
  147. func (PoznanZtm) QRInfo() (string, QRLocation, string) {
  148. return "www.peka.poznan.pl", QRLocationQuery, "przystanek"
  149. }