Giter Site home page Giter Site logo

google / cfr Goto Github PK

View Code? Open in Web Editor NEW
75.0 8.0 18.0 11.83 MB

Solve vehicle routing problems with Google Optimization AI Cloud Fleet Routing

Home Page: https://cloud.google.com/optimization/

License: MIT License

Dockerfile 0.01% TypeScript 23.53% JavaScript 64.14% HTML 3.16% SCSS 0.61% CSS 0.03% Makefile 0.01% HCL 0.15% Python 7.54% Jupyter Notebook 0.83% Shell 0.01%
fleet-management google google-cloud google-maps optimization route-optimization routing vrp logistics transportation tsp tsp-problem tsp-solver vrp-solver

cfr's Introduction

Google Fleet Routing App

A web application to explore the capabilities of the Cloud Fleet Routing (CFR) feature of Google Cloud Optimization API.

CFR solves vehicle routing problems (VRPs). Given a set of shipments with locations, a set of vehicles to carry out deliveries, costs and additional constraints; CFR works to find an optimal solution with efficient routes where every shipment is delivered by a vehicle, with all constraints met and minimal cost.

This application presents the properties of the CFR data model as interactive forms, tables, and maps. Users may find it a helpful way to familiarize themselves with the data model and functions of the API. Before writing any code, use the application to construct CFR scenarios, tune constraint parameters, visualize routes, and more.

https://cloud.google.com/optimization

Fleet Routing App screenshot

Intended Use

The application is intended to be used as an exploratory tool and should not be deployed in any production critical path. Google provides this application for users to try out the API and understand how to model their use cases in CFR. But customers should implement their own solutions to integrate Cloud Fleet Routing into their business processes.

Billing

The resources and API usage generated by the application are billed to the project owner. Fleet Routing App is not free to use. Customers can expect ongoing charges related to cloud resources (compute, networking, storage, etc.), along with usage-based charges for the Maps Platform APIs and Cloud Fleet Routing. When running locally for development, the application will still incur usage-based charges for Maps and CFR.

In order to deploy the application to a project, the project must be linked to a valid Google Cloud Billing Account. The customer is responsible for all charges accrued on the account.

⚠️ The application and Cloud Fleet Routing perform several kinds of batch operations. This means it can be easy to generate a high volume of usage in a short period of time, especially for large scenarios with many shipments. Familiarize yourself with the pricing models for Maps Platform and Cloud Fleet Routing before using the application and routinely monitor the charges on your billing account.

Keep scenarios small to begin with and get comfortable with the billing model before attempting to solve large scenarios which may be expensive.

Pricing

Refer to the following pricing guides for Cloud, Maps, and CFR for detailed costs:

⚠️ Google Cloud and Google Maps Platform offer "getting started" and "free tier" credits that may cover a small amount of usage for free. However, as mentioned in the previous section, large scenarios can generate a lot of spend in a short period of time. If you are not careful, it is possible to use up all of your credits with just a few large scenarios.

License

Code is license under an MIT-style license, see LICENSE for details.

Terms of Use

The application is subject the following terms of use:


Deploy an Instance

To deploy a containerized instance of the application from Google Artifact Registry, follow the steps in the project setup and deployment guides:

  • Project Setup
    Create and configure a Google Cloud project with the prerequisites to deploy Fleet Routing App.
  • Deployment Guide
    Deploy an instance of Fleet Routing App into your Google Cloud project.

Local Development

To run a local instance of the application on your machine, follow the steps in the development guide:


User Guide

Instructions for how to use the application are available in the User Guide.

This guide can also be accessed by clicking the "app help docs" link on the application's landing page or the "❔ Help" button in the lower-left corner of the main application window.

cfr's People

Contributors

caio1985 avatar cmorabito-woolpert avatar dependabot[bot] avatar jmccollum-woolpert avatar ondrasej avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cfr's Issues

Label shipments and vehicles on map

Label shipment and vehicle icons on the map with basic information (id and label). These labels should be available for both scenario and solution maps and gantt and metadata views (solution). Permanent labels or on mouse hover may make better sense.

CSV upload doesn't auto-map all fields from shipment sample

Due to changes in column naming since the original implementation, the sample shipment CSV is no longer 100% automatically mapped to the associated api fields. The following fields are affected:

  • Pickup arrival waypoint
  • Delivery arrival waypoint
  • All fields for load demand value and type

image

Support imperial units of measurement

Offer support for miles (and any other imperial units, if necessary) in the app.

This could go in the app configuration itself so it automatically loads with the desired settings. Any place in the application that shows units of measurement would then need to conditionally render the converted units and use appropriate labels.

DEADLINE_EXCEEDED: Deadline exceeded

follow the Local Environment Setup step by step

after Local Development
open http://localhost:8080/ in browser
Upload sample-scenario.json
Select all shipments and all Vehicles
Click Generate

it not show solution but a error message: 4 DEADLINE_EXCEEDED: Deadline exceeded
and console log

