google_distance_matrix 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/CHANGELOG.md +10 -1
- data/README.md +31 -12
- data/lib/google_distance_matrix.rb +3 -1
- data/lib/google_distance_matrix/configuration.rb +28 -8
- data/lib/google_distance_matrix/errors.rb +7 -0
- data/lib/google_distance_matrix/log_subscriber.rb +19 -3
- data/lib/google_distance_matrix/matrix.rb +5 -3
- data/lib/google_distance_matrix/place.rb +4 -0
- data/lib/google_distance_matrix/polyline_encoder.rb +47 -0
- data/lib/google_distance_matrix/polyline_encoder/delta.rb +52 -0
- data/lib/google_distance_matrix/polyline_encoder/value_encoder.rb +61 -0
- data/lib/google_distance_matrix/route.rb +11 -3
- data/lib/google_distance_matrix/routes_finder.rb +35 -1
- data/lib/google_distance_matrix/url_builder.rb +24 -4
- data/lib/google_distance_matrix/url_builder/polyline_encoder_buffer.rb +26 -0
- data/lib/google_distance_matrix/version.rb +1 -1
- data/spec/lib/google_distance_matrix/configuration_spec.rb +13 -0
- data/spec/lib/google_distance_matrix/log_subscriber_spec.rb +88 -0
- data/spec/lib/google_distance_matrix/matrix_spec.rb +17 -2
- data/spec/lib/google_distance_matrix/polyline_encoder/delta_spec.rb +15 -0
- data/spec/lib/google_distance_matrix/polyline_encoder_spec.rb +17 -0
- data/spec/lib/google_distance_matrix/route_spec.rb +3 -0
- data/spec/lib/google_distance_matrix/routes_finder_spec.rb +43 -1
- data/spec/lib/google_distance_matrix/url_builder_spec.rb +26 -0
- data/spec/request_recordings/success_with_in_traffic +78 -0
- metadata +14 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3ca9d7d93abd6340a3cb5d36d03cbadfda5e4e1c
|
4
|
+
data.tar.gz: 2cb7956404bd763af695eae8c10b81de5db48450
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c5364924b1a055ce8c67c1508b219a1fc187ee9ecfa95d683775c21888f1076518bd1617b6a2e5be0020f5ef862e6707341bf8c71fff60e12e011d4dad719b9
|
7
|
+
data.tar.gz: 59c211df2561ea00a1da7858051fb87de4a02e35642faba695852baf974e9e3d30d34c9b710e3078e05a2cf1ea1caefb6411f35a0604a90a6f01c37f9c9af715
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
## v.0.
|
1
|
+
## v.0.4.0
|
2
|
+
* When mode is `driving` and `departure_time` is set all `route` objects will contain
|
3
|
+
`duration_in_traffic_in_seconds` and `duration_in_traffic_text`.
|
4
|
+
You can also query the matrix by `shortest_route_by_duration_in_traffic_to(place)`.
|
5
|
+
* Added option to encode origins and destinations as polylines to save characters in the URL.
|
6
|
+
* Filter sensitive GET params when logging the URL we query Google Matrix with.
|
7
|
+
* departure_time can now be set to 'now'.
|
8
|
+
* Dropped support for Ruby 2.0.0
|
9
|
+
|
10
|
+
## v.0.3.0
|
2
11
|
This release includes one breaking change, the removal of sensor parameter.
|
3
12
|
This parameter is no longer used - see:
|
4
13
|
https://developers.google.com/maps/documentation/distance-matrix/intro#Sensor
|
data/README.md
CHANGED
@@ -56,14 +56,14 @@ matrix.configure do |config|
|
|
56
56
|
config.google_business_api_client_id = "123"
|
57
57
|
config.google_business_api_private_key = "your-secret-key"
|
58
58
|
|
59
|
-
# If you have an API key, you can specify that as well.
|
59
|
+
# If you have an API key, you can specify that as well.
|
60
60
|
config.google_api_key = "YOUR_API_KEY"
|
61
61
|
end
|
62
62
|
```
|
63
63
|
### Get the data for the matrix
|
64
64
|
|
65
65
|
`matrix.data` returns the data, loaded from Google, for this matrix.
|
66
|
-
|
66
|
+
|
67
67
|
It is a multi dimensional array. Rows are ordered according to the values in the origins.
|
68
68
|
Each row corresponds to an origin, and each element within that row corresponds to a pairing of the origin with a destination.
|
69
69
|
|
@@ -80,19 +80,25 @@ Returns Google::DistanceMatrix::Route with given origin and destination
|
|
80
80
|
|
81
81
|
```ruby
|
82
82
|
matrix.route_for origin: lat_lng, destination: dest_address
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
matrix.shortest_route_by_duration_to(dest_address)
|
83
|
+
|
84
|
+
# Returns the shortest route to given destination, either by distance or duration
|
85
|
+
matrix.shortest_route_by_distance_to(dest_address)
|
86
|
+
matrix.shortest_route_by_duration_to(dest_address)
|
87
|
+
|
88
|
+
# If your matrix is for driving and you provided a departure_time all Route objects within
|
89
|
+
# the matrix will have duration_in_traffic_in_seconds. We can query the matrix for this data as well:
|
90
|
+
matrix.shortest_route_by_duration_in_traffic_to(dest_address)
|
87
91
|
```
|
88
92
|
|
89
|
-
In cases where you built the place with an object (not hash with attributes) you may provide that object
|
93
|
+
In cases where you built the place with an object (not hash with attributes) you may provide that object
|
94
|
+
as well asking for routes. This is true for `route_for` and `shortest_route_by_*` as well.
|
90
95
|
|
91
96
|
```ruby
|
92
97
|
matrix.routes_for point_dest # Returns routes for dest_object
|
93
98
|
```
|
94
99
|
|
95
|
-
You may call query methods with a bang, in which case it will fail with an error if not all of the
|
100
|
+
You may call query methods with a bang, in which case it will fail with an error if not all of the
|
101
|
+
routes in your result set for the called method are ok.
|
96
102
|
|
97
103
|
|
98
104
|
## Installation
|
@@ -117,6 +123,19 @@ Configuration is done directly on a matrix or via `GoogleDistanceMatrix.configur
|
|
117
123
|
Apart from configuration on requests it is also possible to provide your own logger class and
|
118
124
|
set a cache.
|
119
125
|
|
126
|
+
### Shorting the URL using encoded coordinates
|
127
|
+
Instead of lat and lng values in the URL it is possible to use encoded set of coordinates
|
128
|
+
using the Encoded Polyline Algorithm. This is particularly useful if you have a large
|
129
|
+
number of origin points, because the URL is significantly shorter when
|
130
|
+
using an encoded polyline.
|
131
|
+
|
132
|
+
```ruby
|
133
|
+
GoogleDistanceMatrix.configure_defaults do |config|
|
134
|
+
config.use_encoded_polylines = true
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
|
120
139
|
### Request cache
|
121
140
|
|
122
141
|
Given Google's limit to the service you may have the need to cache requests. This is done by simply
|
@@ -124,10 +143,10 @@ using URL as cache keys. Cache we'll accept should provide a default ActiveSuppo
|
|
124
143
|
|
125
144
|
```ruby
|
126
145
|
GoogleDistanceMatrix.configure_defaults do |config|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
146
|
+
config.cache = ActiveSupport::Cache.lookup_store :your_store, {
|
147
|
+
expires_in: 12.hours
|
148
|
+
# ..or other options you like for your store
|
149
|
+
}
|
131
150
|
end
|
132
151
|
```
|
133
152
|
|
@@ -17,8 +17,8 @@ require "google_distance_matrix/matrix"
|
|
17
17
|
require "google_distance_matrix/places"
|
18
18
|
require "google_distance_matrix/place"
|
19
19
|
require "google_distance_matrix/route"
|
20
|
+
require "google_distance_matrix/polyline_encoder"
|
20
21
|
|
21
|
-
require "google_distance_matrix/log_subscriber"
|
22
22
|
require 'google_distance_matrix/railtie' if defined? Rails
|
23
23
|
|
24
24
|
|
@@ -37,3 +37,5 @@ module GoogleDistanceMatrix
|
|
37
37
|
@logger ||= Logger.new default_configuration.logger
|
38
38
|
end
|
39
39
|
end
|
40
|
+
|
41
|
+
require "google_distance_matrix/log_subscriber"
|
@@ -9,6 +9,7 @@ module GoogleDistanceMatrix
|
|
9
9
|
class Configuration
|
10
10
|
include ActiveModel::Validations
|
11
11
|
|
12
|
+
# Attributes we'll include building URL for our matrix
|
12
13
|
ATTRIBUTES = %w[
|
13
14
|
mode avoid units language
|
14
15
|
departure_time arrival_time
|
@@ -19,19 +20,41 @@ module GoogleDistanceMatrix
|
|
19
20
|
API_DEFAULTS = {
|
20
21
|
mode: "driving",
|
21
22
|
units: "metric",
|
22
|
-
traffic_model: "best_guess"
|
23
|
+
traffic_model: "best_guess",
|
24
|
+
use_encoded_polylines: false,
|
25
|
+
protocol: 'https',
|
26
|
+
lat_lng_scale: 5,
|
27
|
+
filter_parameters_in_logged_url: ['key', 'signature'].freeze
|
23
28
|
}.with_indifferent_access
|
24
29
|
|
25
|
-
attr_accessor *ATTRIBUTES
|
30
|
+
attr_accessor *ATTRIBUTES
|
31
|
+
|
32
|
+
# The protocol to use, either http or https
|
33
|
+
attr_accessor :protocol
|
34
|
+
|
35
|
+
# lat_lng_scale is used for each Place when we include it's lat and lng values in the URL.
|
36
|
+
# Defaults to 5 decimals, but you can set it lower to save characters in the URL.
|
37
|
+
#
|
38
|
+
# Speaking of saving characters. If you use_encoded_polylines all Places which has lat/lng
|
39
|
+
# will use encoded set of coordinates using the Encoded Polyline Algorithm.
|
40
|
+
# This is particularly useful if you have a large number of origin points,
|
41
|
+
# because the URL is significantly shorter when using an encoded polyline.
|
42
|
+
# See: https://developers.google.com/maps/documentation/distance-matrix/intro#RequestParameters
|
43
|
+
attr_accessor :lat_lng_scale, :use_encoded_polylines
|
44
|
+
|
45
|
+
# Google credentials
|
26
46
|
attr_accessor :google_business_api_client_id, :google_business_api_private_key, :google_api_key
|
27
|
-
attr_accessor :cache
|
28
47
|
|
48
|
+
attr_accessor :cache, :logger
|
49
|
+
|
50
|
+
# When logging we filter sensitive parameters
|
51
|
+
attr_accessor :filter_parameters_in_logged_url
|
29
52
|
|
30
53
|
validates :mode, inclusion: {in: ["driving", "walking", "bicycling", "transit"]}, allow_blank: true
|
31
54
|
validates :avoid, inclusion: {in: ["tolls", "highways", "ferries", "indoor"]}, allow_blank: true
|
32
55
|
validates :units, inclusion: {in: ["metric", "imperial"]}, allow_blank: true
|
33
56
|
|
34
|
-
validates :departure_time,
|
57
|
+
validates :departure_time, format: /\A(\d+|now)\Z/, allow_blank: true
|
35
58
|
validates :arrival_time, numericality: true, allow_blank: true
|
36
59
|
|
37
60
|
validates :transit_mode, inclusion: {in: %w[bus subway train tram rail]}, allow_blank: true
|
@@ -41,11 +64,8 @@ module GoogleDistanceMatrix
|
|
41
64
|
validates :protocol, inclusion: {in: ["http", "https"]}, allow_blank: true
|
42
65
|
|
43
66
|
def initialize
|
44
|
-
self.protocol = "https"
|
45
|
-
self.lat_lng_scale = 5
|
46
|
-
|
47
67
|
API_DEFAULTS.each_pair do |attr_name, value|
|
48
|
-
self[attr_name] = value
|
68
|
+
self[attr_name] = value.dup rescue value
|
49
69
|
end
|
50
70
|
end
|
51
71
|
|
@@ -14,6 +14,13 @@ module GoogleDistanceMatrix
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
# Public: Raised when we query the matrix for something it cannot answer.
|
18
|
+
#
|
19
|
+
# Example: Asking it for shortest_route_by_duration_in_traffic when the
|
20
|
+
# matrix data has no such data.
|
21
|
+
class InvalidQuery < Error
|
22
|
+
end
|
23
|
+
|
17
24
|
# Public: Route seems invalid
|
18
25
|
#
|
19
26
|
# Fails if a route is built, but it's status from
|
@@ -1,11 +1,27 @@
|
|
1
1
|
module GoogleDistanceMatrix
|
2
2
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
3
|
+
attr_reader :logger, :config
|
4
|
+
|
5
|
+
def initialize(logger: GoogleDistanceMatrix.logger, config: GoogleDistanceMatrix.default_configuration)
|
6
|
+
super()
|
7
|
+
|
8
|
+
@logger = logger
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
3
12
|
def client_request_matrix_data(event)
|
4
|
-
|
13
|
+
url = filter_url! event.payload[:url]
|
14
|
+
logger.info "(#{event.duration}ms) (elements: #{event.payload[:elements]}) GET #{url}", tag: :client
|
5
15
|
end
|
6
16
|
|
7
|
-
|
8
|
-
|
17
|
+
private
|
18
|
+
|
19
|
+
def filter_url!(url)
|
20
|
+
config.filter_parameters_in_logged_url.each do |param|
|
21
|
+
url.gsub! %r{(#{param})=.*?(&|$)}, '\1=[FILTERED]\2'
|
22
|
+
end
|
23
|
+
|
24
|
+
url
|
9
25
|
end
|
10
26
|
end
|
11
27
|
end
|
@@ -54,10 +54,12 @@ module GoogleDistanceMatrix
|
|
54
54
|
end
|
55
55
|
|
56
56
|
|
57
|
-
delegate :route_for,
|
57
|
+
delegate :route_for, :routes_for, to: :routes_finder
|
58
58
|
delegate :route_for!, :routes_for!, to: :routes_finder
|
59
|
-
delegate :shortest_route_by_distance_to,
|
60
|
-
delegate :shortest_route_by_distance_to!, :shortest_route_by_duration_to!,
|
59
|
+
delegate :shortest_route_by_distance_to, :shortest_route_by_duration_to, to: :routes_finder
|
60
|
+
delegate :shortest_route_by_distance_to!, :shortest_route_by_duration_to!, to: :routes_finder
|
61
|
+
delegate :shortest_route_by_duration_in_traffic_to, to: :routes_finder
|
62
|
+
delegate :shortest_route_by_duration_in_traffic_to!, to: :routes_finder
|
61
63
|
|
62
64
|
|
63
65
|
# Public: The data for this matrix.
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative 'polyline_encoder/delta'
|
2
|
+
require_relative 'polyline_encoder/value_encoder'
|
3
|
+
|
4
|
+
module GoogleDistanceMatrix
|
5
|
+
# Encodes a set of lat/lng pairs in to a polyline
|
6
|
+
# according to Google's Encoded Polyline Algorithm Format.
|
7
|
+
#
|
8
|
+
# See https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
9
|
+
class PolylineEncoder
|
10
|
+
|
11
|
+
# Encodes a set of lat/lng pairs
|
12
|
+
#
|
13
|
+
# Example
|
14
|
+
# encoded = PolylineEncoder.encode [[lat, lng], [lat, lng]]
|
15
|
+
def self.encode(array_of_lat_lng_pairs)
|
16
|
+
new(array_of_lat_lng_pairs).encode
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
# Initialize a new encoder
|
21
|
+
#
|
22
|
+
# Arguments
|
23
|
+
# array_of_lat_lng_pairs - The array of lat/lng pairs, like [[lat, lng], [lat, lng], ..etc]
|
24
|
+
# delta - An object responsible for rounding and calculate the deltas
|
25
|
+
# between the given lat/lng pairs.
|
26
|
+
# value_encoder - After deltas are calculated each value is passed to the encoder
|
27
|
+
# to be encoded in to ASCII characters
|
28
|
+
#
|
29
|
+
# @see ::encode
|
30
|
+
def initialize(array_of_lat_lng_pairs, delta: Delta.new, value_encoder: ValueEncoder.new)
|
31
|
+
@array_of_lat_lng_pairs = array_of_lat_lng_pairs
|
32
|
+
@delta = delta
|
33
|
+
@value_encoder = value_encoder
|
34
|
+
@encoded = nil
|
35
|
+
end
|
36
|
+
|
37
|
+
# Encode and returns the encoded string
|
38
|
+
def encode
|
39
|
+
return @encoded if @encoded
|
40
|
+
|
41
|
+
deltas = @delta.deltas_rounded @array_of_lat_lng_pairs
|
42
|
+
chars_array = deltas.map { |v| @value_encoder.encode v }
|
43
|
+
|
44
|
+
@encoded = chars_array.join
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module GoogleDistanceMatrix
|
2
|
+
class PolylineEncoder
|
3
|
+
# Calculates deltas between lat_lng values, internal helper class for PolylineEncoder.
|
4
|
+
#
|
5
|
+
# According to the Google's polyline encoding spec:
|
6
|
+
# "Additionally, to conserve space, points only include the offset
|
7
|
+
# from the previous point (except of course for the first point)"
|
8
|
+
#
|
9
|
+
# @see GoogleDistanceMatrix::PolylineEncoder
|
10
|
+
class Delta
|
11
|
+
def initialize(precision = 1e5)
|
12
|
+
@precision = precision
|
13
|
+
end
|
14
|
+
|
15
|
+
# Takes a set of lat/lng pairs and calculates delta
|
16
|
+
#
|
17
|
+
# Returns a flatten array where each lat/lng delta pair is put in order.
|
18
|
+
def deltas_rounded(array_of_lat_lng_pairs)
|
19
|
+
rounded = round_to_precision array_of_lat_lng_pairs
|
20
|
+
calculate_deltas rounded
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def round_to_precision(array_of_lat_lng_pairs)
|
27
|
+
array_of_lat_lng_pairs.map do |(lat, lng)|
|
28
|
+
[
|
29
|
+
(lat * @precision).round,
|
30
|
+
(lng * @precision).round
|
31
|
+
]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def calculate_deltas(rounded)
|
36
|
+
deltas = []
|
37
|
+
|
38
|
+
delta_lat = 0
|
39
|
+
delta_lng = 0
|
40
|
+
|
41
|
+
rounded.each do |(lat, lng)|
|
42
|
+
deltas << lat - delta_lat
|
43
|
+
deltas << lng - delta_lng
|
44
|
+
|
45
|
+
delta_lat, delta_lng = lat, lng
|
46
|
+
end
|
47
|
+
|
48
|
+
deltas
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
module GoogleDistanceMatrix
|
2
|
+
class PolylineEncoder
|
3
|
+
# Encodes a single value, like 17998321, in to encoded polyline value,
|
4
|
+
# as described in Google's documentation
|
5
|
+
# https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
6
|
+
#
|
7
|
+
# This is an internal helper class for PolylineEncoder.
|
8
|
+
# This encoder expects that the value is rounded.
|
9
|
+
#
|
10
|
+
# @see GoogleDistanceMatrix::PolylineEncoder
|
11
|
+
class ValueEncoder
|
12
|
+
def encode(value)
|
13
|
+
negative = value < 0
|
14
|
+
value = value.abs
|
15
|
+
|
16
|
+
# Step 3: Two's complement when negative
|
17
|
+
value = ~value + 1 if negative
|
18
|
+
|
19
|
+
# Step 4: Left shift one bit
|
20
|
+
value = value << 1
|
21
|
+
|
22
|
+
# Step 5: Invert if value was negative
|
23
|
+
value = ~value if negative
|
24
|
+
|
25
|
+
# Step 6 and 7: 5-bit chunks in reverse order
|
26
|
+
# We AND 5 first bits and push them on to chunks array.
|
27
|
+
# Right shift bits to get rid of the ones we just put on the array.
|
28
|
+
# Bits will end up in reverse order.
|
29
|
+
chunks_of_5_bits = []
|
30
|
+
while value > 0 do
|
31
|
+
chunks_of_5_bits.push(value & 0x1f)
|
32
|
+
value >>= 5
|
33
|
+
end
|
34
|
+
|
35
|
+
chunks_of_5_bits << 0 if chunks_of_5_bits.empty?
|
36
|
+
|
37
|
+
# Step 8, 9 and 10: OR each value with 0x20, unless last one. Add 63 to all values
|
38
|
+
last_index = chunks_of_5_bits.length - 1
|
39
|
+
chunks_of_5_bits.each_with_index do |chunk, index|
|
40
|
+
chunks_of_5_bits[index] = chunk | 0x20 unless index == last_index
|
41
|
+
chunks_of_5_bits[index] += 63
|
42
|
+
end
|
43
|
+
|
44
|
+
# step 11: Convert to ASCII
|
45
|
+
chunks_of_5_bits.map(&:chr)
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
# Debug method for pretty printing integers as bits.
|
51
|
+
#
|
52
|
+
# Example of usage
|
53
|
+
# p d 17998321 # => "00000001 00010010 10100001 11110001"
|
54
|
+
def d(v, bits = 32, chunk_size = 8)
|
55
|
+
(bits - 1).downto(0).
|
56
|
+
map { |n| v[n] }.
|
57
|
+
each_slice(chunk_size).map { |chunk| chunk.join }.join ' '
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -5,12 +5,15 @@ module GoogleDistanceMatrix
|
|
5
5
|
# it's origin and destination.
|
6
6
|
#
|
7
7
|
class Route
|
8
|
-
STATUSES = %w[ok zero_results not_found]
|
8
|
+
STATUSES = %w[ok zero_results not_found].freeze
|
9
9
|
|
10
10
|
ATTRIBUTES = %w[
|
11
11
|
origin destination
|
12
|
-
status
|
13
|
-
|
12
|
+
status
|
13
|
+
distance_text distance_in_meters
|
14
|
+
duration_text duration_in_seconds
|
15
|
+
duration_in_traffic_text duration_in_traffic_in_seconds
|
16
|
+
].freeze
|
14
17
|
|
15
18
|
attr_reader *ATTRIBUTES
|
16
19
|
|
@@ -30,6 +33,11 @@ module GoogleDistanceMatrix
|
|
30
33
|
@distance_in_meters = attributes[:distance][:value]
|
31
34
|
@duration_text = attributes[:duration][:text]
|
32
35
|
@duration_in_seconds = attributes[:duration][:value]
|
36
|
+
|
37
|
+
if attributes.key? :duration_in_traffic
|
38
|
+
@duration_in_traffic_text = attributes[:duration_in_traffic][:text]
|
39
|
+
@duration_in_traffic_in_seconds = attributes[:duration_in_traffic][:value]
|
40
|
+
end
|
33
41
|
end
|
34
42
|
end
|
35
43
|
|
@@ -3,7 +3,7 @@ module GoogleDistanceMatrix
|
|
3
3
|
class RoutesFinder
|
4
4
|
|
5
5
|
attr_reader :matrix
|
6
|
-
delegate :data, :origins, :destinations, to: :matrix
|
6
|
+
delegate :data, :origins, :destinations, :configuration, to: :matrix
|
7
7
|
|
8
8
|
|
9
9
|
def initialize(matrix)
|
@@ -110,6 +110,34 @@ module GoogleDistanceMatrix
|
|
110
110
|
routes_for!(place_or_object_place_was_built_from).min_by &:duration_in_seconds
|
111
111
|
end
|
112
112
|
|
113
|
+
# Public: Finds shortes route by duration in traffic to a place.
|
114
|
+
#
|
115
|
+
# NOTE The matrix must be loaded with mode driving and a departure_time set to
|
116
|
+
# get the matrix loaded with duration in traffic.
|
117
|
+
#
|
118
|
+
# place - The place, or object place was built from, you want the shortest route to
|
119
|
+
#
|
120
|
+
# Returns shortest route, or nil if no routes had status ok
|
121
|
+
def shortest_route_by_duration_in_traffic_to(place_or_object_place_was_built_from)
|
122
|
+
ensure_driving_and_departure_time_or_fail!
|
123
|
+
|
124
|
+
routes = routes_for place_or_object_place_was_built_from
|
125
|
+
select_ok_routes(routes).min_by &:duration_in_traffic_in_seconds
|
126
|
+
end
|
127
|
+
|
128
|
+
# Public: Finds shortes route by duration in traffic to a place.
|
129
|
+
#
|
130
|
+
# NOTE The matrix must be loaded with mode driving and a departure_time set to
|
131
|
+
# get the matrix loaded with duration in traffic.
|
132
|
+
#
|
133
|
+
# place - The place, or object place was built from, you want the shortest route to
|
134
|
+
#
|
135
|
+
# Returns shortest route, fails if any of the routes are not ok
|
136
|
+
def shortest_route_by_duration_in_traffic_to!(place_or_object_place_was_built_from)
|
137
|
+
ensure_driving_and_departure_time_or_fail!
|
138
|
+
|
139
|
+
routes_for!(place_or_object_place_was_built_from).min_by &:duration_in_traffic_in_seconds
|
140
|
+
end
|
113
141
|
|
114
142
|
|
115
143
|
|
@@ -165,5 +193,11 @@ module GoogleDistanceMatrix
|
|
165
193
|
def select_ok_routes(routes)
|
166
194
|
routes.select &:ok?
|
167
195
|
end
|
196
|
+
|
197
|
+
def ensure_driving_and_departure_time_or_fail!
|
198
|
+
if configuration.mode != 'driving' || configuration.departure_time.nil?
|
199
|
+
fail InvalidQuery, "Matrix must be in mode driving and a departure_time must be set"
|
200
|
+
end
|
201
|
+
end
|
168
202
|
end
|
169
203
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require_relative 'url_builder/polyline_encoder_buffer'
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
2
4
|
class UrlBuilder
|
3
5
|
BASE_URL = "maps.googleapis.com/maps/api/distancematrix/json"
|
@@ -48,14 +50,32 @@ module GoogleDistanceMatrix
|
|
48
50
|
end
|
49
51
|
|
50
52
|
def params
|
51
|
-
places_to_param_config = {lat_lng_scale: configuration.lat_lng_scale}
|
52
|
-
|
53
53
|
configuration.to_param.merge(
|
54
|
-
origins: matrix.origins
|
55
|
-
destinations: matrix.destinations
|
54
|
+
origins: places_to_param(matrix.origins),
|
55
|
+
destinations: places_to_param(matrix.destinations)
|
56
56
|
)
|
57
57
|
end
|
58
58
|
|
59
|
+
def places_to_param(places)
|
60
|
+
places_to_param_config = {lat_lng_scale: configuration.lat_lng_scale}
|
61
|
+
|
62
|
+
out = []
|
63
|
+
polyline_encode_buffer = PolylineEncoderBuffer.new
|
64
|
+
|
65
|
+
places.each do |place|
|
66
|
+
if place.lat_lng? && configuration.use_encoded_polylines
|
67
|
+
polyline_encode_buffer << place.lat_lng
|
68
|
+
else
|
69
|
+
polyline_encode_buffer.flush to: out
|
70
|
+
out << escape(place.to_param places_to_param_config)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
polyline_encode_buffer.flush to: out
|
75
|
+
|
76
|
+
out.join(DELIMITER)
|
77
|
+
end
|
78
|
+
|
59
79
|
def protocol
|
60
80
|
configuration.protocol + "://"
|
61
81
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module GoogleDistanceMatrix
|
2
|
+
class UrlBuilder
|
3
|
+
class PolylineEncoderBuffer
|
4
|
+
def initialize
|
5
|
+
@buffer = []
|
6
|
+
end
|
7
|
+
|
8
|
+
def <<(lat_lng)
|
9
|
+
@buffer << lat_lng
|
10
|
+
end
|
11
|
+
|
12
|
+
def flush(to:)
|
13
|
+
return if @buffer.empty?
|
14
|
+
|
15
|
+
to << escape("enc:#{PolylineEncoder.encode @buffer}:")
|
16
|
+
@buffer.clear
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def escape(string)
|
22
|
+
CGI.escape string
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -13,6 +13,18 @@ describe GoogleDistanceMatrix::Configuration do
|
|
13
13
|
expect(subject.errors[:departure_time].length).to eq 0
|
14
14
|
end
|
15
15
|
|
16
|
+
it 'is valid with "now"' do
|
17
|
+
subject.departure_time = 'now'
|
18
|
+
subject.valid?
|
19
|
+
expect(subject.errors[:departure_time].length).to eq 0
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'is invalid with "123now"' do
|
23
|
+
subject.departure_time = '123now'
|
24
|
+
subject.valid?
|
25
|
+
expect(subject.errors[:departure_time].length).to eq 1
|
26
|
+
end
|
27
|
+
|
16
28
|
it 'is invalid with something else' do
|
17
29
|
subject.departure_time = 'foo'
|
18
30
|
subject.valid?
|
@@ -57,6 +69,7 @@ describe GoogleDistanceMatrix::Configuration do
|
|
57
69
|
it { expect(subject.avoid).to be_nil }
|
58
70
|
it { expect(subject.units).to eq "metric" }
|
59
71
|
it { expect(subject.lat_lng_scale).to eq 5 }
|
72
|
+
it { expect(subject.use_encoded_polylines).to eq false }
|
60
73
|
it { expect(subject.protocol).to eq 'https' }
|
61
74
|
it { expect(subject.language).to be_nil }
|
62
75
|
|
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module GoogleDistanceMatrix
|
4
|
+
describe LogSubscriber do
|
5
|
+
class MockLogger
|
6
|
+
attr_reader :logged
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@logged = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def info(msg, tag)
|
13
|
+
@logged << msg
|
14
|
+
end
|
15
|
+
|
16
|
+
def error(msg)
|
17
|
+
fail msg
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Little helper to clean up examples
|
22
|
+
def notify(instrumentation)
|
23
|
+
ActiveSupport::Notifications.instrument "client_request_matrix_data.google_distance_matrix", instrumentation do
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
let(:mock_logger) { MockLogger.new }
|
29
|
+
let(:config) { Configuration.new }
|
30
|
+
|
31
|
+
# Attach our own test logger, re-attach the original attached log subscriber after test.
|
32
|
+
before do
|
33
|
+
@old_subscribers = LogSubscriber.subscribers.dup
|
34
|
+
LogSubscriber.subscribers.clear
|
35
|
+
LogSubscriber.attach_to "google_distance_matrix", LogSubscriber.new(logger: mock_logger, config: config)
|
36
|
+
end
|
37
|
+
|
38
|
+
after do
|
39
|
+
@old_subscribers.each do |subscriber|
|
40
|
+
LogSubscriber.attach_to "google_distance_matrix", subscriber
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
it "logs the url and elements" do
|
46
|
+
url = 'https://example.com'
|
47
|
+
instrumentation = {url: url, elements: 0}
|
48
|
+
|
49
|
+
expect { notify instrumentation }.to change(mock_logger.logged, :length).from(0).to 1
|
50
|
+
|
51
|
+
expect(mock_logger.logged.first).to include "(elements: 0) GET https://example.com"
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "filtering of logged url" do
|
55
|
+
it "filters nothing if config has no keys to be filtered" do
|
56
|
+
config.filter_parameters_in_logged_url.clear
|
57
|
+
|
58
|
+
instrumentation = {url: 'https://example.com/?foo=bar&sensitive=secret'}
|
59
|
+
notify instrumentation
|
60
|
+
|
61
|
+
expect(mock_logger.logged.first).to include "https://example.com/?foo=bar&sensitive=secret"
|
62
|
+
end
|
63
|
+
|
64
|
+
it "filters sensitive GET param if config has it in list of params to filter" do
|
65
|
+
config.filter_parameters_in_logged_url << 'sensitive'
|
66
|
+
|
67
|
+
instrumentation = {url: 'https://example.com/?foo=bar&sensitive=secret'}
|
68
|
+
notify instrumentation
|
69
|
+
|
70
|
+
expect(mock_logger.logged.first).to include "https://example.com/?foo=bar&sensitive=[FILTERED]"
|
71
|
+
end
|
72
|
+
|
73
|
+
it "filters key and signature as defaul from configuration" do
|
74
|
+
instrumentation = {url: 'https://example.com/?key=bar&signature=secret&other=foo'}
|
75
|
+
notify instrumentation
|
76
|
+
|
77
|
+
expect(mock_logger.logged.first).to include "https://example.com/?key=[FILTERED]&signature=[FILTERED]&other=foo"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "filters all appearances of a param" do
|
81
|
+
instrumentation = {url: 'https://example.com/?key=bar&key=secret&other=foo'}
|
82
|
+
notify instrumentation
|
83
|
+
|
84
|
+
expect(mock_logger.logged.first).to include "https://example.com/?key=[FILTERED]&key=[FILTERED]&other=foo"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -81,6 +81,8 @@ describe GoogleDistanceMatrix::Matrix do
|
|
81
81
|
shortest_route_by_duration_to!
|
82
82
|
shortest_route_by_distance_to
|
83
83
|
shortest_route_by_distance_to!
|
84
|
+
shortest_route_by_duration_in_traffic_to
|
85
|
+
shortest_route_by_duration_in_traffic_to!
|
84
86
|
].each do |method|
|
85
87
|
it "delegates #{method} to routes_finder" do
|
86
88
|
finder = double
|
@@ -94,9 +96,22 @@ describe GoogleDistanceMatrix::Matrix do
|
|
94
96
|
end
|
95
97
|
|
96
98
|
describe "making API requests", :request_recordings do
|
97
|
-
it "loads correctly" do
|
99
|
+
it "loads correctly API response data in to route objects" do
|
98
100
|
stub_request(:get, url).to_return body: recorded_request_for(:success)
|
101
|
+
expect(subject.data[0][0].distance_text).to eq '2.0 km'
|
99
102
|
expect(subject.data[0][0].distance_in_meters).to eq 2032
|
103
|
+
expect(subject.data[0][0].duration_text).to eq '6 mins'
|
104
|
+
expect(subject.data[0][0].duration_in_seconds).to eq 367
|
105
|
+
end
|
106
|
+
|
107
|
+
it "loads correctly API response data in to route objects when it includes in traffic data" do
|
108
|
+
stub_request(:get, url).to_return body: recorded_request_for(:success_with_in_traffic)
|
109
|
+
expect(subject.data[0][0].distance_text).to eq '1.8 km'
|
110
|
+
expect(subject.data[0][0].distance_in_meters).to eq 1752
|
111
|
+
expect(subject.data[0][0].duration_text).to eq '7 mins'
|
112
|
+
expect(subject.data[0][0].duration_in_seconds).to eq 435
|
113
|
+
expect(subject.data[0][0].duration_in_traffic_text).to eq '7 mins'
|
114
|
+
expect(subject.data[0][0].duration_in_traffic_in_seconds).to eq 405
|
100
115
|
end
|
101
116
|
|
102
117
|
context "no cache" do
|
@@ -185,7 +200,7 @@ describe GoogleDistanceMatrix::Matrix do
|
|
185
200
|
expect(api_request_stub).to have_been_requested
|
186
201
|
end
|
187
202
|
|
188
|
-
it "
|
203
|
+
it "adds loaded route with errors correctly" do
|
189
204
|
route = subject.data[0][1]
|
190
205
|
|
191
206
|
expect(route.status).to eq "zero_results"
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module GoogleDistanceMatrix
|
4
|
+
describe PolylineEncoder::Delta do
|
5
|
+
it 'calculates deltas correctly' do
|
6
|
+
deltas = subject.deltas_rounded [[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]]
|
7
|
+
|
8
|
+
expect(deltas).to eq [
|
9
|
+
3850000, -12020000,
|
10
|
+
220000, -75000,
|
11
|
+
255200, -550300
|
12
|
+
]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module GoogleDistanceMatrix
|
4
|
+
describe PolylineEncoder do
|
5
|
+
tests = {
|
6
|
+
[[-179.9832104, -179.9832104]] => '`~oia@`~oia@',
|
7
|
+
[[38.5, -120.2], [40.7, -120.95], [43.252, -126.453]] => '_p~iF~ps|U_ulLnnqC_mqNvxq`@',
|
8
|
+
[[41.3522171071184, -86.0456299662023],[41.3522171071183, -86.0454368471533]] => 'krk{FdxdlO?e@'
|
9
|
+
}
|
10
|
+
|
11
|
+
tests.each_pair do |lat_lng_values, expected|
|
12
|
+
it "encodes #{lat_lng_values} to #{expected}" do
|
13
|
+
expect(described_class.encode lat_lng_values).to eq expected
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -5,6 +5,7 @@ describe GoogleDistanceMatrix::Route do
|
|
5
5
|
{
|
6
6
|
"distance" => {"text" => "2.0 km", "value" => 2032},
|
7
7
|
"duration" => {"text" =>"6 mins", "value" => 367},
|
8
|
+
"duration_in_traffic" => {"text" =>"5 mins", "value" => 301},
|
8
9
|
"status" =>"OK"
|
9
10
|
}
|
10
11
|
end
|
@@ -16,6 +17,8 @@ describe GoogleDistanceMatrix::Route do
|
|
16
17
|
it { expect(subject.distance_text).to eq "2.0 km" }
|
17
18
|
it { expect(subject.duration_in_seconds).to eq 367 }
|
18
19
|
it { expect(subject.duration_text).to eq "6 mins" }
|
20
|
+
it { expect(subject.duration_in_traffic_in_seconds).to eq 301 }
|
21
|
+
it { expect(subject.duration_in_traffic_text).to eq "5 mins" }
|
19
22
|
|
20
23
|
it { is_expected.to be_ok }
|
21
24
|
end
|
@@ -21,7 +21,33 @@ describe GoogleDistanceMatrix::RoutesFinder, :request_recordings do
|
|
21
21
|
|
22
22
|
subject { described_class.new matrix }
|
23
23
|
|
24
|
-
context "success" do
|
24
|
+
context "success, with traffic data" do
|
25
|
+
before do
|
26
|
+
matrix.configure do |c|
|
27
|
+
c.departure_time = 'now'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
let!(:api_request_stub) { stub_request(:get, url).to_return body: recorded_request_for(:success_with_in_traffic) }
|
32
|
+
|
33
|
+
describe "#shortest_route_by_duration_in_traffic_to" do
|
34
|
+
it "returns route representing shortest duration to given origin" do
|
35
|
+
expect(subject.shortest_route_by_duration_in_traffic_to(origin_1)).to eq matrix.data[0][0]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "returns route representing shortest duration to given destination" do
|
39
|
+
expect(subject.shortest_route_by_duration_in_traffic_to(destination_2)).to eq matrix.data[1][1]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "#shortest_route_by_duration_in_traffic_to!" do
|
44
|
+
it "returns the same as shortest_route_by_duration_in_traffic_to" do
|
45
|
+
expect(subject.shortest_route_by_duration_in_traffic_to!(origin_1)).to eq subject.shortest_route_by_duration_in_traffic_to(origin_1)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "success, without in traffic data" do
|
25
51
|
let!(:api_request_stub) { stub_request(:get, url).to_return body: recorded_request_for(:success) }
|
26
52
|
|
27
53
|
describe "#routes_for" do
|
@@ -123,6 +149,22 @@ describe GoogleDistanceMatrix::RoutesFinder, :request_recordings do
|
|
123
149
|
expect(subject.shortest_route_by_duration_to!(origin_1)).to eq subject.shortest_route_by_duration_to(origin_1)
|
124
150
|
end
|
125
151
|
end
|
152
|
+
|
153
|
+
describe "#shortest_route_by_duration_in_traffic_to" do
|
154
|
+
it "returns route representing shortest duration to given origin" do
|
155
|
+
expect {
|
156
|
+
subject.shortest_route_by_duration_in_traffic_to(origin_1)
|
157
|
+
}.to raise_error GoogleDistanceMatrix::InvalidQuery
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "#shortest_route_by_duration_in_traffic_to!" do
|
162
|
+
it "returns the same as shortest_route_by_duration_in_traffic_to" do
|
163
|
+
expect {
|
164
|
+
subject.shortest_route_by_duration_in_traffic_to!(origin_1)
|
165
|
+
}.to raise_error GoogleDistanceMatrix::InvalidQuery
|
166
|
+
end
|
167
|
+
end
|
126
168
|
end
|
127
169
|
|
128
170
|
context "routes mssing data" do
|
@@ -3,6 +3,7 @@ require "spec_helper"
|
|
3
3
|
describe GoogleDistanceMatrix::UrlBuilder do
|
4
4
|
let(:delimiter) { described_class::DELIMITER }
|
5
5
|
let(:comma) { CGI.escape "," }
|
6
|
+
let(:colon) { CGI.escape ":" }
|
6
7
|
|
7
8
|
let(:origin_1) { GoogleDistanceMatrix::Place.new address: "address_origin_1" }
|
8
9
|
let(:origin_2) { GoogleDistanceMatrix::Place.new address: "address_origin_2" }
|
@@ -79,6 +80,31 @@ describe GoogleDistanceMatrix::UrlBuilder do
|
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
83
|
+
describe "use encoded polylines" do
|
84
|
+
let(:destination_3) { GoogleDistanceMatrix::Place.new address: "address_destination_3" }
|
85
|
+
let(:destination_4) { GoogleDistanceMatrix::Place.new lat: 4, lng: 44 }
|
86
|
+
let(:destinations) { [destination_1, destination_2, destination_3, destination_4] }
|
87
|
+
|
88
|
+
before do
|
89
|
+
matrix.configure { |c| c.use_encoded_polylines = true }
|
90
|
+
end
|
91
|
+
|
92
|
+
it "includes places with addresses as addresses" do
|
93
|
+
expect(subject.url).to include "origins=address_origin_1#{delimiter}address_origin_2"
|
94
|
+
end
|
95
|
+
|
96
|
+
it "encodes places with lat/lng values togheter, broken up by addresses to keep places order" do
|
97
|
+
expect(subject.url).to include(
|
98
|
+
# 2 first places encoded togheter as they have lat lng values
|
99
|
+
"destinations=enc#{colon}_ibE_mcbA_ibE_mcbA#{colon}#{delimiter}" +
|
100
|
+
# encoded polyline broken off by a destination with address
|
101
|
+
"address_destination_3#{delimiter}" +
|
102
|
+
# We continue to encode the last destination as it's own ony point polyline
|
103
|
+
"enc#{colon}_glW_wpkG#{colon}"
|
104
|
+
)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
82
108
|
describe "configuration" do
|
83
109
|
context 'with google api key set' do
|
84
110
|
before do
|
@@ -0,0 +1,78 @@
|
|
1
|
+
{
|
2
|
+
"destination_addresses" : [
|
3
|
+
"Drammensveien 1, 0271 Oslo, Norway",
|
4
|
+
"Skjellestadhagen, 1389 Heggedal, Norway"
|
5
|
+
],
|
6
|
+
"origin_addresses" : [ "Karl Johans gate, Oslo, Norway", "Askerveien 1, 1384 Asker, Norway" ],
|
7
|
+
"rows" : [
|
8
|
+
{
|
9
|
+
"elements" : [
|
10
|
+
{
|
11
|
+
"distance" : {
|
12
|
+
"text" : "1.8 km",
|
13
|
+
"value" : 1752
|
14
|
+
},
|
15
|
+
"duration" : {
|
16
|
+
"text" : "7 mins",
|
17
|
+
"value" : 435
|
18
|
+
},
|
19
|
+
"duration_in_traffic" : {
|
20
|
+
"text" : "7 mins",
|
21
|
+
"value" : 405
|
22
|
+
},
|
23
|
+
"status" : "OK"
|
24
|
+
},
|
25
|
+
{
|
26
|
+
"distance" : {
|
27
|
+
"text" : "30.5 km",
|
28
|
+
"value" : 30501
|
29
|
+
},
|
30
|
+
"duration" : {
|
31
|
+
"text" : "38 mins",
|
32
|
+
"value" : 2267
|
33
|
+
},
|
34
|
+
"duration_in_traffic" : {
|
35
|
+
"text" : "36 mins",
|
36
|
+
"value" : 2179
|
37
|
+
},
|
38
|
+
"status" : "OK"
|
39
|
+
}
|
40
|
+
]
|
41
|
+
},
|
42
|
+
{
|
43
|
+
"elements" : [
|
44
|
+
{
|
45
|
+
"distance" : {
|
46
|
+
"text" : "21.3 km",
|
47
|
+
"value" : 21322
|
48
|
+
},
|
49
|
+
"duration" : {
|
50
|
+
"text" : "24 mins",
|
51
|
+
"value" : 1438
|
52
|
+
},
|
53
|
+
"duration_in_traffic" : {
|
54
|
+
"text" : "23 mins",
|
55
|
+
"value" : 1397
|
56
|
+
},
|
57
|
+
"status" : "OK"
|
58
|
+
},
|
59
|
+
{
|
60
|
+
"distance" : {
|
61
|
+
"text" : "9.6 km",
|
62
|
+
"value" : 9550
|
63
|
+
},
|
64
|
+
"duration" : {
|
65
|
+
"text" : "18 mins",
|
66
|
+
"value" : 1109
|
67
|
+
},
|
68
|
+
"duration_in_traffic" : {
|
69
|
+
"text" : "18 mins",
|
70
|
+
"value" : 1083
|
71
|
+
},
|
72
|
+
"status" : "OK"
|
73
|
+
}
|
74
|
+
]
|
75
|
+
}
|
76
|
+
],
|
77
|
+
"status" : "OK"
|
78
|
+
}
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google_distance_matrix
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thorbjørn Hermansen
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-05-
|
11
|
+
date: 2016-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -148,22 +148,30 @@ files:
|
|
148
148
|
- lib/google_distance_matrix/matrix.rb
|
149
149
|
- lib/google_distance_matrix/place.rb
|
150
150
|
- lib/google_distance_matrix/places.rb
|
151
|
+
- lib/google_distance_matrix/polyline_encoder.rb
|
152
|
+
- lib/google_distance_matrix/polyline_encoder/delta.rb
|
153
|
+
- lib/google_distance_matrix/polyline_encoder/value_encoder.rb
|
151
154
|
- lib/google_distance_matrix/railtie.rb
|
152
155
|
- lib/google_distance_matrix/route.rb
|
153
156
|
- lib/google_distance_matrix/routes_finder.rb
|
154
157
|
- lib/google_distance_matrix/url_builder.rb
|
158
|
+
- lib/google_distance_matrix/url_builder/polyline_encoder_buffer.rb
|
155
159
|
- lib/google_distance_matrix/version.rb
|
156
160
|
- spec/lib/google_distance_matrix/client_cache_spec.rb
|
157
161
|
- spec/lib/google_distance_matrix/client_spec.rb
|
158
162
|
- spec/lib/google_distance_matrix/configuration_spec.rb
|
163
|
+
- spec/lib/google_distance_matrix/log_subscriber_spec.rb
|
159
164
|
- spec/lib/google_distance_matrix/logger_spec.rb
|
160
165
|
- spec/lib/google_distance_matrix/matrix_spec.rb
|
161
166
|
- spec/lib/google_distance_matrix/place_spec.rb
|
162
167
|
- spec/lib/google_distance_matrix/places_spec.rb
|
168
|
+
- spec/lib/google_distance_matrix/polyline_encoder/delta_spec.rb
|
169
|
+
- spec/lib/google_distance_matrix/polyline_encoder_spec.rb
|
163
170
|
- spec/lib/google_distance_matrix/route_spec.rb
|
164
171
|
- spec/lib/google_distance_matrix/routes_finder_spec.rb
|
165
172
|
- spec/lib/google_distance_matrix/url_builder_spec.rb
|
166
173
|
- spec/request_recordings/success
|
174
|
+
- spec/request_recordings/success_with_in_traffic
|
167
175
|
- spec/request_recordings/zero_results
|
168
176
|
- spec/spec_helper.rb
|
169
177
|
homepage: ''
|
@@ -194,13 +202,17 @@ test_files:
|
|
194
202
|
- spec/lib/google_distance_matrix/client_cache_spec.rb
|
195
203
|
- spec/lib/google_distance_matrix/client_spec.rb
|
196
204
|
- spec/lib/google_distance_matrix/configuration_spec.rb
|
205
|
+
- spec/lib/google_distance_matrix/log_subscriber_spec.rb
|
197
206
|
- spec/lib/google_distance_matrix/logger_spec.rb
|
198
207
|
- spec/lib/google_distance_matrix/matrix_spec.rb
|
199
208
|
- spec/lib/google_distance_matrix/place_spec.rb
|
200
209
|
- spec/lib/google_distance_matrix/places_spec.rb
|
210
|
+
- spec/lib/google_distance_matrix/polyline_encoder/delta_spec.rb
|
211
|
+
- spec/lib/google_distance_matrix/polyline_encoder_spec.rb
|
201
212
|
- spec/lib/google_distance_matrix/route_spec.rb
|
202
213
|
- spec/lib/google_distance_matrix/routes_finder_spec.rb
|
203
214
|
- spec/lib/google_distance_matrix/url_builder_spec.rb
|
204
215
|
- spec/request_recordings/success
|
216
|
+
- spec/request_recordings/success_with_in_traffic
|
205
217
|
- spec/request_recordings/zero_results
|
206
218
|
- spec/spec_helper.rb
|