-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #39 from ibikecph/develop
Added Travel planner(route breaking) feature
- Loading branch information
Showing
17 changed files
with
405 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,6 @@ logfile | |
*~ | ||
\#*\# | ||
.\#* | ||
config/database.yml | ||
config/secrets.yml | ||
.gitignore | ||
config/application.yml | ||
.idea |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
web: bundle exec thin start -p $PORT -e $RAILS_ENV | ||
web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
class Api::V1::JourneyController < Api::V1::BaseController | ||
skip_before_filter :check_auth_token! | ||
|
||
rescue_from TravelPlanner::Error, with: :travel_planner_message | ||
rescue_from StandardError, with: :standard_message | ||
|
||
def show | ||
render json: TravelPlanner.get_journey(params[:loc]) | ||
end | ||
|
||
def travel_planner_message(e) | ||
render json: {error: e.message}, status: 422 | ||
end | ||
|
||
def standard_message(e) | ||
ExceptionNotifier.notify_exception(e, env: request.env) | ||
render json: {error: 'An unexpected error occurred.'}, status: 500 | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
module TravelPlanner | ||
require 'travel_planner/errors' | ||
|
||
include HTTParty | ||
default_timeout 15 | ||
disable_rails_query_string_format # for ibike routing server | ||
base_uri ENV['REJSEPLANEN_API_URL'] | ||
|
||
def self.get_journey(loc) | ||
Journey.new(options(loc)).trips | ||
end | ||
|
||
def self.options(loc) | ||
{ loc: loc.map {|coord| coord.split(',')}.flatten, | ||
originCoordName: '\0', | ||
destCoordName: '\0', | ||
useBicycle: 1, | ||
maxCyclingDistanceDep: 5000, | ||
maxCyclingDistanceDest: 5000, | ||
format: 'json' } | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
class TravelPlanner::CoordSet | ||
# This class gathers all the logic needed to format coordinates, so we can use them in different services. | ||
# It takes coordinate data in the form of [origin_lat,origin_lng,dest_lat,dest_lng]. | ||
|
||
def initialize(coord_data) | ||
raise TravelPlanner::InvalidCoordsError unless coord_data.is_a?(Array) and coord_data.length == 4 | ||
@coords = coord_data | ||
end | ||
|
||
def coords | ||
@coords | ||
end | ||
|
||
def origin | ||
[coords[0],coords[1]] | ||
end | ||
|
||
def destination | ||
[coords[2],coords[3]] | ||
end | ||
|
||
def as_via_points | ||
[[coords[0],coords[1]], [coords[2],coords[3]]] | ||
end | ||
|
||
def for_travel | ||
travel_coords = coords.flatten.map { |x| (x.to_f * (10**6)).to_i } | ||
{ | ||
originCoordX: travel_coords[1], | ||
originCoordY: travel_coords[0], | ||
destCoordX: travel_coords[3], | ||
destCoordY: travel_coords[2] | ||
} | ||
end | ||
|
||
def for_ibike | ||
[ coords[0].to_s+','+coords[1].to_s, coords[2].to_s+','+coords[3].to_s ] | ||
end | ||
|
||
def for_polyline | ||
poly_coords = coords.map {|coord| coord.to_f} | ||
[[poly_coords[0],poly_coords[1]], [poly_coords[2],poly_coords[3]]] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module TravelPlanner | ||
#todo improve and translate error messages | ||
class Error < StandardError | ||
def message | ||
'An unexpected error occurred.' | ||
end | ||
end | ||
|
||
class ConnectionError < Error | ||
def message | ||
'The routing server could not be reached.' | ||
end | ||
end | ||
|
||
class InvalidCoordsError < Error | ||
def message | ||
'Supplied coordinates are invalid.' | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
class TravelPlanner::Journey | ||
def initialize(options) | ||
@coords = TravelPlanner::CoordSet.new options[:loc] | ||
@journey_data = fetch_journey_data options.merge(@coords.for_travel) | ||
end | ||
|
||
def trips | ||
format_journeys @journey_data | ||
end | ||
|
||
private | ||
def fetch_journey_data(query) | ||
response = TravelPlanner.get('/trips/', query: query) | ||
response ? response['TripList']['Trip'] : raise(TravelPlanner::ConnectionError) | ||
end | ||
|
||
def format_journeys(journey_data) | ||
journey_data.first(3).map {|journey| format_legs(journey) } | ||
end | ||
|
||
def format_legs(journey_data) | ||
total_time = total_distance = total_bike_distance = 0 | ||
|
||
journey = journey_data['Leg'].map do |leg_data| | ||
leg = TravelPlanner::Leg.new leg_data, @coords | ||
|
||
formatted_leg = leg.type=='BIKE' ? format_bike(leg) : format_public(leg) | ||
|
||
total_time += formatted_leg['route_summary']['total_time'] | ||
total_distance += formatted_leg['route_summary']['total_distance'] | ||
total_bike_distance += formatted_leg['route_summary']['total_distance'] if leg.type == 'BIKE' | ||
|
||
formatted_leg | ||
end | ||
|
||
{ | ||
journey_summary:{ | ||
total_time: total_time, | ||
total_distance: total_distance, | ||
total_bike_distance: total_bike_distance | ||
}, | ||
journey:journey | ||
} | ||
end | ||
|
||
# We're formatting the response so it mirrors our OSRM-routers bike response. | ||
def format_public(leg) | ||
{ route_name: [ | ||
leg.origin['name'], | ||
leg.destination['name'] | ||
], | ||
|
||
route_summary: { | ||
start_point: leg.origin['name'], | ||
end_point: leg.destination['name'], | ||
total_time: leg.total_time, | ||
total_distance: leg.distance, | ||
type: leg.type, | ||
name: leg.name, | ||
departure_time: leg.departure_time, | ||
arrival_time: leg.arrival_time | ||
}, | ||
|
||
route_instructions: leg.route_instructions, | ||
route_geometry: leg.route_geometry, | ||
|
||
via_points: leg.coords.as_via_points | ||
}.with_indifferent_access | ||
end | ||
|
||
def format_bike(leg) | ||
options = { | ||
loc: leg.coords.for_ibike, | ||
z: 18, | ||
alt: false, | ||
instructions:true | ||
} | ||
|
||
response = TravelPlanner.get('http://routes.ibikecph.dk/v1.1/fast/viaroute', query: options) | ||
|
||
raise TravelPlanner::ConnectionError unless response['status'] == 0 | ||
|
||
response['route_summary'].merge!({ | ||
'type': leg.type, | ||
'departure_time': leg.departure_time, | ||
'arrival_time': leg.arrival_time | ||
}) | ||
response | ||
end | ||
end |
Oops, something went wrong.