= TransportEditor
image:https://github.com/oskopek/TransportEditor/workflows/Java%20CI%20with%20Maven/badge.svg["build status", link="https://github.com/oskopek/TransportEditor/actions?query=workflow%3A%22Java+CI+with+Maven%22"]
My Bachelor thesis and individual software project, TransportEditor.
TransportEditor aims to be a problem editor and plan visualizer for the Transport domain from the IPC 2008. The goal is to create an intuitive GUI desktop application for making quick changes and re-planning, but also designing a new problem dataset from scratch.
=== Screenshot
image:transport-editor/docs/img/screenshot.png["TransportEditor screenshot", scalewidth="20%"]
=== Getting help
For users looking for help: a manual describing all possible features of TransportEditor is available in the app itself: in the upper menu bar item Help -> Help.
Post any development questions or comments you may have on Stack Overflow and/or don't hesitate to https://gitlab.com/oskopek/TransportEditor/issues[open an issue].
=== Running TransportEditor releases
TransportEditor-VERSION-jar-with-dependencies.jar
java -jar TransportEditor-VERSION-jar-with-dependencies.jar
=== Building & running TransportEditor
mvn clean install -DskipTests
mvn clean install
mvn clean install -Pit
mvn clean
mvn clean install -Pdocs
mvn exec:java
from the transport-editor
module directory.
If you want to run a translated version of TransportEditor, set your system locale accordingly and restart TransportEditor.
If you want to try out a translated version (on Linux), try: LC_ALL="LOCALE" java -jar TransportEditor.jar
, where
LOCALE
is any locale available on your system (run locale -a
to view all available).TransportEditor uses http://semver.org/[semantic versioning].
=== Setup your build environment
==== Linux & Mac
. Install Git
Fedora: sudo dnf install git
Ubuntu: sudo apt-get install git
. Install git-lfs from https://git-lfs.github.com/
. Install Java8 JDK -- link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[Oracle JDK Downloads] -- Select: Java Platform (JDK)
* NOTE*: You need jdk-8u40
or newer (JavaFX 8 dependency).
. Install Maven -- preferably the latest version you can.
Usually, your distribution's package management repository is enough:
Fedora: sudo dnf install mvn
Ubuntu: sudo apt-get install maven
. Fork the repository -- Create a fork of the link:https://gitlab.com/oskopek/TransportEditor/[oskopek/TransportEditor repository]
(under the logo) on GitLab, usually the fork will be called: yourusername/TransportEditor
.
. Clone the your fork -- run git clone https://gitlab.com/yourusername/TransportEditor.git
(or, preferably, use SSH: git clone git@gitlab.com:yourusername/TransportEditor.git
)
. Pull the LFS files -- run git lfs pull
. Run the build (see the Building section)
==== Windows
. Install Java8 JDK -- link:http://www.oracle.com/technetwork/java/javase/downloads/index.html[Oracle JDK Downloads] -- Select: Java Platform (JDK)
. Install Maven -- (preferably the latest version you can). See: http://maven.apache.org/guides/getting-started/windows-prerequisites.html[Maven on Windows] and http://maven.apache.org/download.cgi[Maven Downloads].
. Download and install GitHub for Windows at http://windows.github.com/[]. If you encounter any problems, see the http://windows.github.com/help.html[GitHub for Windows FAQ].
. Find the oskopek/TransportEditor
https://github.com/oskopek/TransportEditor[repository] on GitHub.
. Create a fork of the repository (right upper corner), usually the fork will be called yourusername/TransportEditor
.
. Run the build (see the Building section)
. The following workflow may be useful for you, if you're not familiar with Git/GitHub for Windows:
.. In the upper left window, you can view all uncommitted changes. Write the name and description of your changes and click the check button.
.. Once in a while, be sure to sync to send all commits to your GitHub fork.
.. After testing your changes, submit a pull request to oskopek/TransportEditor
through https://github.com/oskopek/TransportEditor/compare[GitHub].
... Click on compare across forks.
... Set the following:
base fork: oskopek/TransportEditor
base: master
head fork: yourusername/TransportEditor
compare: branchname
.. Click on Click to create a pull request for this comparison.
.. Our GitLab/Travis continuous integration server will test the merge of your pull request. You can view the results in the thread of the pull request.
.. Congratulations! Your pull request will get reviewed and probably be merged in.
=== Submitting an Issue
We use the https://gitlab.com/oskopek/TransportEditor/issues[GitLab issue tracker] to track bugs and features. Before submitting a bug report or feature request, check to make sure it hasn't already been submitted. When submitting a bug report, please include a public/internal https://gitlab.com/snippets/new[Snippet] that includes a stack trace and any details that may be necessary to reproduce the bug, including your Java version and operating system.
=== Contributing
NO CONTRIBUTIONS ARE ACCEPTED AT THIS TIME, THIS IS A CLASSROOM PROJECT.
Everyone is encouraged to help improve this project.
Here are some ways you can contribute:
=== Submitting a Pull Request
. http://help.github.com/fork-a-repo/[Fork the repository]
. http://learn.github.com/p/branching.html[Create a topic branch]
. Optional: To ease the process of contributing code back into TransportEditor,
please set-up https://github.com/oskopek/ide-config[IDE coding templates] first
. Implement your feature or bug fix
. If applicable, add tests and documentation for your feature or bug fix
(see link:transport-editor/docs/howto-write-documentation.adoc[How-to write documentation])
. Run mvn clean install -Pit
. If the tests fail, return to step 3 and 4
. Add, commit, and push your changes
. http://help.github.com/send-pull-requests/[Submit a pull request]
'''
== Development documentation
=== Short design description
The model for the Transport domain is pretty complicated, because it handles:
That's what this short section is for -- describing the ideas behind the model, so that reading the code afterwards is easier.
The model is split into 4 parts:
=== Plan
The plan consists of an ordered list of actions. There are two types of plans:
===== Visualizing plans
There are currently two ways to visualize both plan types:
Simple list -- both sequential and temporal versions look similar. Both are filterable by right clicking on the headers. Sequential: uses a simple drag-and-drop reorderable table of action arguments. See the screenshot on the top of the README for a preview. Is redrawn completely after every change. Temporal: in contrast to the sequential variant, this one cannot be reordered by dragging. The start times can however be edited, which will result in the table reordering itself. Is not redrawn completely, adjusts its internal state and redraws the necessary parts.
Gantt chart -- both sequential and temporal versions look alike, resembling a XY chart, the X axis being the time axis and the Y axis having all action objects. Both are redrawn every time the plan changes or it's filter in the simple list is changed. Sequential: using it to visualize sequential plans is quite non-interesting, as it offers almost no added insights on top of the simple list Temporal: when visualizing temporal plans with a Gantt, we can observe the synchronicity of planned actions and, to some extent, the cooperation of individual actors
//* "Graph" // Sequential: path with relationships to other tasks (precondition blockers) as edges // Temporal: graph (nodes sorted by time - find a visually pleasing way) with relationships to other tasks //(precondition blockers) as edges
==== Persisting plans
Using string manipulation and built-in constants and format, it is persisted into a VAL-like format.
For parsing, we assume a correct and valid VAL-like plan. A very simple string manipulation and Regex-based approach
is used for both temporal and sequential plans. Additionally, a simple http://www.antlr.org/[ANTLR] grammar
is used in some places. See the persistence
package for details.
=== Problem
The problem is basically a graph (with multiple possible "layers", f.e. fuel) and a vehicle and package map.
Currently we use http://graphstream-project.org/[GraphStream] for both the data storage and visualization of the graph. Apart from nodes and edge arrows, everything else is visualized as "link:http://graphstream-project.org/doc/Tutorials/Graph-Visualisation/#sprites[sprites]".
Fuel is added as different graph edge type (FuelRoad instead of DefaultRoad) and a domain label change
(see PddlLabel
s in the domain).
If the domain is fuel enabled, the fuel properties of locations, roads and vehicles else will be displayed.
===== Visualizing problems
Problem visualization does not fundamentally differ between different domains and problems. Some problem tooltips/properties might dis/appear when changing the domain type.
The graph is automatically laid out using a SpringBox
algorithm from GraphStream
for a given time and then switched to manual layout.
==== Persisting problems
Both rule pages of http://icaps-conference.org/ipc2008/deterministic/CompetitionRules.html[IPC-6] and https://helios.hud.ac.uk/scommv/IPC-14/rules.html[IPC-8] specify PDDL 3.1 as their official modelling language (language for domain and problem specification). Daniel L. Kovacs proposed an updated and corrected BNF (Backus-Naur Form) https://helios.hud.ac.uk/scommv/IPC-14/repository/kovacs-pddl-3.1-2011.pdf[definition of PDDL 3.1].
Using a http://freemarker.org/[Freemarker] template and a lot of string manipulation it is persisted into PDDL.
For parsing, we assume a correct and valid problem and use a formal grammar written in http://www.antlr.org/[ANTLR]
to parse PDDL into a generated code structure provided by ANTLR and the maven-antlr-plugin
. The same grammar as for
domains is used. See the persistence
package and the src/main/antlr4
folder for details.
=== Domain
There is basically only one domain type: VariableDomain
(we also have the notion of a SequentialDomain
,
but it is basically just an in-code hardcoded equivalent of loading the sequential Transport domain PDDL
into a VariableDomain
).
The domain contains flags (labels), telling us which "layers" are enabled and which are not. The UI, validator, IO and planner all take these into account. It also contains methods for action creation using their correct domain-specified definitions and provides other useful data (predicates, functions, ...).
===== Visualizing domains
Domains are not visualizable per se.
==== Persisting domains
Using a http://freemarker.org/[Freemarker] template and a lot of string manipulation it is persisted into PDDL.
For parsing, we assume a correct and valid problem and use a formal grammar written in http://www.antlr.org/[ANTLR]
to parse PDDL into a generated code structure provided by ANTLR and the maven-antlr-plugin
. The same grammar as for
problems is used.
TransportEditor doesn't load the PDDL domain definitions directly -- those are already built-in. We only read the domain files to check which subset of conditions the user has chosen to model.
In the UI, we can also create a domain using a dialog backed by the VariableDomainBuilder
.
It is essentially switchboard for gathering the appropriate flags and other properties the domain should have.
=== Session
The session is where everything comes together. It keeps an instance of the domain, problem and plan (and planner and validator, ...). We can use it to reason about what actions can be executed in the UI with the currently loaded objects and also as a quick persistence solution -- if you save a session, you can then load it next time and do not have to open all the individual parts again.
===== Visualizing sessions
Sessions are visualized by visualizing all their (possible) parts.
==== Persisting sessions
Sessions are persisted automatically to XML using https://x-stream.github.io/[XStream]. This means, all its properties should be reasonably serializable (by reflection).
=== Planning
Any class implementing the Planner
interface can be set as the planner for a session and if it has all the properties
that are needed (domain & problem), we can generate a plan using an instance of that class. TransportEditor supports
external (executable) planners out of the box, given that the executable adhere to a few rules (for details, see
ExternalPlanner
). An end of planning event is raised after planning finishes, for UI redrawing purposes.
=== Validation
Any class implementing the Validator
interface can be used as a validator for plans in a planning session.
Validation happens automatically after planning in a session or it can be triggered manually. There are different
validators with different strictness (used for different domain variants). Choosing a wrong combination of domain,
problem and validator might cause false positives or false negatives, make sure to read the documentation of the
individual validators. TransportEditor supports a popular external validator called VAL, out of the box.
=== General notes
There are few other small features of the project worth mentioning.
==== CDI & the EventBus
CDI (Context and Dependency Injection) using http://weld.cdi-spec.org/[Weld] is used for inversion of control and for communication without tight coupling. Should only be used in the UI part of the project.
For event-driven communication on the front end, Guava's EventBus
is used. Again, it enables persistent
reactive handling without tight coupling.
==== JavaFX properties and bindings
The JavaFX based UI makes heavy use of bindings and properties, essential features of JavaFX. They enable reactive changes to the UI in an efficient manner, but can be a bit tricky when reading code that uses them. For even more power, we use the http://fxexperience.com/controlsfx/[ControlsFX] library, but try to avoid it, if possible.
==== Model immutability
The model (mainly the package com.oskopek.transport.model
) is designed to be immutable
(excluding a few exceptions). This makes it easier to reason about complex, possibly multithreaded operations
on top of it. This note is useful to keep in mind when reading code that changes the model data.
==== Tests
The project aims to be well tested and verified. To stick to these goals, we have several levels of tests, that are run by a CI (Continuous Integration) system after every push and should also be run by developers (at least) after every commit. The displayed test coverage in the README is calculated as an average of unit and integration test coverage.
TransportEditor currently has 3 types of tests:
*Test.java
) -- simple and quick to run tests that test one thing and test it well.*IT.java
) -- complex tests that handle multiple moving parts at once. Usually involving IO or
other not easily mockable things. Try to avoid abusively writing these in favour of unit tests, if possible.*UI.java
) -- test the UI using https://github.com/TestFX/TestFX[TestFX].
Under-represented and run not very often. CI doesn't run them by default at the moment.==== Comments, code style
TransportEditor employs a rigorous code style checker called checkstyle
that is run automatically at every build.
Please adhere to that style when extending/editing the code base. Multiple other unwritten and unspecified rules might
apply. Please, do not take any style comments personally -- they are in place so that the code remains in tact and
readable in the long term.
As part of the checkstyle
process, JavaDoc comments are enforced on every method and class (excluding tests).
They should briefly describe the design/implementation choices, why they were made and any useful examples and or
other quirks.