Skip to content

Commit 1d4d8ca

Browse files
committed
add shipments and priority to optimization endpoint
1 parent dc0746b commit 1d4d8ca

File tree

3 files changed

+245
-13
lines changed

3 files changed

+245
-13
lines changed

openrouteservice/optimization.py

Lines changed: 133 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@
1919

2020

2121
def optimization(client,
22-
jobs,
23-
vehicles,
22+
jobs=None,
23+
vehicles=None,
24+
shipments=None,
2425
matrix=None,
2526
geometry=None,
2627
dry_run=None):
@@ -40,10 +41,13 @@ def optimization(client,
4041
>>> result = api.optimization(jobs=jobs, vehicles=vehicles)
4142
4243
:param jobs: The Job objects to fulfill.
43-
:type jobs: list of :class:`openrouteservice.optimization.Job`
44+
:type jobs: list of Job
4445
4546
:param vehicles: The vehicles to fulfill the :class:`openrouteservice.optimization.Job`'s.
46-
:type vehicles: list of :class:`openrouteservice.optimization.Vehicle`
47+
:type vehicles: list of Vehicle
48+
49+
:param shipments: The Shipment objects to fulfill.
50+
:type shipments: list of Shipment
4751
4852
:param matrix: Specify a custom cost matrix. If not specified, it will be calculated with
4953
the :meth:`openrouteservice.matrix.matrix` endpoint.
@@ -59,11 +63,30 @@ def optimization(client,
5963
:rtype: dict
6064
"""
6165

62-
assert all([isinstance(x, Job) for x in jobs])
6366
assert all([isinstance(x, Vehicle) for x in vehicles])
6467

65-
params = {"jobs": [job.__dict__ for job in jobs],
66-
"vehicles": [vehicle.__dict__ for vehicle in vehicles]}
68+
params = {"vehicles": [vehicle.__dict__ for vehicle in vehicles]}
69+
70+
if jobs:
71+
assert all([isinstance(x, Job) for x in jobs])
72+
params['jobs'] = [job.__dict__ for job in jobs]
73+
if shipments:
74+
assert all([isinstance(x, Shipment) for x in shipments])
75+
params['shipments'] = list()
76+
77+
for shipment in shipments:
78+
shipment_dict = dict()
79+
if getattr(shipment, 'pickup'):
80+
assert isinstance(shipment.pickup, ShipmentStep)
81+
shipment_dict['pickup'] = shipment.pickup.__dict__
82+
if getattr(shipment, 'delivery'):
83+
assert isinstance(shipment.delivery, ShipmentStep)
84+
shipment_dict['delivery'] = shipment.delivery.__dict__
85+
shipment_dict['amount'] = shipment.amount
86+
shipment_dict['skills'] = shipment.skills
87+
shipment_dict['priority'] = shipment.priority
88+
89+
params['shipments'].append(shipment_dict)
6790

6891
if geometry is not None:
6992
params.update({"options": {"g": geometry}})
@@ -87,6 +110,7 @@ def __init__(self,
87110
service=None,
88111
amount=None,
89112
skills=None,
113+
priority=None,
90114
time_windows=None
91115
):
92116
"""
@@ -111,6 +135,9 @@ def __init__(self,
111135
:param skills: An array of integers defining mandatory skills for this job.
112136
:type skills: list of int or tuple of int
113137
138+
:param priority: An integer in the [0, 10] range describing priority level (defaults to 0).
139+
:type priority: int
140+
114141
:param time_windows: An array of time_window objects describing valid slots for job service start.
115142
:type time_windows: list of lists of int
116143
"""
@@ -132,10 +159,109 @@ def __init__(self,
132159
if skills is not None:
133160
self.skills = skills
134161

162+
if priority is not None:
163+
self.priority = priority
164+
165+
if time_windows is not None:
166+
self.time_windows = time_windows
167+
168+
169+
class ShipmentStep(object):
170+
"""
171+
Class to create a Shipment object for optimization endpoint.
172+
173+
Full documentation at https://github.com/VROOM-Project/vroom/blob/master/docs/API.md#shipments.
174+
"""
175+
def __init__(self,
176+
id=None,
177+
location=None,
178+
location_index=None,
179+
service=None,
180+
time_windows=None
181+
):
182+
"""
183+
Create a shipment step object for the optimization endpoint.
184+
185+
:param id: Integer used as unique identifier.
186+
:type id: int
187+
188+
:param location: Location of the job, as [lon, lat]. Optional if custom matrix is provided.
189+
:type location: tuple of float or list of float
190+
191+
:param location_index: Index of relevant row and column in custom matrix. Mandatory if custom
192+
matrix is provided. Irrelevant when no custom matrix is provided.
193+
:type location_index: int
194+
195+
:param service: Optional job service duration in seconds
196+
:type service: int
197+
198+
:param time_windows: An array of time_window objects describing valid slots for job service start.
199+
:type time_windows: list of lists of int
200+
"""
201+
202+
self.id = id
203+
204+
if location is not None:
205+
self.location = location
206+
207+
if location_index is not None:
208+
self.location_index = location_index
209+
210+
if service is not None:
211+
self.service = service
212+
135213
if time_windows is not None:
136214
self.time_windows = time_windows
137215

138216

217+
class Shipment(object):
218+
"""
219+
Class to create a Shipment object for optimization endpoint.
220+
221+
Full documentation at https://github.com/VROOM-Project/vroom/blob/master/docs/API.md#shipments.
222+
"""
223+
def __init__(self,
224+
pickup=None,
225+
delivery=None,
226+
amount=None,
227+
skills=None,
228+
priority=None
229+
):
230+
"""
231+
Create a shipment object for the optimization endpoint.
232+
233+
:param pickup: a ShipmentStep object describing pickup
234+
:type pickup: ShipmentStep
235+
236+
:param delivery: a ShipmentStep object describing delivery
237+
:type delivery: ShipmentStep
238+
239+
:param amount: An array of integers describing multidimensional quantities.
240+
:type amount: list of int or tuple of int
241+
242+
:param skills: An array of integers defining mandatory skills.
243+
:type skills: list of int or tuple of int
244+
245+
:param priority: An integer in the [0, 10] range describing priority level (defaults to 0).
246+
:type priority: int
247+
"""
248+
249+
if pickup is not None:
250+
self.pickup = pickup
251+
252+
if delivery is not None:
253+
self.delivery = delivery
254+
255+
if amount is not None:
256+
self.amount = amount
257+
258+
if skills is not None:
259+
self.skills = skills
260+
261+
if priority is not None:
262+
self.priority = priority
263+
264+
139265
class Vehicle(object):
140266
"""
141267
Class to create a Vehicle object for optimization endpoint.

test/test_helper.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,88 @@
135135
'sortby': 'distance',
136136
},
137137
'optimization': {
138+
"shipments": [
139+
{
140+
"pickup": {
141+
"id": 0,
142+
"location": [
143+
8.688641,
144+
49.420577
145+
],
146+
"location_index": 0,
147+
"service": 500,
148+
"time_windows": [
149+
[
150+
50,
151+
50
152+
]
153+
]
154+
},
155+
"delivery": {
156+
"id": 0,
157+
"location": [
158+
8.688641,
159+
49.420577
160+
],
161+
"location_index": 0,
162+
"service": 500,
163+
"time_windows": [
164+
[
165+
50,
166+
50
167+
]
168+
]
169+
},
170+
"amount": [
171+
50
172+
],
173+
"skills": [
174+
50,
175+
50
176+
],
177+
"priority": 50
178+
},
179+
{
180+
"pickup": {
181+
"id": 1,
182+
"location": [
183+
8.680916,
184+
49.415776
185+
],
186+
"location_index": 1,
187+
"service": 500,
188+
"time_windows": [
189+
[
190+
50,
191+
50
192+
]
193+
]
194+
},
195+
"delivery": {
196+
"id": 1,
197+
"location": [
198+
8.680916,
199+
49.415776
200+
],
201+
"location_index": 1,
202+
"service": 500,
203+
"time_windows": [
204+
[
205+
50,
206+
50
207+
]
208+
]
209+
},
210+
"amount": [
211+
50
212+
],
213+
"skills": [
214+
50,
215+
50
216+
],
217+
"priority": 50
218+
}
219+
],
138220
"jobs": [
139221
{
140222
"id": 0,
@@ -143,6 +225,7 @@
143225
"service": PARAM_INT_BIG,
144226
"amount": [PARAM_INT_SMALL],
145227
"skills": PARAM_LIST_ONE,
228+
"priority": PARAM_INT_SMALL,
146229
"time_windows": [PARAM_LIST_ONE]
147230
},
148231
{
@@ -152,6 +235,7 @@
152235
"service": PARAM_INT_BIG,
153236
"amount": [PARAM_INT_SMALL],
154237
"skills": PARAM_LIST_ONE,
238+
"priority": PARAM_INT_SMALL,
155239
"time_windows": [PARAM_LIST_ONE]
156240
}
157241
],

test/test_optimization.py

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,21 @@
2424
import json
2525

2626
from test.test_helper import *
27-
from openrouteservice.optimization import Job, Vehicle
27+
from openrouteservice.optimization import Job, Vehicle, ShipmentStep, Shipment
2828

2929

3030
class OptimizationTest(_test.TestCase):
3131

3232
def _get_params(self):
33-
jobs, vehicles = list(), list()
33+
jobs, vehicles, shipments = list(), list(), list()
3434

3535
for idx, coord in enumerate(PARAM_LINE):
3636
jobs.append(Job(idx, location=coord,
3737
service=PARAM_INT_BIG,
3838
location_index=idx,
3939
amount=[PARAM_INT_SMALL],
4040
skills=PARAM_LIST_ONE,
41+
priority=PARAM_INT_SMALL,
4142
time_windows=[PARAM_LIST_ONE]
4243
))
4344

@@ -49,11 +50,32 @@ def _get_params(self):
4950
capacity=[PARAM_INT_SMALL],
5051
skills=PARAM_LIST_ONE,
5152
time_window=PARAM_LIST_ONE))
52-
return jobs, vehicles
53+
54+
shipments.append(Shipment(
55+
pickup=ShipmentStep(
56+
idx,
57+
location=coord,
58+
location_index=idx,
59+
service=PARAM_INT_BIG,
60+
time_windows=[PARAM_LIST_ONE]
61+
),
62+
delivery=ShipmentStep(
63+
idx,
64+
location=coord,
65+
location_index=idx,
66+
service=PARAM_INT_BIG,
67+
time_windows=[PARAM_LIST_ONE]
68+
),
69+
amount=[PARAM_INT_SMALL],
70+
skills=PARAM_LIST_ONE,
71+
priority=PARAM_INT_SMALL
72+
))
73+
74+
return jobs, vehicles, shipments
5375

5476
def test_jobs_vehicles_classes(self):
5577

56-
jobs, vehicles = self._get_params()
78+
jobs, vehicles, shipments = self._get_params()
5779

5880
self.assertEqual(ENDPOINT_DICT['optimization']['jobs'], [j.__dict__ for j in jobs])
5981
self.assertEqual(ENDPOINT_DICT['optimization']['vehicles'], [v.__dict__ for v in vehicles])
@@ -62,14 +84,14 @@ def test_jobs_vehicles_classes(self):
6284
def test_full_optimization(self):
6385
query = deepcopy(ENDPOINT_DICT['optimization'])
6486

65-
jobs, vehicles = self._get_params()
87+
jobs, vehicles, shipments = self._get_params()
6688

6789
responses.add(responses.POST,
6890
'https://api.openrouteservice.org/optimization',
6991
json={},
7092
status=200,
7193
content_type='application/json')
7294

73-
self.client.optimization(jobs, vehicles, geometry=False, matrix=PARAM_LIST_TWO)
95+
self.client.optimization(jobs, vehicles, shipments, geometry=False, matrix=PARAM_LIST_TWO)
7496

7597
self.assertEqual(query, json.loads(responses.calls[0].request.body.decode('utf-8')))

0 commit comments

Comments
 (0)