idfm-api/types/journeys.go

196 lines
5.4 KiB
Go

package types
import (
"encoding/json"
"fmt"
"strconv"
"time"
)
// A JourneyQualification qualifies a Journey, see const declaration.
type JourneyQualification string
// JourneyXXX qualify journeys
const (
JourneyBest JourneyQualification = "best"
JourneyRapid JourneyQualification = "rapid"
JourneyComfort JourneyQualification = "comfort"
JourneyCar JourneyQualification = "car"
JourneyLessWalk JourneyQualification = "less_fallback_walk"
JourneyLessBike JourneyQualification = "less_fallback_bike"
JourneyLessBikeShare JourneyQualification = "less_fallback_bss"
JourneyFastest JourneyQualification = "fastest"
JourneyNoPTWalk JourneyQualification = "non_pt_walk"
JourneyNoPTBike JourneyQualification = "non_pt_bike"
JourneyNoPTBikeShare JourneyQualification = "non_pt_bss"
)
// JourneyQualifications is a user-friendly slice of all journey qualification
// As it might be used in requests, this is exported
var JourneyQualifications = []JourneyQualification{
JourneyBest,
JourneyRapid,
JourneyComfort,
JourneyCar,
JourneyLessWalk,
JourneyLessBike,
JourneyLessBikeShare,
JourneyFastest,
JourneyNoPTWalk,
JourneyNoPTBike,
JourneyNoPTBikeShare,
}
// A Journey holds information about a possible journey
type Journey struct {
Duration time.Duration
Transfers uint
Departure time.Time
Requested time.Time
Arrival time.Time
CO2Emissions CO2Emissions
Sections []Section
From Container
To Container
Type JourneyQualification
Fare Fare
// Status from the whole journey taking into acount the most disturbing information retrieved on every object used
Status Effect
}
// jsonJourney define the JSON implementation of Journey types
// We define some of the value as pointers to the real values,
// allowing us to bypass copying in cases where we don't need to process the data.
type jsonJourney struct {
Duration int64 `json:"duration"`
Transfers *uint `json:"nb_transfers"`
Departure string `json:"departure_date_time"`
Requested string `json:"requested_date_time"`
Arrival string `json:"arrival_date_time"`
Sections *[]Section `json:"sections"`
From *Container `json:"from"`
To *Container `json:"to"`
Type *JourneyQualification `json:"type"`
Fare *Fare `json:"fare"`
Status *Effect `json:"status"`
}
// CO2Emissions holds how much CO2 is emitted.
type CO2Emissions struct {
Unit string
Value float64
}
// jsonCO2Emissions define the JSON implementation of CO2Emissions types
// We define some of the value as pointers to the real values,
// allowing us to bypass copying in cases where we don't need to process the data.
type jsonCO2Emissions struct {
Unit *string `json:"unit"`
Value string `json:"value"`
}
// TravelerType is a Traveler's type
// Defines speeds & accessibility values for different types of people
type TravelerType string
// The defined types of the api
const (
// A standard Traveler
TravelerStandard TravelerType = "standard"
// A slow walker
TravelerSlowWalker TravelerType = "slow_walker"
// A fast walker
TravelerFastWalker TravelerType = "fast_walker"
// A Traveler with luggage
TravelerWithLuggage TravelerType = "luggage"
// A Traveler in a wheelchair
TravelerInWheelchair TravelerType = "wheelchair"
)
// UnmarshalJSON implements json.Unmarshaller for a Journey.
// Behaviour:
// - If "from" is empty, then don't populate the From field.
// - Same for "to"
func (j *Journey) UnmarshalJSON(b []byte) error {
data := &jsonJourney{
Transfers: &j.Transfers,
Sections: &j.Sections,
From: &j.From,
To: &j.To,
Type: &j.Type,
Fare: &j.Fare,
Status: &j.Status,
}
// Now unmarshall the raw data into the analogous structure
if err := json.Unmarshal(b, data); err != nil {
return fmt.Errorf("error while unmarshalling Journey: %w", err)
}
// Let's create the error generator
gen := unmarshalErrorMaker{"Journey", b}
// As the given duration is in second, let's multiply it by one second to have the correct value
j.Duration = time.Duration(data.Duration) * time.Second
var err error
// For departure, requested and arrival, we use parseDateTime
j.Departure, err = parseDateTime(data.Departure)
if err != nil {
return gen.err(err, "Departure", "departure_date_time", data.Departure, "parseDateTime failed")
}
j.Requested, err = parseDateTime(data.Requested)
if err != nil {
return gen.err(err, "Requested", "requested_date_time", data.Requested, "parseDateTime failed")
}
j.Arrival, err = parseDateTime(data.Arrival)
if err != nil {
return gen.err(err, "Arrival", "arrival_date_time", data.Arrival, "parseDateTime failed")
}
return nil
}
// UnmarshalJSON implements json.Unmarshaller for CO2Emissions
func (c *CO2Emissions) UnmarshalJSON(b []byte) error {
// First let's create the analogous structure
// We define some of the value as pointers to the real values, allowing us to bypass copying in cases where we don't need to process the data
data := &jsonCO2Emissions{
Unit: &c.Unit,
}
// Now unmarshall the raw data into the analogous structure
if err := json.Unmarshal(b, data); err != nil {
return fmt.Errorf("error while unmarshalling CO2Emissions: %w", err)
}
// Let's create the error generator
gen := unmarshalErrorMaker{"CO2Emissions", b}
// Now parse the value
f, err := strconv.ParseFloat(data.Value, 64)
if err != nil {
return gen.err(err, "Value", "value", data.Value, "error in strconv.ParseFloat")
}
c.Value = f
return nil
}