:projectKey: org.optaweb.vehiclerouting:optaweb-vehicle-routing
:sonarBadge: image:https://sonarcloud.io/api/project_badges/measure?project={projectKey}
:sonarLink: link="https://sonarcloud.io/dashboard?id={projectKey}"

= OptaWeb Vehicle Routing

image:https://travis-ci.com/kiegroup/optaweb-vehicle-routing.svg?branch=master[
"Build Status", link="https://travis-ci.com/kiegroup/optaweb-vehicle-routing"]

{sonarBadge}&metric=alert_status["Quality Gate Status", {sonarLink}]
{sonarBadge}&metric=reliability_rating["Reliability Rating", {sonarLink}]
{sonarBadge}&metric=security_rating["Security Rating", {sonarLink}]
{sonarBadge}&metric=sqale_rating["Maintainability Rating", {sonarLink}]
{sonarBadge}&metric=ncloc["Lines of Code", {sonarLink}]
{sonarBadge}&metric=coverage["Coverage", {sonarLink}]

Web application for solving the https://www.optaplanner.org/learn/useCases/vehicleRoutingProblem.html[Vehicle Routing Problem]
using https://www.optaplanner.org/[OptaPlanner].

== Starting the application

First, clone this repository and `cd` into it.

Frontend and backend are built and run independently. Open two terminal windows. Start the backend first, and then, when the backend is ready, start the frontend.

=== Running the backend

JDK 8 is the only system prerequisite for the backend. To install OpenJDK 8 on Fedora, run:

[source,shell]
----
sudo dnf install java-1.8.0-openjdk-devel
----

. Download OpenStreetMap data for a region. For demonstration purposes, we use data for Belgium from Geofabrik:
.. Open http://download.geofabrik.de/europe/belgium.html.
.. Download the OSM file http://download.geofabrik.de/europe/belgium-latest.osm.pbf[belgium-latest.osm.pbf].
.. Save it to `optaweb-vehicle-routing/optaweb-vehicle-routing-backend/local/openstreetmap/belgium-latest.osm.pbf`.

. Build backend:
+
[source,shell]
----
cd optaweb-vehicle-routing-backend
./mvnw install
----

. Run backend:
+
[source,shell]
----
java -jar target/optaweb-vehicle-routing-backend-*.jar
----

When you start the backend for the first time, it will need several minutes to process the geographical information. Monitoring the terminal output, wait until the processing is complete, then start the frontend.

See
xref:optaweb-vehicle-routing-backend/README.adoc#development-guide[Backend Development Guide]
to learn how to run backend during development.

==== Configuring the working region

If you want to try a different region than Belgium, download an OSM file from
http://download.geofabrik.de/[Geofabrik]
and select it with `app.routing.osm-file` property when starting the backend.

Don't forget to use `app.region.country-codes` property to override geosearch results constraint.

There is currently only one out-of-the-box data set for Belgium
so the *Load demo* button won't work with other regions.

[source,shell]
----
java -jar target/optaweb-vehicle-routing-backend-*.jar \
--app.routing.osm-file=massachusetts-latest.osm.pbf \
--app.region.country-codes=US
----

[CAUTION]
.Using large OSM files
====
For best user experience, use smaller regions like individual European or US states.
Using OSM files larger than 1 GB will require significant RAM size
and take a lot of time (up to several hours) for the initial processing.
====

=== Running the frontend

. Install `npm`. If you're on Fedora, you can do this by running:
+
[source,shell]
----
sudo dnf install npm
----

. Install dependencies:
+
[source,shell]
----
cd optaweb-vehicle-routing-frontend
npm install
----

. Run frontend:
+
[source,shell]
----
npm start
----

. Open http://localhost:3000/ in a web browser. By default, the `npm start` command attempts to open this URL in your default browser.

[TIP]
.Prevent `npm start` from launching your default browser
====
If you don't want `npm start` to open a new browser tab each time you run it,
export an environment variable `BROWSER=none`.

You can use `.env.local` file to make this preference permanent.
To do that, run

[source,shell]
----
echo BROWSER=none >> .env.local
----
====

