Giter Club home page Giter Club logo

navitia's Introduction

navitia is a Go client for the navitia API for public transit & transportation

Build Status Go Report Card GoDoc

This is govitia/navitia golang API.

Dependencies

  • It needs at least go 1.7 to work as we use context & tests use testing.T.Run for subtests.
  • The dependencies are directly pulled in by go get, but for you

Install

go get -u github.com/govitia/navitia

Coverage

  • Coverage [/coverage]: You can easily navigate through regions covered by navitia.io, with the coverage api. The shape of the region is provided in GeoJSON, though this is not yet implemented. (navitia.io doc)
  • Journeys [/journeys]: This computes journeys or isochrone tables. (navitia.io doc)
  • Places [/places]: Allows you to search in all geographical objects using their names, returning a list of places. (navitia.io doc)

Changelog

Changelog

Contributing

Contributing guide

Getting started

Creating a new session

First, you should have an API key from navitia.io, if you don't already have one, it's this way !

session, err := navitia.New(APIKEY)

Finding places

import(
	"github.com/govitia/navitia"
	"github.com/govitia/navitia/types"
	"context"
)

// Create a request
req := navitia.PlacesRequest{
	Query: "10 rue du caire, Paris",
	Types: []string{"address"},
	Count: 1,
}

// Execute it
res, _ := session.Places(context.Background(),req)

// Create a variable to store it
var myPlace types.Place

// Check if there are enough results, and then assign the first element as your place
if places := res.Places; len(places) != 0 {
	myPlace = res.Places
}

Calculating a journey

import(
	"github.com/govitia/navitia"
	"fmt"
	"context"
)

// Create a request, having already found two corresponding places
request := navitia.JourneyRequest{
	From: myPlace,
	To: thatOtherPlace,
}

// Execute it
res, _ := session.Journeys(context.Background(),request)

// Print it (JourneysResults implements Stringer)
fmt.Println(res)

Paging

Unfortunately, paging isn't supported by Regions nor by Places requests. You'll have to play with the PlacesRequest.Count value in the latter case. We'll use a Journey to showcase the paging:

// Obtain a journey like last time...

// Create a value to store the paginated result
var paginated *JourneyResults = res

// Iterate by checking if the Paging.Next function is not nil !
for paginated.Paging.Next != nil {
	// Create a new JourneyResults to hold the data
	p := JourneyResults{}
	
	// Call the function
	_ = paginated.Paging.Next(ctx, testSession, &p)

	// Assign a pointer to the previously created data structure to paginated
	paginated = &p
}

Obviously, you'll want to stop paginating at some point, and most importantly do something with the value. An example is on the way !

Scoping

When you wish to make some requests requiring a specific coverage, or have more meaningful results in global requests, you create a Scope

import (
	"github.com/govitia/navitia"
	"github.com/govitia/navitia/types"
	"context"
)

var (
	session *navitia.Session
	regionID types.ID
	req navitia.PlacesRequest
)

scope := session.Scope(regionID)

// Requests places in this scope
res, _ := scope.Places(context.Background(),req)

Going further

Obviously, this is a very simple example of what navitia can do, check out the documentation !

navitia's People

Contributors

aabizri avatar nicolasdscp avatar thomas-tacquet avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

adelcasse ridygo

navitia's Issues

types: merge *_json files with regular files

For exemple, Coordinates struct have two associated files (coordinates.go and coordinates_json.go).
The _json file implement the json.Unmarshaller. We want to move this implementation to the coordinates.go file directly.

types: `PhysicalModes` and `GeoJSON` of Route struct seems to be not unmarshalled by Unmarshaller

In struct Route ;