fleetrouting-app-backend: [1] [1680403288300] DEBUG (5076 on PC-home): FleetRoutingService.optimizeTours: begin request
fleetrouting-app-backend: [1] [1680403310014] ERROR (5076 on PC-home): 4 DEADLINE_EXCEEDED: Deadline exceeded
fleetrouting-app-backend: [1]     err: {
fleetrouting-app-backend: [1]       "type": "Error",
fleetrouting-app-backend: [1]       "message": "4 DEADLINE_EXCEEDED: Deadline exceeded",
fleetrouting-app-backend: [1]       "stack":
fleetrouting-app-backend: [1]           Error: 4 DEADLINE_EXCEEDED: Deadline exceeded
fleetrouting-app-backend: [1]               at Object.callErrorFromStatus (D:\code\cfr-4.4.1\application\backend\node_modules\@grpc\grpc-js\build\src\call.js:31:19)
fleetrouting-app-backend: [1]               at Object.onReceiveStatus (D:\code\cfr-4.4.1\application\backend\node_modules\@grpc\grpc-js\build\src\client.js:195:52)
fleetrouting-app-backend: [1]               at Object.onReceiveStatus (D:\code\cfr-4.4.1\application\backend\node_modules\@grpc\grpc-js\build\src\client-interceptors.js:365:141)
fleetrouting-app-backend: [1]               at Object.onReceiveStatus (D:\code\cfr-4.4.1\application\backend\node_modules\@grpc\grpc-js\build\src\client-interceptors.js:328:181)
fleetrouting-app-backend: [1]               at D:\code\cfr-4.4.1\application\backend\node_modules\@grpc\grpc-js\build\src\call-stream.js:188:78
fleetrouting-app-backend: [1]               at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
fleetrouting-app-backend: [1]           for call at
fleetrouting-app-backend: [1]               at ServiceClientImpl.makeUnaryRequest (D:\code\cfr-4.4.1\application\backend\node_modules\@grpc\grpc-js\build\src\client.js:163:34)
fleetrouting-app-backend: [1]               at ServiceClientImpl.<anonymous> (D:\code\cfr-4.4.1\application\backend\node_modules\@grpc\grpc-js\build\src\make-client.js:105:19)
fleetrouting-app-backend: [1]               at D:\code\cfr-4.4.1\application\backend\lib\optimization-api\build\src\v1\fleet_routing_client.js:223:29
fleetrouting-app-backend: [1]               at D:\code\cfr-4.4.1\application\backend\node_modules\google-gax\build\src\normalCalls\timeout.js:44:16
fleetrouting-app-backend: [1]               at repeat (D:\code\cfr-4.4.1\application\backend\node_modules\google-gax\build\src\normalCalls\retries.js:80:25)
fleetrouting-app-backend: [1]               at Timeout._onTimeout (D:\code\cfr-4.4.1\application\backend\node_modules\google-gax\build\src\normalCalls\retries.js:101:25)
fleetrouting-app-backend: [1]               at listOnTimeout (node:internal/timers:569:17)
fleetrouting-app-backend: [1]               at process.processTimers (node:internal/timers:512:7)
fleetrouting-app-backend: [1]       "code": 4,
fleetrouting-app-backend: [1]       "details": "Deadline exceeded",
fleetrouting-app-backend: [1]       "metadata": {},
fleetrouting-app-backend: [1]       "note": "Exception occurred in retry method that was not classified as transient"
fleetrouting-app-backend: [1]     }
fleetrouting-app-backend: [1] [1680403310014] INFO (5076 on PC-home): request errored
fleetrouting-app-backend: [1]     req: {
fleetrouting-app-backend: [1]       "id": 42,
fleetrouting-app-backend: [1]       "method": "POST",
fleetrouting-app-backend: [1]       "url": "/api/optimization/fleet-routing/optimize-tours",
fleetrouting-app-backend: [1]       "query": {},
fleetrouting-app-backend: [1]       "params": {},
fleetrouting-app-backend: [1]       "headers": {
fleetrouting-app-backend: [1]         "host": "localhost:8080",
fleetrouting-app-backend: [1]         "connection": "keep-alive",
fleetrouting-app-backend: [1]         "content-length": "2496",
fleetrouting-app-backend: [1]         "sec-ch-ua": "\"Google Chrome\";v=\"111\", \"Not(A:Brand\";v=\"8\", \"Chromium\";v=\"111\"",
fleetrouting-app-backend: [1]         "accept": "application/json, text/plain, */*",
fleetrouting-app-backend: [1]         "content-type": "application/json",
fleetrouting-app-backend: [1]         "dnt": "1",
fleetrouting-app-backend: [1]         "sec-ch-ua-mobile": "?0",
fleetrouting-app-backend: [1]         "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36",
fleetrouting-app-backend: [1]         "sec-ch-ua-platform": "\"Windows\"",
fleetrouting-app-backend: [1]         "origin": "http://127.0.0.1:8080",
fleetrouting-app-backend: [1]         "sec-fetch-site": "cross-site",
fleetrouting-app-backend: [1]         "sec-fetch-mode": "cors",
fleetrouting-app-backend: [1]         "sec-fetch-dest": "empty",
fleetrouting-app-backend: [1]         "referer": "http://127.0.0.1:8080/",
fleetrouting-app-backend: [1]         "accept-encoding": "gzip, deflate, br",
fleetrouting-app-backend: [1]         "accept-language": "en-US,en;q=0.9"
fleetrouting-app-backend: [1]       },
fleetrouting-app-backend: [1]       "remoteAddress": "::1",
fleetrouting-app-backend: [1]       "remotePort": 61184
fleetrouting-app-backend: [1]     }
fleetrouting-app-backend: [1]     res: {
fleetrouting-app-backend: [1]       "statusCode": 500,
fleetrouting-app-backend: [1]       "headers": {
fleetrouting-app-backend: [1]         "access-control-allow-origin": "*",
fleetrouting-app-backend: [1]         "content-type": "text/html; charset=utf-8",
fleetrouting-app-backend: [1]         "content-length": "38",
fleetrouting-app-backend: [1]         "etag": "W/\"26-tbLX3IrCviffpIQ9DBgTOEg/VrE\""
fleetrouting-app-backend: [1]       }
fleetrouting-app-backend: [1]     }
fleetrouting-app-backend: [1]     responseTime: 21723
fleetrouting-app-backend: [1]     err: {
fleetrouting-app-backend: [1]       "type": "Error",
fleetrouting-app-backend: [1]       "message": "failed with status code 500",
fleetrouting-app-backend: [1]       "stack":
fleetrouting-app-backend: [1]           Error: failed with status code 500
fleetrouting-app-backend: [1]               at ServerResponse.onResFinished (D:\code\cfr-4.4.1\application\backend\node_modules\pino-http\logger.js:107:40)
fleetrouting-app-backend: [1]               at ServerResponse.emit (node:events:525:35)
fleetrouting-app-backend: [1]               at onFinish (node:_http_outgoing:989:10)
fleetrouting-app-backend: [1]               at callback (node:internal/streams/writable:555:21)
fleetrouting-app-backend: [1]               at afterWrite (node:internal/streams/writable:500:5)
fleetrouting-app-backend: [1]               at afterWriteTick (node:internal/streams/writable:487:10)
fleetrouting-app-backend: [1]               at process.processTicksAndRejections (node:internal/process/task_queues:81:21)
fleetrouting-app-backend: [1]     }