=== Creating custom data sets

There is a built-in demo data set consisting of a several large Belgian cities.
If you want to have more demos offered by the *Load demo* dropdown,
you can prepare your own data sets.
To do that, follow these steps:

. Add a depot and a set of visits by clicking on the map or using geosearch.
. Click *Export* and save the file in `optaweb-vehicle-routing-backend/local/data` directory.
. Edit the YAML file and choose a unique name for the data set.
. Restart the backend.

After you restart the backend, files in the `data` directory will be made available
in the *Load demo* dropdown.

== Using the application

In the OptaWeb Vehicle Routing application, you can mark a number of locations on the map. The first location is assumed to be the warehouse. Vehicles must deliver goods from this warehouse to every other location that you marked.

You can set the number of vehicles and the carrying capacity of every vehicle. However, the route is not guaranteed to use all vehicles. The application uses as many vehicles as required for an optimal route.

The current version has certain limitations:

* Every delivery to a location is supposed to take 1 point of vehicle capacity. For example, a vehicle with a capacity of 10 can visit up to 10 locations before returning to the warehouse.
* Setting custom names of vehicles and locations is not supported.
* Error information is not supported in the user interface. You must view the terminal output of the backend to see detailed error messages.

=== Creating a route

To create an optimal route, use the *Demo* tab of the user interface.

. Click *Demo* to open the *Demo* tab.
. Use the blue *+* and *-* buttons above the map to set the number of vehicles. Each vehicle has a default capacity of 10.
. Use the *+* button on the map to zoom in as necessary.
+
[NOTE]
====
Do not double-click to zoom in. A double click also creates a location.
====
+
. Click a location for the warehouse.
. Click other locations on the map for delivery points.
. If you want to delete a location:
.. Hover the mouse cursor over the location to see the location name.
.. Find the location name in the list in the left part of the screen.
.. Click the *x* icon next to the name.

Every time you add or remove a location or change the number of vehicles, the application creates and displays a new optimal route. If the solution uses several vehicles, the application shows the route for every vehicle in a different color.

=== Viewing and setting other details

You can use other tabs of the user interface to view and set additional details.

* In the *Vehicles* tab, you can view, add, and remove vehicles, and also set the capacity for every vehicle.
* In the *Visits* tab, you can view and remove locations.
* In the *Route* tab, you can select every vehicle and view the route for this vehicle.

=== Troubleshooting

If the application behaves unexpectedly, review the backend terminal output log.

To resolve issues, remove the backend database:

. Stop the backend by pressing Ctrl+C in the backend terminal window.
. Remove the directory `optaweb-vehicle-routing/optaweb-vehicle-routing-backend/local/db`.

== Running on a local OpenShift cluster

Use https://developers.redhat.com/products/codeready-containers[Red Hat CodeReady Containers]
to easily set up a single-node OpenShift 4 cluster on your local computer.

.Prerequisites
You have successfully built the project with Maven.

.Procedure
1. To install CRC, follow the https://code-ready.github.io/crc/[Getting Started Guide].

2. When the cluster has started,

a. add oc command-line interface to your `$PATH`:
+
[source,shell]
----
eval $(crc oc-env)
----

b. log in as "developer".
+
[source,shell]
----
oc login -u developer -p developer https://api.crc.testing:6443
----

3. Create a new project
+
[source,subs="quotes"]
----
oc new-project _project_name_
----

4. Run the script:
+
[source,subs="quotes"]
----
./runOnOpenShift.sh _osm_file_name_ _country_code_list_ _osm_file_download_url_
----
+
or

+
[source,shell]
----
./runOnOpenShift.sh --help
----
+
to see more details about how to use the script.

=== Updating the deployed application with local changes

==== Backend

Change the source code and build the backend module with Maven.
Then start OpenShift build:

[source,shell]
----
cd optaweb-vehicle-routing-backend
oc start-build backend --from-dir=. --follow
----

==== Frontend

Change the source code and build the frontend module with npm.
Then start OpenShift build:

[source,shell]
----
cd optaweb-vehicle-routing-frontend
oc start-build frontend --from-dir=docker --follow
----
