aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Polden <mpolden@mpolden.no>2021-08-11 23:29:29 +0200
committerMartin Polden <mpolden@mpolden.no>2021-08-11 23:55:03 +0200
commit8a87fe4bfc70b6aad19e7b2a5fbe9ffe2425cddc (patch)
treef49f6fa66e861ff62b3531561c110e2215ee1eb0
parent62a480d81d5e4bdb66594b0aef2b82b0e8ee11a3 (diff)
http: Add support for specifying direction
-rw-r--r--http/http.go21
-rw-r--r--http/http_test.go31
-rw-r--r--http/types.go20
-rw-r--r--http/types_test.go13
4 files changed, 60 insertions, 25 deletions
diff --git a/http/http.go b/http/http.go
index 0af0146..f8ecbe0 100644
--- a/http/http.go
+++ b/http/http.go
@@ -15,6 +15,11 @@ import (
"github.com/mpolden/atb/entur"
)
+const (
+ inbound = "inbound"
+ outbound = "outbound"
+)
+
// Server represents an Server server.
type Server struct {
ATB *atb.Client
@@ -92,8 +97,13 @@ func (s *Server) atbDepartures(urlPrefix string, nodeID int) (Departures, bool,
return departures, hit, nil
}
-func (s *Server) enturDepartures(urlPrefix string, stopID int) (Departures, bool, error) {
- cacheKey := strconv.Itoa(stopID)
+func (s *Server) enturDepartures(urlPrefix string, stopID int, direction string) (Departures, bool, error) {
+ var cacheKey string
+ if direction == inbound || direction == outbound {
+ cacheKey = fmt.Sprintf("%d-%s", stopID, direction)
+ } else {
+ cacheKey = fmt.Sprintf("%d", stopID)
+ }
cached, hit := s.cache.Get(cacheKey)
if hit {
return cached.(Departures), hit, nil
@@ -102,7 +112,7 @@ func (s *Server) enturDepartures(urlPrefix string, stopID int) (Departures, bool
if err != nil {
return Departures{}, hit, err
}
- departures := convertDepartures(enturDepartures)
+ departures := convertDepartures(enturDepartures, direction)
departures.URL = fmt.Sprintf("%s/api/v2/departures/%d", urlPrefix, stopID)
s.cache.Set(cacheKey, departures, s.ttl.departures)
return departures, hit, nil
@@ -214,12 +224,13 @@ func (s *Server) DepartureHandlerV2(w http.ResponseWriter, r *http.Request) (int
Message: "Invalid stop ID. Use https://stoppested.entur.org/ to find stop IDs.",
}
}
- departures, hit, err := s.enturDepartures(urlPrefix(r), stopID)
+ direction := r.URL.Query().Get("direction")
+ departures, hit, err := s.enturDepartures(urlPrefix(r), stopID, direction)
if err != nil {
return nil, &Error{
err: err,
Status: http.StatusInternalServerError,
- Message: "Failed to get departures from AtB",
+ Message: "Failed to get departures from Entur",
}
}
s.setCacheHeader(w, hit)
diff --git a/http/http_test.go b/http/http_test.go
index ed7486b..0304828 100644
--- a/http/http_test.go
+++ b/http/http_test.go
@@ -96,7 +96,8 @@ func TestAPI(t *testing.T) {
// Show specific departure (v2)
{"/api/v2/departures", `{"status":400,"message":"Invalid stop ID. Use https://stoppested.entur.org/ to find stop IDs."}`, 400},
{"/api/v2/departures/", `{"status":400,"message":"Invalid stop ID. Use https://stoppested.entur.org/ to find stop IDs."}`, 400},
- {"/api/v2/departures/42098", fmt.Sprintf(`{"url":"%s/api/v2/departures/42098","isGoingTowardsCentrum":false,"departures":[{"line":"21","scheduledDepartureTime":"2021-08-11T21:19:00.000","destination":"Pirbadet via sentrum","isRealtimeData":false}]}`, httpSrv.URL), 200},
+ {"/api/v2/departures/60890", fmt.Sprintf(`{"url":"%s/api/v2/departures/60890","departures":[{"line":"11","scheduledDepartureTime":"2021-08-11T23:33:09.000","destination":"Risvollan via sentrum","isRealtimeData":true,"isGoingTowardsCentrum":false},{"line":"3","scheduledDepartureTime":"2021-08-11T23:38:01.000","destination":"Hallset","isRealtimeData":true,"isGoingTowardsCentrum":true}]}`, httpSrv.URL), 200},
+ {"/api/v2/departures/60890?direction=inbound", fmt.Sprintf(`{"url":"%s/api/v2/departures/60890","departures":[{"line":"3","scheduledDepartureTime":"2021-08-11T23:38:01.000","destination":"Hallset","isRealtimeData":true,"isGoingTowardsCentrum":true}]}`, httpSrv.URL), 200},
}
for _, tt := range tests {
data, contentType, status, err := httpGet(httpSrv.URL + tt.url)
@@ -282,21 +283,37 @@ const forecastResponse = `<?xml version="1.0" encoding="utf-8"?>
const enturResponse = `{
"data": {
"stopPlace": {
- "id": "NSR:StopPlace:42098",
- "name": "Ilsvika",
+ "id": "NSR:StopPlace:60890",
+ "name": "Ila",
"estimatedCalls": [
{
- "realtime": false,
- "expectedDepartureTime": "2021-08-11T21:19:00+0200",
+ "realtime": true,
+ "expectedDepartureTime": "2021-08-11T23:33:09+0200",
"actualDepartureTime": null,
"destinationDisplay": {
- "frontText": "Pirbadet via sentrum"
+ "frontText": "Risvollan via sentrum"
},
"serviceJourney": {
"journeyPattern": {
"directionType": "outbound",
"line": {
- "publicCode": "21"
+ "publicCode": "11"
+ }
+ }
+ }
+ },
+ {
+ "realtime": true,
+ "expectedDepartureTime": "2021-08-11T23:38:01+0200",
+ "actualDepartureTime": null,
+ "destinationDisplay": {
+ "frontText": "Hallset"
+ },
+ "serviceJourney": {
+ "journeyPattern": {
+ "directionType": "inbound",
+ "line": {
+ "publicCode": "3"
}
}
}
diff --git a/http/types.go b/http/types.go
index d08f969..56855b0 100644
--- a/http/types.go
+++ b/http/types.go
@@ -50,7 +50,7 @@ type GeoJSONCollection struct {
// Departures represents a list of departures, from a given bus stop.
type Departures struct {
URL string `json:"url"`
- TowardsCentrum bool `json:"isGoingTowardsCentrum"`
+ TowardsCentrum *bool `json:"isGoingTowardsCentrum,omitempty"`
Departures []Departure `json:"departures"`
}
@@ -61,6 +61,7 @@ type Departure struct {
ScheduledDepartureTime string `json:"scheduledDepartureTime"`
Destination string `json:"destination"`
IsRealtimeData bool `json:"isRealtimeData"`
+ TowardsCentrum *bool `json:"isGoingTowardsCentrum,omitempty"`
}
// Error represents an error in the API, which is returned to the user.
@@ -179,34 +180,39 @@ func convertForecasts(f atb.Forecasts) (Departures, error) {
departures = append(departures, departure)
}
return Departures{
- TowardsCentrum: towardsCentrum,
+ TowardsCentrum: &towardsCentrum,
Departures: departures,
}, nil
}
-func convertDepartures(enturDepartures []entur.Departure) Departures {
+func convertDepartures(enturDepartures []entur.Departure, direction string) Departures {
departures := make([]Departure, 0, len(enturDepartures))
- inbound := false
const timeLayout = "2006-01-02T15:04:05.000"
for _, d := range enturDepartures {
+ if direction == inbound && !d.Inbound {
+ continue
+ }
+ if direction == outbound && d.Inbound {
+ continue
+ }
scheduledDepartureTime := d.ScheduledDepartureTime.Format(timeLayout)
registeredDepartureTime := ""
if !d.RegisteredDepartureTime.IsZero() {
registeredDepartureTime = d.RegisteredDepartureTime.Format(timeLayout)
}
+ towardsCentrum := d.Inbound
departure := Departure{
LineID: d.Line,
ScheduledDepartureTime: scheduledDepartureTime,
RegisteredDepartureTime: registeredDepartureTime,
Destination: d.Destination,
IsRealtimeData: d.IsRealtime,
+ TowardsCentrum: &towardsCentrum,
}
- inbound = d.Inbound
departures = append(departures, departure)
}
return Departures{
- TowardsCentrum: inbound,
- Departures: departures,
+ Departures: departures,
}
}
diff --git a/http/types_test.go b/http/types_test.go
index eac8b53..9550001 100644
--- a/http/types_test.go
+++ b/http/types_test.go
@@ -37,13 +37,13 @@ func TestConvertBusStop(t *testing.T) {
func TestConvertBusStops(t *testing.T) {
stops := atb.BusStops{
- Stops: []atb.BusStop{atb.BusStop{
+ Stops: []atb.BusStop{{
NodeID: "16011376",
Longitude: "1157514",
Latitude: 9202874,
}}}
expected := BusStops{
- Stops: []BusStop{BusStop{
+ Stops: []BusStop{{
NodeID: 16011376,
Longitude: 10.398126,
Latitude: 63.415535,
@@ -116,13 +116,14 @@ func TestIsTowardsCentrum(t *testing.T) {
func TestConvertForecasts(t *testing.T) {
forecasts := atb.Forecasts{
- Nodes: []atb.NodeInfo{atb.NodeInfo{NodeID: "16011376"}},
- Forecasts: []atb.Forecast{atb.Forecast{
+ Nodes: []atb.NodeInfo{{NodeID: "16011376"}},
+ Forecasts: []atb.Forecast{{
RegisteredDepartureTime: "26.02.2015 18:38",
ScheduledDepartureTime: "26.02.2015 18:01",
}}}
- expected := Departures{TowardsCentrum: true,
- Departures: []Departure{Departure{
+ b := true
+ expected := Departures{TowardsCentrum: &b,
+ Departures: []Departure{{
RegisteredDepartureTime: "2015-02-26T18:38:00.000",
ScheduledDepartureTime: "2015-02-26T18:01:00.000",
IsRealtimeData: false,