did anyone know why?
.env environment variable fille have been Create

Do not display breaks outside of vehicle [start, end].

Vehicle breaks do not count towards costs if they are before vehicle start or after vehicle end.
The schedule part of the interface still displays them in those cases, and also display wait time between the vehicle time window and the "outside" break.

Instead, there should be no waiting time displayed, and outside breaks should either no be displayed or displayed suggesting the break is not performed, for instance in grey.

Metrics per Route grid sort behavior issue

  1. Generate solution
  2. Go to Metadata view, Metrics per Route
  3. Sort by Traveled time

Expected: travel time would be sorted by hour/minute
Actual: travel times below two hours are sorted incorrectly. Example below shows sorting treating 01:35 as greater than 22:37.

image

Adding a start time window to an existing vehicle throws an error

Attempting to add a start time window to an existing vehicle that has no start time windows throws an error.

Steps to reproduce:

  • Create a vehicle without time windows and save
  • Edit the vehicle
  • Click "Add time window" in the Start Time Windows section and an error is thrown in the console and the component doesn't render. End time windows don't appear to be affected.
ERROR TypeError: Cannot read properties of undefined (reading 'startTime')

image

Route Duration Limit and Route Distance Limit don't display in Vehicles table

Create a vehicle and only set the max distance and max duration limits:

image

image

The tabular preview of the vehicle will show nothing for Route Distance Limit and partial information for Route Duration Limit, including a default of "00:00" for soft duration max.

image

Expectation is that fields that are set should be displayed regardless of the presence of unrelated fields and that data that is not set should be excluded from the tabular view.

Adding precedence rules throws an error

Attempting to add a precedence rule to a fresh scenario throws the error TypeError: Cannot read properties of null (reading 'id') and prevents the form from being edited.

Attempting to export a PDF with blank routes throws an error

Attempting to export a PDF for a route with no shipments and no start or end location throws an unhelpful error to the user. Variations of the following can appear depending on the exact issue:

Error generating report
Li.path.map is not a function

Expectation:

  • Empty routes should either be filtered out of export completely or properly supported with a blank table and map
  • A more helpful error message for the user should be provided if there's an error during export.

FRA showing unscheduled breaks.

FRA is displaying breaks at the end of a route, after the vehicle is to have gone back to its depo. When I check the solution file no such break is scheduled.
image

Shown below is a route where a break is scheduled at the end but does not occur in transitions and is not reflected in breakDuration.

