Step 5: Migrate the simulation model logic

Intro

Recall that in Part 1 and Part 2 we placed all simulation-related classes in the 'tutorial.model' package of the console app. In this part of the tutorial, this logic will be located in a separate subproject, or bundle, whose name ends with 'simulation'.

These were the wizard settings when we created the application (yours may have been different):

Wizard window

So, in this case, the simulation logic bundle will have the name 'com.company.tutorial3.simulation'. Names of other generated bundles will also start with 'com.company.tutorial3'.

Let’s explore the contents of the 'simulation' bundle:

Simulation bundle structure
  • The ExperimentRun class is almost the same as in the console application.

  • The Mapping class is similar to its counterpart in the console app.

  • The Model class plays the same role as in the console app, we will update this class soon.

  • The Arc and the Node classes in the graph subpackage are the same as their siblings in the 'tutorial.model' package of the console application.

Here is what we will do next:

  1. Migrate most of the 'tutorial.model' classes to the 'simulation' bundle of the desktop application.

  2. Update the Model class in the desktop application.

Migrate the model package and road graph classes

In the …​simulation bundle, rename the …​simulation.graph package to …​simulation.model (for example, if the root package is named com.company.tutorial3.simulation.graph, then it should change its name to com.company.tutorial3.simulation.model).

Use code refactoring capabilities of your IDE. In Eclipse, use package’s context menu item Refactor → Rename.

Move the Model class from the ..simulation package to the …​model package.

Use "Refactor" → "Move" context menu item for convenience, so that IDE updates the references appropriately.
Sometimes the IDE is not adding appropriate import statements. If the Model class fails to find the Mapping class after being moved to another package, add the missing import manually.

Now the …​simulation bundle file structure is close to what we already have in the console application.

Copy the following classes from the console application (tutorial.model package) into the …​simulation.model package in the desktop application:

  1. Asset

  2. Dispatcher

  3. RequestGenerator

  4. Statistics

  5. Store

  6. TransportationRequest

  7. TransportationTask

  8. Truck

  9. Warehouse

If you have both the desktop app and the console app opened in Eclipse, you can select those java files in the console app (in Project Explorer tree), copy them (use Ctrl+C or the context menu item), then select the target package, and finally paste the copied items (Ctrl+V or the context menu item).

There should be some compilation errors in the copied classes. This is OK, since they need an updated Model class.

Migrate the Model class

Rather than updating the Model class, we will replace it and fix any compilation errors.

First, remove the Model class from the the desktop application (…​simulation.model package).

Then, copy the Model class from the console application to the desktop application, into the …​simulation.model package.

This will cause a couple of compilation errors, so let’s fix them:

  • Open the 'MANIFEST.MF' file of the 'simulation' bundle and add 'org.apache.commons.math3' into the dependency list. This is required, since we are going to use various random distributions during simulation.

  • Remove any failing import statements.

  • Import the correct Scenario and Mapping classes. These should be from the desktop application source code.

  • Add a new import statement to the Model class:

import com.amalgamasimulation.randomdatamodel.DistributionFactory;
  • Replace the createPolyline() method:

private Polyline createPolyline(com.company.tutorial3.datamodel.Arc dmArc) {
    List<Point> points = new ArrayList<>();
    points.add(new Point(dmArc.getSource().getX(), dmArc.getSource().getY()));
    dmArc.getPoints().forEach(
            bendpoint -> points.add(new Point(bendpoint.getX(), bendpoint.getY())));
    points.add(new Point(dmArc.getDest().getX(), dmArc.getDest().getY()));
    return new Polyline(points.stream().distinct().toList());
}
  • In the Model class constructor, find the newRequestIntervalDistribution declaration and replace it:

var newRequestIntervalDistribution = DistributionFactory
                .createDistribution(scenario.getIntervalBetweenRequestsHrs(), randomGenerator);
  • Add the following methods to the Model class, as they are required by other classes in the desktop application:

public List<Arc> getArcs() {
    return arcs;
}

public GraphEnvironment<Node, Arc, ?> getGraphEnvironment() {
    return graphEnvironment;
}

public double getEndTime() {
    return dateToTime(scenario.getEndDate());
}

The simulation logic is now fully migrated. In your IDE you can safely close the project with the source code of Part 2.

Check the result

  1. Start the application (use the product file in the releng folder).

  2. Create a new scenario.

  3. Add two nodes, give them different IDs, make their names equal to IDs.

  4. Connect the nodes with an arc.

  5. Add one Warehouse at the 1st node, and one Store at the 2nd node. Make assets' names and IDs not null.

  6. Add one Truck, make sure all its fields are not null and the speed is positive.

  7. Click the root item of the Scenario structure tree and set 'Max delivery time' to be positive, edit 'Interval between requests' to contain some non-null value.

  8. Switch to the Simulation mode.

Model initialization should work without error, and the model should also run without issue.

But we still see no warehouses, stores, and trucks in the animation window. Let’s make them all visible.