type Route struct {
	ID            ID             `json:"id"`             // Identifier of the route, eg: "route:RAT:M6"
	Name          string         `json:"name"`           // Name of the route
	Frequence     bool           `json:"is_frequence"`   // If the route has frequency or not. Can only be “False”, but may be “True” in the future
	Line          Line           `json:"line"`           // Line is the line it is connected to
	Direction     Container      `json:"direction"`      // Direction is the direction of the route (Place or POI)
	PhysicalModes []PhysicalMode `json:"physical_modes"` // PhysicalModes of the line
	GeoJSON       GeoJSON        `json:"geo_json"`
}

According to the following JSON struct:

type jsonRoute struct {
	ID        *ID        `json:"id"`
	Name      *string    `json:"name"`
	Line      *Line      `json:"line"`
	Direction *Container `json:"direction"`

	// Value to process
	Frequence string `json:"is_frequence"`
}

PhysicalModes and GeoJSON of Route struct seems to be ignored when unmarshalling process ?!

types: Add validation to all types

The problem

Currently, the types don't have proper validation, notably just after parsing.

A solution

Add a .Check method to all types, calling included types' .Check methods.

Add easy chaining of requests

Reasoning

Most resource endpoints (e.g ../stop_areas/{stop_area}) have sub-endpoints (e.g ../routes) following HATEOS principle. Currently you have to take the resource's ID and call a different method.

Possible solutions

We could simplify this these ways:

For results type having multiple results in them:

- Have a `func (r {Results}) Related() map[ID]map[string](func(context.Context,*Session) Results)` method on the results type, we'll have to create an exported interface `Results` for this to work intelligently.
- Have a single function `func Related(r {Results}) map[ID]map[string](func(context.Context, *Session) Results)` much like the method.

For results type having a single result in them:

- Have each `Results` type that returns only one result implement have an `Explore(ctx context.Context, s *Session, selector string)` method, allowing us easier chaining. (i.e `session.Coords(ctx, coords).Explore(ctx,session,"stop_areas")`).

There may be other ways, I'm open to suggestion !

types: Rename all reference to API types to something clearer.

### The problem

Currently, the term type is used everywhere, which doesn't help clarify that we're talking about resources returned by the remote API.

A solution

(Warning extreme API-Break).

Rename every mention of types in the context of a resource returned by the remote API to resource, including the subpackage's name itself.

Improve the provider selection.

The problem

Currently we implement provider selection through the URL only. However this has the downside that for some providers that restrict some endpoints (like SNCF), we can't stop a request before executing it.

The solution

One way we could do this is move the providers info from URLs to a proper Struct, with information about which endpoints are allowed/disallowed, which will be integrated in Session via a map[string]bool (has O(1) complexity) allowing us not to waste bandwidth.

This may also allow us to have the SSL fingerprints public in those structs, though that's a question for another issue.

As always, I'm open to suggestions.

Datetimes issues (UTC vs local time)

As far as I know (we didn't test much and went to the easier solution on our side), Navitia returns datetimes as "YYYYMMDDTHHMMSS".

As implemented here with the time.Parse function, datetimes are parsed as if they were UTC https://github.com/govitia/navitia/blob/master/types/json.go#L23 instead of the correct local time.

In our fork of the library, we've used time.ParseInLocation to get the correct timezone (but it's hardcoded to our use cases only in France with "Europe/Paris" ;))

The correct way might be to use the "context" given by navitia on every endpoint response (https://doc.navitia.io/#other-objects) with the timezone in it, and then use ParseInLocation with this timezone. But this would probably have quite a big impact on everything related to unmarshalling in the library, as it's returned aside of the types themselves.

What do you think ?

Improve handling for remote error parsing failures.

The problem

Currently, when we try to parse a remote error, and its not a valid JSON payload, (such as some undefined errors and path errors) we return an error that is not a RemoteError, which also means that the specifics (status code & plain-text message) gets lost as well.

One solution

Add the ability to RemoteError to note what was the plain-text response in case the unmarshalling fails, such as a Plain []byte field noting the contents, an ID made on the fly, and correct RemoteError.Error handling.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.