{
      "vehicleIndex": 0,
      "vehicleLabel": "vehicle_1",
      "vehicleStartTime": "2023-06-12T15:59:06.000Z",
      "vehicleEndTime": "2023-06-13T00:43:32.000Z",
      "visits": [
        {
          "shipmentIndex": 1106,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T16:00:00.000Z",
          "detour": "0s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T15:59:06.000Z",
            "duration": "54s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1109,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T16:07:43.000Z",
          "detour": "114s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T16:05:43.000Z",
            "duration": "120s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1110,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T16:08:43.000Z",
          "detour": "174s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1111,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T16:17:39.000Z",
          "detour": "1059s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T16:16:45.000Z",
            "duration": "54s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1107,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T16:33:37.000Z",
          "detour": "1173s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T16:32:37.000Z",
            "duration": "60s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1106,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T16:35:44.000Z",
          "detour": "1179s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T16:34:37.000Z",
            "duration": "67s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1110,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T16:36:44.000Z",
          "detour": "814s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1111,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T16:37:44.000Z",
          "detour": "240s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1107,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T16:52:38.000Z",
          "detour": "247s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T16:51:44.000Z",
            "duration": "54s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1109,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T16:53:38.000Z",
          "detour": "2219s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1113,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T17:33:00.000Z",
          "detour": "5016s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T17:30:00.000Z",
            "duration": "180s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1108,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T17:44:15.000Z",
          "detour": "5862s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T17:41:15.000Z",
            "duration": "180s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1112,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T18:01:50.000Z",
          "detour": "6530s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T17:58:50.000Z",
            "duration": "180s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1113,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T18:15:30.000Z",
          "detour": "1929s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T18:14:36.000Z",
            "duration": "54s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1108,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T18:48:06.000Z",
          "detour": "3390s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T18:47:06.000Z",
            "duration": "60s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1112,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T18:50:00.000Z",
          "detour": "2070s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T18:49:06.000Z",
            "duration": "54s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1114,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T19:00:54.000Z",
          "detour": "10854s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1114,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T19:16:59.000Z",
          "detour": "0s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T19:15:52.000Z",
            "duration": "67s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1115,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T20:10:17.000Z",
          "detour": "13338s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T20:09:17.000Z",
            "duration": "60s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1139,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T21:12:40.000Z",
          "detour": "16301s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T21:11:40.000Z",
            "duration": "60s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1140,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T21:20:36.000Z",
          "detour": "16887s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T21:18:48.000Z",
            "duration": "108s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1141,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T21:26:17.000Z",
          "detour": "17342s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T21:25:17.000Z",
            "duration": "60s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1120,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T22:04:55.000Z",
          "detour": "21375s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T22:01:55.000Z",
            "duration": "180s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1117,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T22:13:01.000Z",
          "detour": "21994s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T22:10:01.000Z",
            "duration": "180s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1118,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T22:17:14.000Z",
          "detour": "22354s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T22:16:14.000Z",
            "duration": "60s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1129,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T22:22:04.000Z",
          "detour": "22575s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T22:20:04.000Z",
            "duration": "120s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1119,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T22:25:55.000Z",
          "detour": "22955s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1116,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T22:31:06.000Z",
          "detour": "23054s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T22:28:06.000Z",
            "duration": "180s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1104,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T22:48:00.000Z",
          "detour": "23852s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T22:45:00.000Z",
            "duration": "180s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1129,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T23:01:05.000Z",
          "detour": "1474s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T22:59:58.000Z",
            "duration": "67s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1119,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T23:15:59.000Z",
          "detour": "2571s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T23:15:05.000Z",
            "duration": "54s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1116,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T23:16:59.000Z",
          "detour": "2317s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1104,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T23:17:59.000Z",
          "detour": "1293s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1120,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T23:18:59.000Z",
          "detour": "3937s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1117,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T23:19:59.000Z",
          "detour": "3584s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1118,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T23:29:54.000Z",
          "detour": "3918s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1145,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T23:30:54.000Z",
          "detour": "27054s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1105,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T23:45:48.000Z",
          "detour": "27168s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T23:42:48.000Z",
            "duration": "180s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1144,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-12T23:52:47.000Z",
          "detour": "27736s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T23:51:47.000Z",
            "duration": "60s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1145,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-13T00:00:59.000Z",
          "detour": "840s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-12T23:59:52.000Z",
            "duration": "67s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1105,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-13T00:15:53.000Z",
          "detour": "985s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-13T00:14:59.000Z",
            "duration": "54s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1144,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-13T00:16:53.000Z",
          "detour": "765s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1089,
          "isPickup": true,
          "visitRequestIndex": 0,
          "startTime": "2023-06-13T00:28:11.000Z",
          "detour": "29927s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-13T00:25:11.000Z",
            "duration": "180s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1141,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-13T00:38:32.000Z",
          "detour": "9206s",
          "visitLabel": "",
          "delayBeforeStart": {
            "startTime": "2023-06-13T00:37:38.000Z",
            "duration": "54s"
          },
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1115,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-13T00:39:32.000Z",
          "detour": "14399s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1139,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-13T00:40:32.000Z",
          "detour": "9903s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1140,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-13T00:41:32.000Z",
          "detour": "9625s",
          "visitLabel": "",
          "shipmentName": ""
        },
        {
          "shipmentIndex": 1089,
          "isPickup": false,
          "visitRequestIndex": 0,
          "startTime": "2023-06-13T00:42:32.000Z",
          "detour": "240s",
          "visitLabel": "",
          "shipmentName": ""
        }
      ],
      "transitions": [
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "delayDuration": "54s",
          "waitDuration": "0s",
          "totalDuration": "54s",
          "startTime": "2023-06-12T15:59:06.000Z"
        },
        {
          "travelDuration": "283s",
          "travelDistanceMeters": 2834,
          "trafficInfoUnavailable": false,
          "delayDuration": "120s",
          "waitDuration": "0s",
          "totalDuration": "403s",
          "startTime": "2023-06-12T16:01:00.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-12T16:08:43.000Z"
        },
        {
          "travelDuration": "422s",
          "travelDistanceMeters": 3549,
          "trafficInfoUnavailable": false,
          "delayDuration": "54s",
          "waitDuration": "0s",
          "totalDuration": "476s",
          "startTime": "2023-06-12T16:09:43.000Z"
        },
        {
          "travelDuration": "838s",
          "travelDistanceMeters": 8780,
          "trafficInfoUnavailable": false,
          "delayDuration": "60s",
          "waitDuration": "0s",
          "totalDuration": "898s",
          "startTime": "2023-06-12T16:18:39.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "delayDuration": "67s",
          "waitDuration": "0s",
          "totalDuration": "67s",
          "startTime": "2023-06-12T16:34:37.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-12T16:36:44.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-12T16:37:44.000Z"
        },
        {
          "travelDuration": "780s",
          "travelDistanceMeters": 9273,
          "trafficInfoUnavailable": false,
          "delayDuration": "54s",
          "waitDuration": "0s",
          "totalDuration": "834s",
          "startTime": "2023-06-12T16:38:44.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-12T16:53:38.000Z"
        },
        {
          "travelDuration": "438s",
          "travelDistanceMeters": 3918,
          "trafficInfoUnavailable": false,
          "delayDuration": "180s",
          "waitDuration": "1684s",
          "totalDuration": "2302s",
          "startTime": "2023-06-12T16:54:38.000Z"
        },
        {
          "travelDuration": "435s",
          "travelDistanceMeters": 3614,
          "trafficInfoUnavailable": false,
          "delayDuration": "180s",
          "waitDuration": "0s",
          "totalDuration": "615s",
          "startTime": "2023-06-12T17:34:00.000Z"
        },
        {
          "travelDuration": "815s",
          "travelDistanceMeters": 8539,
          "trafficInfoUnavailable": false,
          "delayDuration": "180s",
          "waitDuration": "0s",
          "totalDuration": "995s",
          "startTime": "2023-06-12T17:45:15.000Z"
        },
        {
          "travelDuration": "706s",
          "travelDistanceMeters": 7166,
          "trafficInfoUnavailable": false,
          "delayDuration": "54s",
          "waitDuration": "0s",
          "totalDuration": "760s",
          "startTime": "2023-06-12T18:02:50.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "delayDuration": "60s",
          "waitDuration": "1836s",
          "totalDuration": "1896s",
          "startTime": "2023-06-12T18:16:30.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "delayDuration": "54s",
          "waitDuration": "0s",
          "totalDuration": "54s",
          "startTime": "2023-06-12T18:49:06.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "594s",
          "totalDuration": "594s",
          "startTime": "2023-06-12T18:51:00.000Z"
        },
        {
          "travelDuration": "838s",
          "travelDistanceMeters": 8780,
          "trafficInfoUnavailable": false,
          "delayDuration": "67s",
          "waitDuration": "0s",
          "totalDuration": "905s",
          "startTime": "2023-06-12T19:01:54.000Z"
        },
        {
          "travelDuration": "1278s",
          "travelDistanceMeters": 26367,
          "trafficInfoUnavailable": false,
          "delayDuration": "60s",
          "breakDuration": "1800s",
          "waitDuration": "0s",
          "totalDuration": "3138s",
          "startTime": "2023-06-12T19:17:59.000Z"
        },
        {
          "travelDuration": "3623s",
          "travelDistanceMeters": 84972,
          "trafficInfoUnavailable": false,
          "delayDuration": "60s",
          "waitDuration": "0s",
          "totalDuration": "3683s",
          "startTime": "2023-06-12T20:11:17.000Z"
        },
        {
          "travelDuration": "308s",
          "travelDistanceMeters": 3348,
          "trafficInfoUnavailable": false,
          "delayDuration": "108s",
          "waitDuration": "0s",
          "totalDuration": "416s",
          "startTime": "2023-06-12T21:13:40.000Z"
        },
        {
          "travelDuration": "221s",
          "travelDistanceMeters": 994,
          "trafficInfoUnavailable": false,
          "delayDuration": "60s",
          "waitDuration": "0s",
          "totalDuration": "281s",
          "startTime": "2023-06-12T21:21:36.000Z"
        },
        {
          "travelDuration": "2078s",
          "travelDistanceMeters": 42637,
          "trafficInfoUnavailable": false,
          "delayDuration": "180s",
          "waitDuration": "0s",
          "totalDuration": "2258s",
          "startTime": "2023-06-12T21:27:17.000Z"
        },
        {
          "travelDuration": "246s",
          "travelDistanceMeters": 1588,
          "trafficInfoUnavailable": false,
          "delayDuration": "180s",
          "waitDuration": "0s",
          "totalDuration": "426s",
          "startTime": "2023-06-12T22:05:55.000Z"
        },
        {
          "travelDuration": "133s",
          "travelDistanceMeters": 887,
          "trafficInfoUnavailable": false,
          "delayDuration": "60s",
          "waitDuration": "0s",
          "totalDuration": "193s",
          "startTime": "2023-06-12T22:14:01.000Z"
        },
        {
          "travelDuration": "110s",
          "travelDistanceMeters": 514,
          "trafficInfoUnavailable": false,
          "delayDuration": "120s",
          "waitDuration": "0s",
          "totalDuration": "230s",
          "startTime": "2023-06-12T22:18:14.000Z"
        },
        {
          "travelDuration": "171s",
          "travelDistanceMeters": 864,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "171s",
          "startTime": "2023-06-12T22:23:04.000Z"
        },
        {
          "travelDuration": "71s",
          "travelDistanceMeters": 277,
          "trafficInfoUnavailable": false,
          "delayDuration": "180s",
          "waitDuration": "0s",
          "totalDuration": "251s",
          "startTime": "2023-06-12T22:26:55.000Z"
        },
        {
          "travelDuration": "452s",
          "travelDistanceMeters": 3375,
          "trafficInfoUnavailable": false,
          "delayDuration": "180s",
          "waitDuration": "322s",
          "totalDuration": "954s",
          "startTime": "2023-06-12T22:32:06.000Z"
        },
        {
          "travelDuration": "658s",
          "travelDistanceMeters": 11338,
          "trafficInfoUnavailable": false,
          "delayDuration": "67s",
          "waitDuration": "0s",
          "totalDuration": "725s",
          "startTime": "2023-06-12T22:49:00.000Z"
        },
        {
          "travelDuration": "780s",
          "travelDistanceMeters": 9273,
          "trafficInfoUnavailable": false,
          "delayDuration": "54s",
          "waitDuration": "0s",
          "totalDuration": "834s",
          "startTime": "2023-06-12T23:02:05.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-12T23:16:59.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-12T23:17:59.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-12T23:18:59.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-12T23:19:59.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "535s",
          "totalDuration": "535s",
          "startTime": "2023-06-12T23:20:59.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-12T23:30:54.000Z"
        },
        {
          "travelDuration": "654s",
          "travelDistanceMeters": 6486,
          "trafficInfoUnavailable": false,
          "delayDuration": "180s",
          "waitDuration": "0s",
          "totalDuration": "834s",
          "startTime": "2023-06-12T23:31:54.000Z"
        },
        {
          "travelDuration": "299s",
          "travelDistanceMeters": 2573,
          "trafficInfoUnavailable": false,
          "delayDuration": "60s",
          "waitDuration": "0s",
          "totalDuration": "359s",
          "startTime": "2023-06-12T23:46:48.000Z"
        },
        {
          "travelDuration": "365s",
          "travelDistanceMeters": 3703,
          "trafficInfoUnavailable": false,
          "delayDuration": "67s",
          "waitDuration": "0s",
          "totalDuration": "432s",
          "startTime": "2023-06-12T23:53:47.000Z"
        },
        {
          "travelDuration": "780s",
          "travelDistanceMeters": 9273,
          "trafficInfoUnavailable": false,
          "delayDuration": "54s",
          "waitDuration": "0s",
          "totalDuration": "834s",
          "startTime": "2023-06-13T00:01:59.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-13T00:16:53.000Z"
        },
        {
          "travelDuration": "438s",
          "travelDistanceMeters": 3918,
          "trafficInfoUnavailable": false,
          "delayDuration": "180s",
          "waitDuration": "0s",
          "totalDuration": "618s",
          "startTime": "2023-06-13T00:17:53.000Z"
        },
        {
          "travelDuration": "507s",
          "travelDistanceMeters": 5109,
          "trafficInfoUnavailable": false,
          "delayDuration": "54s",
          "waitDuration": "0s",
          "totalDuration": "561s",
          "startTime": "2023-06-13T00:29:11.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-13T00:39:32.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-13T00:40:32.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-13T00:41:32.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-13T00:42:32.000Z"
        },
        {
          "travelDuration": "0s",
          "travelDistanceMeters": 0,
          "trafficInfoUnavailable": false,
          "waitDuration": "0s",
          "totalDuration": "0s",
          "startTime": "2023-06-13T00:43:32.000Z"
        }
      ],
      "hasTrafficInfeasibilities": false,
      "breaks": [
        {
          "startTime": "2023-06-12T00:00:00.000Z",
          "duration": "1800s"
        },
        {
          "startTime": "2023-06-12T06:00:00.000Z",
          "duration": "1800s"
        },
        {
          "startTime": "2023-06-12T12:00:00.000Z",
          "duration": "1800s"
        },
        {
          "startTime": "2023-06-12T19:17:59.000Z",
          "duration": "1800s"
        },
        {
          "startTime": "2023-06-13T00:43:32.000Z",
          "duration": "1800s"
        },
        {
          "startTime": "2023-06-13T06:00:00.000Z",
          "duration": "1800s"
        },
        {
          "startTime": "2023-06-13T12:00:00.000Z",
          "duration": "1800s"
        },
        {
          "startTime": "2023-06-13T18:00:00.000Z",
          "duration": "1800s"
        }
      ],
      "metrics": {
        "performedShipmentCount": 24,
        "travelDuration": "18727s",
        "waitDuration": "4971s",
        "delayDuration": "3088s",
        "breakDuration": "1800s",
        "visitDuration": "2880s",
        "totalDuration": "31466s",
        "travelDistanceMeters": 273949,
        "totalCost": 0,
        "performedMandatoryShipmentCount": 24
      },
      "travelSteps": [
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "282s",
          "distanceMeters": 2837,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "421s",
          "distanceMeters": 3547,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "838s",
          "distanceMeters": 8785,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "780s",
          "distanceMeters": 9278,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "437s",
          "distanceMeters": 3915,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "437s",
          "distanceMeters": 3616,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "815s",
          "distanceMeters": 8541,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "706s",
          "distanceMeters": 7169,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "838s",
          "distanceMeters": 8785,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "1277s",
          "distanceMeters": 26364,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "3623s",
          "distanceMeters": 84975,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "307s",
          "distanceMeters": 3348,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "220s",
          "distanceMeters": 993,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "2077s",
          "distanceMeters": 42634,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "245s",
          "distanceMeters": 1588,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "132s",
          "distanceMeters": 888,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "110s",
          "distanceMeters": 515,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "171s",
          "distanceMeters": 864,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "70s",
          "distanceMeters": 276,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "452s",
          "distanceMeters": 3374,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "658s",
          "distanceMeters": 11342,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "780s",
          "distanceMeters": 9278,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "653s",
          "distanceMeters": 6489,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "298s",
          "distanceMeters": 2576,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "364s",
          "distanceMeters": 3702,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "780s",
          "distanceMeters": 9278,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "437s",
          "distanceMeters": 3915,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "509s",
          "distanceMeters": 5107,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        },
        {
          "duration": "0s",
          "distanceMeters": 0,
          "trafficInfoUnavailable": false
        }
      ],
      "vehicleDetour": "31466s",
      "routeCosts": {
        "model.vehicles.cost_per_kilometer": 25.53359461185,
        "model.vehicles.cost_per_hour": 171.14007777777775,
        "model.vehicles.fixed_cost": 24.65
      },
      "routeTotalCost": 221.32367238962775,
      "vehicleName": "",
      "vehicleFullness": {
        "maxFullness": 0.8740555555555556,
        "activeDuration": 0.8740555555555556,
        "activeSpan": 0.18215815676739608
      }
    }

