routific 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d2e7ffe5c2bb636a3ab3c1e594516b763d2e8197
4
+ data.tar.gz: be71b166f79ade2947066ab085952980b04b5a5d
5
+ SHA512:
6
+ metadata.gz: ef023e2e3aca0209ded96748d90bc1cc158f05d819a057ad16a4d71fde24c9a113e4ee084ab388c4bcdc51bec5f51553dde2d9a1bff7bdabc0b604fe68b62caa
7
+ data.tar.gz: 007e6e6b7a0b5cbb8873aa25257835425f7ae0822d9afaa90a66f6cdac2f96341a9c0a3ccc366cddd57219c04a08029fbb3466059586623343ec55e455f50cd2
@@ -0,0 +1,150 @@
1
+ Routific Ruby Gem
2
+ =================
3
+
4
+ This Ruby Gem assists users to easily access the [Routific API][1], which is a practical and scalable solution to the Vehicle Routing Problem.
5
+
6
+ Logistics companies struggle with this challenge every day; most of them are still manually scheduling their fleet with a team of dispatchers.
7
+
8
+ Routific can automate this process, and optimize it. The savings are tremendous: less fuel, and fewer vehicles, drivers and dispatchers.
9
+
10
+ In the U.S., 1/8th of all fuel is consumed by trucks - that's 50 billion gallons a year. Our optimization algorithms will reduce that number by 20%!
11
+
12
+ [1]: https://routific.com
13
+
14
+ Installing
15
+ ----------
16
+
17
+ > gem install routific
18
+
19
+ Usage
20
+ -----
21
+ Remember to require it before using it
22
+
23
+ > require 'routific'
24
+
25
+ The following instance methods are available:
26
+
27
+ - Sets a location with the specified ID and parameters
28
+
29
+ Required arguments in params:
30
+
31
+ - lat: Latitude of this location
32
+ - lng: Longitude of this location
33
+
34
+ Optional arguments in params:
35
+ - name: Name of this location
36
+
37
+ > routific.setLocation( id, params )
38
+
39
+ - Sets a visit for the specified location using the specified parameters
40
+
41
+ Optional arguments in params:
42
+ - start: the earliest time for this visit. Default value is 00:00, if not specified.
43
+ - end: the latest time for this visit. Default value is 23:59, if not specified.
44
+ - duration: the length of this visit in minutes
45
+ - demand: the capacity that this visit requires
46
+
47
+ > routific.setVisit( id, [params] )
48
+
49
+ - Sets a vehicle with the specified ID and parameters
50
+
51
+ Required arguments in params:
52
+ - start_location: ID of start location for this vehicle
53
+
54
+ Optional arguments in params:
55
+ - end_location: ID of end location for this vehicle
56
+ - shift_start: this vehicle's start shift time (e.g. '08:00'). Default value is 00:00, if not specified.
57
+ - shift_end: this vehicle's end shift time (e.g. '17:00'). Default value is 23:59, if not specified.
58
+ - capacity: the capacity that this vehicle can load
59
+
60
+ > routific.setVehicle( id, params )
61
+
62
+ - Returns the route using the previously provided network, visits and
63
+ fleet information
64
+ > routific.getRoute()
65
+
66
+ The following class methods are available:
67
+
68
+ - Sets the default access token to use
69
+ > Routific.setToken( token )
70
+
71
+ - Returns the route using the specified access token, network, visits and fleet information
72
+ > Routific.getRoute( id, [params] )
73
+
74
+ Both getRoute functions return the Route object, which has the following methods:
75
+
76
+ - status: A sanity check, will always be success when the HTTP code is 200
77
+ - fitness: Total travel-time, representing the fitness score of the solution (less is better)
78
+ - unserved: List of visits that could not be scheduled.
79
+ - vehicleRoutes: The optimized schedule
80
+
81
+ Examples
82
+ --------
83
+ Example 1:
84
+
85
+ require 'routific'
86
+
87
+ routific = Routific.new(--API_KEY--)
88
+ routific.setLocation("order_1", {
89
+ "name" => "6800 Cambie",
90
+ "lat" => 49.227107,
91
+ "lng" => -123.1163085,
92
+ })
93
+
94
+ routific.setLocation("depot", {
95
+ "name" => "800 Kingsway",
96
+ "lat" => 49.2553636,
97
+ "lng" => -123.0873365,
98
+ })
99
+
100
+ routific.setVisit("order_1", {
101
+ "start" => "9:00",
102
+ "end" => "12:00",
103
+ "duration" => 10,
104
+ })
105
+
106
+ routific.setVehicle("vehicle_1", {
107
+ "start_location" => "depot",
108
+ "end_location" => "depot",
109
+ "shift_start" => "8:00",
110
+ "shift_end" => "12:00",
111
+ })
112
+
113
+ Example 2:
114
+
115
+ require 'routific'
116
+
117
+ Routific.setToken(--API_KEY--)
118
+ network = {
119
+ "order_1" => {
120
+ "name" => "6800 Cambie",
121
+ "lat" => 49.227107,
122
+ "lng" => -123.1163085
123
+ },
124
+ "depot" => {
125
+ "name" => "800 Kingsway",
126
+ "lat" => 49.2553636,
127
+ "lng" => -123.0873365
128
+ }
129
+ }
130
+ visits = {
131
+ "order_1" => {
132
+ "start" => "9:00",
133
+ "end" => "12:00",
134
+ "duration" => 10
135
+ }
136
+ }
137
+ fleet = {
138
+ "vehicle_1" => {
139
+ "start-location" => "depot",
140
+ "end-location" => "depot",
141
+ "shift-start" => "8:00",
142
+ "shift-end" => "12:00"
143
+ }
144
+ }
145
+ @data = {
146
+ network: network,
147
+ visits: visits,
148
+ fleet: fleet
149
+ }
150
+ Routific.getRoute(@data)
@@ -0,0 +1,88 @@
1
+ require 'rest-client'
2
+ require 'json'
3
+
4
+ require_relative './routific/location'
5
+ require_relative './routific/visit'
6
+ require_relative './routific/vehicle'
7
+ require_relative './routific/route'
8
+ require_relative './routific/way_point'
9
+
10
+ # Main class of this gem
11
+ class Routific
12
+ attr_reader :token, :network, :visits, :fleet
13
+
14
+ # Constructor
15
+ # token: Access token for Routific API
16
+ def initialize(token)
17
+ @token = token
18
+ @network = {}
19
+ @visits = {}
20
+ @fleet = {}
21
+ end
22
+
23
+ # Sets a location with the specified ID and parameters
24
+ # id: location ID
25
+ # params: parameters for this location
26
+ def setLocation(id, params)
27
+ network[id] = Location.new(params)
28
+ end
29
+
30
+ # Sets a visit for the specified location using the specified parameters
31
+ # id: ID of location to visit
32
+ # params: parameters for this visit
33
+ def setVisit(id, params={})
34
+ visits[id] = Visit.new(params)
35
+ end
36
+
37
+ # Sets a vehicle with the specified ID and parameters
38
+ # id: vehicle ID
39
+ # params: parameters for this vehicle
40
+ def setVehicle(id, params)
41
+ fleet[id] = Vehicle.new(params)
42
+ end
43
+
44
+ # Returns the route using the previously provided network, visits and fleet information
45
+ def getRoute
46
+ data = {
47
+ network: network,
48
+ visits: visits,
49
+ fleet: fleet
50
+ }
51
+
52
+ Routific.getRoute(data, token)
53
+ end
54
+
55
+ class << self
56
+ # Sets the default access token to use
57
+ def setToken(token)
58
+ @@token = token
59
+ end
60
+
61
+ def token
62
+ @@token
63
+ end
64
+
65
+ # Returns the route using the specified access token, network, visits and fleet information
66
+ # If no access token is provided, the default access token previously set is used
67
+ # If the default access token either is nil or has not been set, an ArgumentError is raised
68
+ def getRoute(data, token = @@token)
69
+ if token.nil?
70
+ raise ArgumentError, "access token must be set"
71
+ end
72
+
73
+ # Sends HTTP request to Routific API server
74
+ response = RestClient.post('https://routific.com/api/vrp',
75
+ data.to_json,
76
+ 'Authorization' => "bearer #{token}",
77
+ content_type: :json,
78
+ accept: :json
79
+ )
80
+
81
+ # Parse the HTTP request response to JSON
82
+ jsonResponse = JSON.parse(response)
83
+
84
+ # Parse the JSON representation into a Route object
85
+ Route.parse(jsonResponse)
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,41 @@
1
+ # This class represents a location in the network
2
+ class Location
3
+ attr_accessor :name, :lat, :lng
4
+
5
+ # Constructor
6
+ #
7
+ # Required arguments in params:
8
+ # lat: Latitude of this location
9
+ # lng: Longitude of this location
10
+ #
11
+ # Optional arguments in params:
12
+ # name: Name of this location
13
+ def initialize(params)
14
+ # Validates the parameters provided
15
+ validate(params)
16
+
17
+ @lat = params["lat"]
18
+ @lng = params["lng"]
19
+ @name = params["name"]
20
+ end
21
+
22
+ # Returns the JSON representation of this object
23
+ def to_json(options = nil)
24
+ jsonData = {}
25
+ jsonData["name"] = self.name if self.name
26
+ jsonData["lat"] = self.lat
27
+ jsonData["lng"] = self.lng
28
+
29
+ jsonData.to_json
30
+ end
31
+
32
+ private
33
+ # Validates the parameters being provided
34
+ # Raises an ArgumentError if any of the required parameters is not provided.
35
+ # Required parameters are: latitude and longitude
36
+ def validate(params)
37
+ if(params["lat"].nil? || params["lng"].nil?)
38
+ raise ArgumentError, "'lat' and 'lng' parameters must be provided"
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,49 @@
1
+ # This class represents the resulting route returned by the Routific API
2
+ class Route
3
+ attr_reader :status, :fitness, :unserved, :vehicleRoutes
4
+
5
+ # Constructor
6
+ def initialize(status, fitness, unserved)
7
+ @status = status
8
+ @fitness = fitness
9
+ @unserved = unserved
10
+ @vehicleRoutes = Hash.new()
11
+ end
12
+
13
+ # Adds a new way point for the specified vehicle
14
+ def addWayPoint(vehicle_name, way_point)
15
+ if @vehicleRoutes[vehicle_name].nil?
16
+ # No previous way point was added for the specified vehicle, so create a new array
17
+ @vehicleRoutes[vehicle_name] = []
18
+ end
19
+ # Adds the provided way point for the specified vehicle
20
+ @vehicleRoutes[vehicle_name] << way_point
21
+ end
22
+
23
+ class << self
24
+ # Parse the JSON representation of a route, and return it as a Route object
25
+ def parse(routeJson)
26
+ status = routeJson["status"]
27
+ fitness = routeJson["fitness"]
28
+ unserved = routeJson["unserved"]
29
+ route = Route.new(status, fitness, unserved)
30
+
31
+ # Get way points for each vehicles
32
+ routeJson["solution"].each do |vehicle_name, way_points|
33
+ # Get all way points for this vehicle
34
+ way_points.each do |waypoint_info|
35
+ # Get all information for this way point
36
+ location_id = waypoint_info["location_id"]
37
+ location_name = waypoint_info["location_name"]
38
+ arrival_time = waypoint_info["arrival_time"]
39
+ finish_time = waypoint_info["finish_time"]
40
+ way_point = WayPoint.new(location_id, location_name, arrival_time, finish_time)
41
+ route.addWayPoint(vehicle_name, way_point)
42
+ end
43
+ end
44
+
45
+ # Return the resulting Route object
46
+ route
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,47 @@
1
+ # This class represents a vehicle in the fleet
2
+ class Vehicle
3
+ attr_accessor :start_location, :end_location, :shift_start, :shift_end, :capacity
4
+
5
+ # Constructor
6
+ #
7
+ # Required arguments in params:
8
+ # start_location: ID of start location for this vehicle
9
+ #
10
+ # Optional arguments in params:
11
+ # end_location: ID of end location for this vehicle
12
+ # shift_start: this vehicle's start shift time (e.g. '08:00'). Default value is 00:00, if not specified.
13
+ # shift_end: this vehicle's end shift time (e.g. '17:00'). Default value is 23:59, if not specified.
14
+ # capacity: the capacity that this vehicle can load
15
+ def initialize(params)
16
+ # Validates the provided parameters
17
+ validate(params)
18
+
19
+ @start_location = params["start_location"]
20
+ @end_location = params["end_location"]
21
+ @shift_start = params["shift_start"]
22
+ @shift_end = params["shift_end"]
23
+ @capacity = params["capacity"]
24
+ end
25
+
26
+ # Returns the JSON representation of this object
27
+ def to_json(options = nil)
28
+ jsonData = {}
29
+ jsonData["start-location"] = self.start_location
30
+ jsonData["end-location"] = self.end_location if self.end_location
31
+ jsonData["shift-start"] = self.shift_start if self.shift_start
32
+ jsonData["shift-end"] = self.shift_end if self.shift_end
33
+ jsonData["capacity"] = self.capacity if self.capacity
34
+
35
+ jsonData.to_json
36
+ end
37
+
38
+ private
39
+ # Validates the parameters being provided
40
+ # Raises an ArgumentError if any of the required parameters is not provided.
41
+ # Required parameter is: start_location
42
+ def validate(params)
43
+ if(params["start_location"].nil?)
44
+ raise ArgumentError, "'start_location' parameter must be provided"
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,29 @@
1
+ # This class represents a location to be visited
2
+ class Visit
3
+ attr_reader :start, :end, :duration, :demand
4
+
5
+ # Constructor
6
+ #
7
+ # Optional arguments in params:
8
+ # start: the earliest time for this visit. Default value is 00:00, if not specified.
9
+ # end: the latest time for this visit. Default value is 23:59, if not specified.
10
+ # duration: the length of this visit in minutes
11
+ # demand: the capacity that this visit requires
12
+ def initialize(params = {})
13
+ @start = params["start"]
14
+ @end = params["end"]
15
+ @duration = params["duration"]
16
+ @demand = params["demand"]
17
+ end
18
+
19
+ # Returns the JSON representation of this object
20
+ def to_json(options = nil)
21
+ jsonData = {}
22
+ jsonData["start"] = self.start if self.start
23
+ jsonData["end"] = self.end if self.end
24
+ jsonData["duration"] = self.duration if self.duration
25
+ jsonData["demand"] = self.demand if self.demand
26
+
27
+ jsonData.to_json
28
+ end
29
+ end
@@ -0,0 +1,12 @@
1
+ # This class represents a location to visit in the route
2
+ class WayPoint
3
+ attr_reader :location_id, :location_name, :arrival_time, :finish_time
4
+
5
+ # Constructor
6
+ def initialize(location_id, location_name, arrival_time, finish_time)
7
+ @location_id = location_id
8
+ @location_name = location_name
9
+ @arrival_time = arrival_time
10
+ @finish_time = finish_time
11
+ end
12
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: routific
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Marc Kuo
8
+ - Andre Soesilo
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-07-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rest-client
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.7'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.7'
28
+ - !ruby/object:Gem::Dependency
29
+ name: json
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.8'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.8'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '3.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '3.0'
56
+ - !ruby/object:Gem::Dependency
57
+ name: faker
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '1.4'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '1.4'
70
+ - !ruby/object:Gem::Dependency
71
+ name: pry
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '0.10'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '0.10'
84
+ - !ruby/object:Gem::Dependency
85
+ name: pry-debugger
86
+ requirement: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - "~>"
89
+ - !ruby/object:Gem::Version
90
+ version: '0.2'
91
+ type: :development
92
+ prerelease: false
93
+ version_requirements: !ruby/object:Gem::Requirement
94
+ requirements:
95
+ - - "~>"
96
+ - !ruby/object:Gem::Version
97
+ version: '0.2'
98
+ - !ruby/object:Gem::Dependency
99
+ name: dotenv
100
+ requirement: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - "~>"
103
+ - !ruby/object:Gem::Version
104
+ version: '0.11'
105
+ type: :development
106
+ prerelease: false
107
+ version_requirements: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - "~>"
110
+ - !ruby/object:Gem::Version
111
+ version: '0.11'
112
+ description: Gem to use Routific API
113
+ email: asoesilo@live.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files:
117
+ - README.md
118
+ files:
119
+ - "./lib/routific.rb"
120
+ - "./lib/routific/location.rb"
121
+ - "./lib/routific/route.rb"
122
+ - "./lib/routific/vehicle.rb"
123
+ - "./lib/routific/visit.rb"
124
+ - "./lib/routific/way_point.rb"
125
+ - README.md
126
+ homepage: https://routific.com/
127
+ licenses:
128
+ - MIT
129
+ metadata:
130
+ source_code: https://github.com/asoesilo/routific-gem
131
+ post_install_message:
132
+ rdoc_options: []
133
+ require_paths:
134
+ - lib
135
+ required_ruby_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ required_rubygems_version: !ruby/object:Gem::Requirement
141
+ requirements:
142
+ - - ">="
143
+ - !ruby/object:Gem::Version
144
+ version: '0'
145
+ requirements: []
146
+ rubyforge_project:
147
+ rubygems_version: 2.2.2
148
+ signing_key:
149
+ specification_version: 4
150
+ summary: routific API
151
+ test_files: []