diff options
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/route_way_cost_unit_converter.rb | 14 | ||||
| -rw-r--r-- | lib/tasks/ci.rake | 17 | ||||
| -rw-r--r-- | lib/tom_tom.rb | 4 | ||||
| -rw-r--r-- | lib/tom_tom/matrix.rb | 114 | ||||
| -rw-r--r-- | lib/tom_tom/matrix/point.rb | 18 | ||||
| -rw-r--r-- | lib/tom_tom/matrix/request_json_serializer.rb | 25 | 
6 files changed, 182 insertions, 10 deletions
| diff --git a/lib/route_way_cost_unit_converter.rb b/lib/route_way_cost_unit_converter.rb index 45edbf538..52515e52c 100644 --- a/lib/route_way_cost_unit_converter.rb +++ b/lib/route_way_cost_unit_converter.rb @@ -8,18 +8,24 @@ class RouteWayCostUnitConverter      end    end -  private -    # Round to 2 decimal places to appease JavaScript validation    def self.meters_to_kilometers(num)      return 0 unless num -    (num / 1000.0).to_i +    snap_to_one(num / 1000.0).to_i    end    def self.seconds_to_minutes(num)      return 0 unless num -    num / 60 +    snap_to_one(num / 60.0).to_i +  end + +  private + +  def self.snap_to_one(decimal) +    return 1 if decimal > 0 && decimal <= 1 + +    decimal    end  end diff --git a/lib/tasks/ci.rake b/lib/tasks/ci.rake index 5b2c8ae3c..cb9ed77e7 100644 --- a/lib/tasks/ci.rake +++ b/lib/tasks/ci.rake @@ -10,6 +10,7 @@ namespace :ci do    desc "Prepare CI build"    task :setup do +    cp "config/database.yml", "config/database.yml.orig"      cp "config/database/ci.yml", "config/database.yml"      puts "Use #{database_name} database"      sh "RAILS_ENV=test rake db:drop db:create db:migrate" @@ -28,6 +29,7 @@ namespace :ci do    end    def deploy_env +    return ENV["DEPLOY_ENV"] if ENV["DEPLOY_ENV"]      if git_branch == "master"        "dev"      elsif git_branch.in?(deploy_envs) @@ -54,12 +56,12 @@ namespace :ci do    desc "Deploy after CI"    task :deploy do -    return if ENV["CHOUETTE_DEPLOY_DISABLED"] - -    if deploy_env -      sh "cap #{deploy_env} deploy:migrations" -    else -      puts "No deploy for branch #{git_branch}" +    unless ENV["CHOUETTE_DEPLOY_DISABLED"] +      if deploy_env +        sh "cap #{deploy_env} deploy:migrations deploy:seed" +      else +        puts "No deploy for branch #{git_branch}" +      end      end    end @@ -75,6 +77,9 @@ namespace :ci do      task :clean do        puts "Drop #{database_name} database"        sh "RAILS_ENV=test rake db:drop" + +      # Restore projet config/database.yml +      # cp "config/database.yml.orig", "config/database.yml" if File.exists?("config/database.yml.orig")      end    end diff --git a/lib/tom_tom.rb b/lib/tom_tom.rb index a1a2bda43..fcebcc7ac 100644 --- a/lib/tom_tom.rb +++ b/lib/tom_tom.rb @@ -19,4 +19,8 @@ module TomTom    def self.batch(way_costs)      TomTom::Batch.new(@connection).batch(way_costs)    end + +  def self.matrix(way_costs) +    TomTom::Matrix.new(@connection).matrix(way_costs) +  end  end diff --git a/lib/tom_tom/matrix.rb b/lib/tom_tom/matrix.rb new file mode 100644 index 000000000..b0c8cc335 --- /dev/null +++ b/lib/tom_tom/matrix.rb @@ -0,0 +1,114 @@ +module TomTom +  class Matrix +    def initialize(connection) +      @connection = connection +    end + +    def matrix(way_costs) +      points_with_ids = points_from_way_costs(way_costs) +      points = points_as_params(points_with_ids) + +      Rails.logger.info "Invoke TomTom for #{points.size} points" + +      response = @connection.post do |req| +        req.url '/routing/1/matrix/json' +        req.headers['Content-Type'] = 'application/json' + +        req.params[:routeType] = 'shortest' +        req.params[:travelMode] = 'bus' + +        req.body = build_request_body(points) +      end + +      extract_costs_to_way_costs!( +        way_costs, +        points_with_ids, +        JSON.parse(response.body) +      ) +    end + +    def points_from_way_costs(way_costs) +      points = [] + +      way_costs.each do |way_cost| +        departure_id, arrival_id = way_cost.id.split('-') + +        departure = TomTom::Matrix::Point.new( +          way_cost.departure, +          departure_id +        ) +        arrival = TomTom::Matrix::Point.new( +          way_cost.arrival, +          arrival_id +        ) + +        # Don't add duplicate coordinates. This assumes that +        # `way_costs` consists of an ordered route of points where +        # each departure coordinate is the same as the preceding +        # arrival coordinate. +        if points.empty? || +            points.last.coordinates != departure.coordinates +          points << departure +        end + +        points << arrival +      end + +      points +    end + +    def points_as_params(points) +      points.map do |point| +        { +          point: { +            latitude: point.coordinates.lat, +            longitude: point.coordinates.lng +          } +        } +      end +    end + +    def build_request_body(points) +      # Serialize `BigDecimal` values as floats to please the TomTom API +      RequestJSONSerializer.dump({ +        origins: points, +        destinations: points +      }) +    end + +    def extract_costs_to_way_costs!(way_costs, points, matrix_json) +      way_costs = [] + +      # `row` and `column` order is the same as `points` +      matrix_json['matrix'].each_with_index do |row, row_i| +        row.each_with_index do |column, column_i| +          next if column['statusCode'] != 200 + +          distance = column['response']['routeSummary']['lengthInMeters'] + +          # Ignore costs between a point and itself (e.g. from A to A) +          next if distance == 0 + +          departure = points[row_i] +          arrival = points[column_i] + +          way_costs << WayCost.new( +            departure: Geokit::LatLng.new( +              departure.coordinates.lat, +              departure.coordinates.lng +            ), +            arrival: Geokit::LatLng.new( +              arrival.coordinates.lat, +              arrival.coordinates.lng +            ), +            distance: distance, +            time: column['response']['routeSummary']['travelTimeInSeconds'], +            id: "#{departure.id}-#{arrival.id}" +          ) +        end +      end + +      way_costs +    end +  end +end diff --git a/lib/tom_tom/matrix/point.rb b/lib/tom_tom/matrix/point.rb new file mode 100644 index 000000000..435b4d4b0 --- /dev/null +++ b/lib/tom_tom/matrix/point.rb @@ -0,0 +1,18 @@ +module TomTom +  class Matrix +    class Point +      attr_reader :coordinates, :id + +      def initialize(coordinates, id) +        @coordinates = coordinates +        @id = id +      end + +      def ==(other) +        other.is_a?(self.class) && +          @coordinates == other.coordinates && +          @id == other.id +      end +    end +  end +end diff --git a/lib/tom_tom/matrix/request_json_serializer.rb b/lib/tom_tom/matrix/request_json_serializer.rb new file mode 100644 index 000000000..f4d12e482 --- /dev/null +++ b/lib/tom_tom/matrix/request_json_serializer.rb @@ -0,0 +1,25 @@ +module TomTom +  class Matrix +    class RequestJSONSerializer +      def self.dump(hash) +        hash[:origins].map! do |point| +          point_to_f(point) +        end +        hash[:destinations].map! do |point| +          point_to_f(point) +        end + +        JSON.dump(hash) +      end + +      private + +      def self.point_to_f(point) +        point[:point][:latitude] = point[:point][:latitude].to_f +        point[:point][:longitude] = point[:point][:longitude].to_f + +        point +      end +    end +  end +end | 