Time to next stop drops doesn't show the full time difference

Known to affect CSV and PDF exports, but may impact other parts of the application due to how it's calculated. The "Time to next stop" column in CSV and PDF exports can drop any differences in days, showing only the hourly difference as it would appear if both stops appeared within the same 24 hour time period. Example:

Stop 1: Visit end at Tue, 28 Feb 2023 16:30:00 GMT
Stop 2: Visit start at Fri, 31 Mar 2023 07:00:00 GMT

Time to next stop: 14:30:00

This is the correct time difference from 16:30:00 to 07:00:00, but not the actual total time difference.

Label shipments on gantt chart

Label shipment icons on the gantt chart with basic information (id and label). Permanent labels or on mouse hover may make better sense.

Routing client for dart?

Is there a cloud fleet grouting client for dart to use Optimization API.

We want to use Optimization API for a flutter app. After going through documentation it's not clear how to do it.

Is there some client similar to Java and Python client for this API?
Client Docs

Can't remove all break rules from a vehicle

Changes aren't kept when trying to remove all break requests or all frequency constraints from a vehicle. At least one entry for either is always kept when trying to remove all of them.

File upload validation occurs before file is selected

When uploading a JSON or ZIP file, the validation error "File is required" appears the moment "Choose a file" is selected, before the user has selected any file. This error should only appear if the user cancels selecting a file and no file is already selected in the input field.

Remember choice of Metrics per route or Metrics per shipment

On the Solution page, when navigating away from the Metadata view and back, Metrics per route is always shown first. The app could remember whether you were last viewing Metrics per route or Metrics per shipment to make it easier to go back and forth between the Gantt and Metadata views when looking at a solution.

Create Maps API Key with Terraform

API Keys can now be managed with Terraform via API Keys API. This could eliminate the need to manually create an API Key during project setup.

Reference: https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/apikeys_key

  • Enable API Keys API (apikeys.googleapis.com)
  • Define a new google_apikeys_key resource
    • Restrict the key's api_targets to the following:
      • Geocoding API
      • Maps JavaScript API
      • Places API
      • Static Maps API
    • Do not set any other restrictions
  • Store the key_string output value in the existing maps_api_key secret

After defining an google_apikeys_key resource:

  • Remove the manual "Create a Google Maps API Key" step in Project Setup doc
  • Remove the maps_api_key input variable from Terraform and Deployment doc
  • Include upgrade note that after deploying this version, users can delete their previous manually-created key

Shipment type requirements don't always save

When editing shipment type requirements, changes are not consistently saved to the data store. This seems to only occur the first time a field is changed after opening the Scenario Settings menu. Subsequent changes to a field (while the window is still open) are saved correctly.

This is caused by the shouldUpdateState function returning false for the shipment requirements form control the first time values are updated due to the touched property, one of the requirements for updating state, updating itself after the form updates have run.

Allow renaming references to Shipments

CFR may be used to for purposes other than delivering shipments, such as optimizing routes for carrying passengers. The ability to rename a "Shipment" to something like "Ride" or "Passenger" in the UI would allows users of these other use cases to use clearer and more appropriate terminology.

Updating the application deployment to store a shipment name configuration would allow renaming "Shipment" to any desired value and would persist for all users.

Vehicle Operators

Hi,

I was trying to get this demo running on my local. I had two problems when you click on Upload from CSV:
1. The third bullet option "Vehicle Operators" doesn't show up on this example;
2. The .csv samples that you gave us for the shipments (shipmentsSample.csv) and vehicles (vehiclesSample.csv) give me an error on step 4 "Geocode and Validate" that says: Error validating file: Cannot read properties of null (reading 'error')

Inside the code there's no error that can explains what happening.
Is there anyone with the same problem?

Thanks in advanced.
Regards,
Gabriela

Increase default memory limit on Cloud Run

The default 256mb of memory can result in a SERVICE UNAVAILABLE error on the frontend if the Cloud run instance runs out of memory when processing a large scenario. Either parameterizing the machine size or increasing the default to 512 should help prevent out of memory errors.

Need Clarification about Optimized Route with Cloud Fleet Routing

Hi,

I would like to know about how to create an Optimized Route with Cloud Fleet Routing based on Google's CFR GitHub (https://github.com/google/cfr). We already deployed it in our Cloud environment here.

My questions are,

  1. Why is the sequence of scenarios and solutions the same? They are not being sorted by distance or travel time first. For example, in the scenario there are labels 486538 and 61154 in sequence, but when the solution is generated, the metadata results based on metrics per shipment show the same order. However, there are other labels that are closer to 486538, it's 753006.
  2. How can we change the sequence based on distance and travel time first? Or provide some other optimization options?
  3. And how can we integrate it with the Google Maps Platform API, while Cloud Fleet Routing is a solution from Optimization AI?

Here is the scenario.json for the questions (https://drive.google.com/file/d/1jGgIAluA3lfYA2vRO7zr5huxAib1Qx93/view?usp=sharing)

Thank you,
Regards,
Yuda Adi

Uploaded injected solutions aren't respected

Uploading a scenario that contains an injected solution results in that injected solution more or less being discarded. The data is accepted into the app and maintained in the data store, but generating a solution does not take this injected solution into account and #45 (which may or may not be caused by this same issue) prevents the user from editing the relaxation constraints. This also results in a UI bug where the "iterate on solution" toggle will be on, but disabled.

Solution timeline doesn't always show travel steps

In some instances, travel steps may not be displayed on a timeline and an error is thrown. This appears to be related to trying to set the endTime property on lastTravelSegment, which may not always be set.

core.mjs:6494 ERROR TypeError: Cannot read properties of undefined (reading 'startTime')
    at getTimeline (timeline.selectors.ts:236:73)
    at timeline.selectors.ts:248:7
    at ngrx-store.mjs:697:30
    at memoized (ngrx-store.mjs:578:39)
    at defaultStateFn (ngrx-store.mjs:601:43)
    at ngrx-store.mjs:700:36
    at memoized (ngrx-store.mjs:578:39)
    at MapSubscriber.project (ngrx-store.mjs:478:52)
    at MapSubscriber._next (map.js:29:1)
    at MapSubscriber.next (Subscriber.js:49:1)

image

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.