diff --git a/pom.xml b/pom.xml
index cb041d8..c10e0fd 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
de.srsoftware
web4rail
- 1.3.2
+ 1.3.3
Web4Rail
jar
Java Model Railway Control
diff --git a/resources/css/style.css b/resources/css/style.css
index 58ff6ce..8f23dae 100644
--- a/resources/css/style.css
+++ b/resources/css/style.css
@@ -261,11 +261,15 @@ h4,ul{
}
.window .disabled{
- background: red;
+ background: orange;
padding: 3px;
display: table;
}
+.window tr.disabled {
+ display: table-row;
+}
+
svg.disabled circle,
svg.disabled line,
svg.disabled polygon,
@@ -309,6 +313,10 @@ table tr:hover td{
background: #cadbdb;
}
+table tr.disabled:hover td {
+ background: yellow;
+}
+
table.brake-times tr > *{
border-style: solid;
border-color: black;
diff --git a/resources/translations/Application.de.translation b/resources/translations/Application.de.translation
index 4fdf712..fdb91ab 100644
--- a/resources/translations/Application.de.translation
+++ b/resources/translations/Application.de.translation
@@ -1,4 +1,5 @@
abort : abbrechen
+Accessory : Zubehör
Actions : Aktionen
Actions\: : Aktionen:
Actions and contacts : Aktionen und Kontakte
@@ -26,6 +27,7 @@ Address\: : Adresse:
analyze : analysieren
Analyze : analysieren
Analyze may overwrite these routes! : Durch die Analyse können diese Fahrstraßen überschrieben werden!
+Analyzing plan... : Plan wird analysiert...
and : und
AndCondition : Und-Bedingung
Apply : Übernehmen
@@ -83,7 +85,6 @@ Current location\: {} : Aufenthaltsort: {}
Current velocity\: {} {} : Aktuelle Geschwindigkeit: {} {}
custom fields : benutzerdefinierte Felder
Decoder address : Decoder-Adresse
-Delay : Verzögerung
DelayedAction : verzögerte Aktion
delete : entfernen
delete route : Route löschen
@@ -152,8 +153,10 @@ Lower speed limit : Minimale Geschwindigkeit
Manage cars : Waggons verwalten
Manage locos : Lokomotiven verwalten
Manage trains : Züge verwalten
+Maximum delay : maximale Verzögerung
Maximum Speed : Höchstgeschwindigkeit
Maximum train length : maximale Zug-Länge
+Minimum delay : minimale Verzögerung
Minimum and maximum times (in Miliseconds) trains with the respective tag have to wait in this block. : Minamle und maximale Block-Haltezeit (in Millisekunden) für Züge mit der entsprchender Markierung.
Move tiles : Kacheln verschieben
name\: : Name:
@@ -194,9 +197,9 @@ quit autopilot : Autopilot beenden
{} reached it`s destination! : {} ist am Ziel angekommen!
ReactivateContact : Kontakt reaktivieren
Relay : Relais
-Relays and Turnouts : Relais und Weichen
-Relay/Turnout : Relais/Weiche
+Relay/Signal/Turnout : Relais/Signal/Weiche
Remove tag "{}" from train : Markierung "{}" von Zug entfernen
+Removed {} : {} gelöscht
Report Issue : Problem melden
reverse : wenden
Reversed {}. : {} umgedreht.
diff --git a/src/main/java/de/srsoftware/web4rail/Device.java b/src/main/java/de/srsoftware/web4rail/Device.java
index b2fdab5..978b206 100644
--- a/src/main/java/de/srsoftware/web4rail/Device.java
+++ b/src/main/java/de/srsoftware/web4rail/Device.java
@@ -1,9 +1,13 @@
package de.srsoftware.web4rail;
+import de.srsoftware.tools.Tag;
+
public interface Device {
public static final String ADDRESS = "address";
public static final String PORT = "port";
public static final String PROTOCOL = "proto";
public int address();
+
+ public Tag link(String...args);
}
diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java
index 8bdd0ec..bd6bae5 100644
--- a/src/main/java/de/srsoftware/web4rail/Plan.java
+++ b/src/main/java/de/srsoftware/web4rail/Plan.java
@@ -9,7 +9,7 @@ import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.security.InvalidParameterException;
import java.util.Collection;
-import java.util.Comparator;
+import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@@ -650,7 +650,7 @@ public class Plan extends BaseClass{
return actions.addTo(actionMenu);
}
- private Window properties(HashMap params) {
+ public Window properties(HashMap params) {
if (params.containsKey(ID)) {
Tile tile = get(Id.from(params), true);
if (isSet(tile)) return tile.properties();
@@ -689,18 +689,41 @@ public class Plan extends BaseClass{
}
private Fieldset relayProperties() {
- Fieldset fieldset = new Fieldset(t("Relays and Turnouts"));
+ Fieldset fieldset = new Fieldset(t("Accessory"));
Table table = new Table();
- table.addHead(t("Address"),t("Relay/Turnout"));
+ table.addHead(t("Address"),t("Relay/Signal/Turnout"));
+
List devices = BaseClass.listElements(Tile.class)
.stream()
.filter(tile -> tile instanceof Device )
.map(tile -> (Device) tile)
- .sorted(Comparator.comparing(Device::address))
.collect(Collectors.toList());
+
+ for (Signal signal : BaseClass.listElements(Signal.class)) {
+ for (int addr : signal.addresses()) {
+ devices.add(new Device() {
+ @Override
+ public int address() {
+ return addr;
+ }
+
+ @Override
+ public Tag link(String... args) {
+ return signal.link(args);
+ }
+
+ @Override
+ public String toString() {
+ return signal.toString();
+ }
+ });
+ }
+ }
+
+ Collections.sort(devices, (d1,d2) -> d1.address() - d2.address());
+
for (Device device : devices) {
- Tile tile = (Tile) device;
- table.addRow(device.address(),tile.link(tile.toString()));
+ table.addRow(device.address(),device.link(device.toString()));
if (device.address() % 4 == 1) table.children().lastElement().clazz("group");
}
@@ -719,8 +742,17 @@ public class Plan extends BaseClass{
Table table = new Table();
table.addHead(t("Name"),t("Start"),t("End"),t("Actions"));
List routes = BaseClass.listElements(Route.class);
+ Collections.sort(routes, (r1,r2) -> r1.name().compareTo(r2.name()));
for (Route route : routes) {
- table.addRow(route.link("span",route.name()),route.link("span", route.startBlock()),route.link("span", route.endBlock()),plan.button(t("simplify name"), Map.of(ACTION,ACTION_AUTO,ROUTE,route.id().toString())));
+ Tag actions = new Tag("div");
+ plan.button(t("simplify name"), Map.of(ACTION,ACTION_AUTO,ROUTE,route.id().toString())).addTo(actions);
+ route.button(t("delete"), Map.of(ACTION,ACTION_DROP)).addTo(actions);
+ Tag row = table.addRow(
+ route.link("span",route.name()),
+ route.link("span", route.startBlock()),
+ route.link("span", route.endBlock()),
+ actions);
+ if (route.isDisabled()) row.clazz("disabled");
}
table.clazz("turnouts").addTo(fieldset);
return fieldset;
diff --git a/src/main/java/de/srsoftware/web4rail/Route.java b/src/main/java/de/srsoftware/web4rail/Route.java
index e736d89..b786fca 100644
--- a/src/main/java/de/srsoftware/web4rail/Route.java
+++ b/src/main/java/de/srsoftware/web4rail/Route.java
@@ -24,7 +24,7 @@ import de.srsoftware.web4rail.Plan.Direction;
import de.srsoftware.web4rail.actions.Action;
import de.srsoftware.web4rail.actions.ActionList;
import de.srsoftware.web4rail.actions.BrakeStart;
-import de.srsoftware.web4rail.actions.BrakeStop;
+import de.srsoftware.web4rail.actions.DelayedAction;
import de.srsoftware.web4rail.actions.FinishRoute;
import de.srsoftware.web4rail.actions.PreserveRoute;
import de.srsoftware.web4rail.actions.SetSignal;
@@ -177,7 +177,8 @@ public class Route extends BaseClass {
switch (params.get(ACTION)) {
case ACTION_DROP:
route.remove();
- return t("Removed {}.",route);
+ plan.stream(t("Removed {}.",route));
+ return plan.properties(new HashMap());
case ACTION_PROPS:
return route.properties();
case ACTION_UPDATE:
@@ -319,11 +320,6 @@ public class Route extends BaseClass {
brakeProcessor = new BrakeProcessor(this,train);
}
- public void brakeStop() {
- train.setSpeed(0);
- if (isSet(brakeProcessor)) brakeProcessor.finish();
- }
-
protected Route clone() {
Route clone = new Route();
clone.startBlock = startBlock;
@@ -349,18 +345,19 @@ public class Route extends BaseClass {
trigger = secondContact.trigger();
for (Signal signal : signals) add(trigger,new SetSignal(this).set(signal).to(Signal.RED));
}
- if (!contacts.isEmpty()) {
- Contact lastContact = contacts.lastElement();
- add(lastContact.trigger(), new BrakeStop(this));
- add(lastContact.trigger(), new FinishRoute(this));
- }
+ if (!contacts.isEmpty()) add(contacts.lastElement().trigger(), new FinishRoute(this));
for (Entry entry : turnouts.entrySet()) {
Turnout turnout = entry.getKey();
Turnout.State state = entry.getValue();
add(ROUTE_SETUP,new SetTurnout(this).setTurnout(turnout).setState(state));
}
- for (Signal signal : signals) add(ROUTE_START,new SetSignal(this).set(signal).to(Signal.GREEN));
- add(ROUTE_START,new SetSpeed(this).to(999));
+ for (Signal signal : signals) add(ROUTE_SETUP,new SetSignal(this).set(signal).to(Signal.GREEN));
+ if (signals.isEmpty()) {
+ add(ROUTE_START,new SetSpeed(this).to(999));
+ } else {
+ DelayedAction da = new DelayedAction(this).setMinDelay(1000).setMaxDelay(7500);
+ add(ROUTE_START,da.add(new SetSpeed(this).to(999)));
+ }
return this;
}
@@ -427,11 +424,21 @@ public class Route extends BaseClass {
}
public void finish() {
+ if (isSet(train)) {
+ if (train.nextRoutePrepared()) {
+ if (isSet(brakeProcessor)) brakeProcessor.abort();
+ } else {
+ train.setSpeed(0);
+ if (isSet(brakeProcessor)) brakeProcessor.finish();
+ }
+ }
+
context.clear(); // prevent delayed actions from firing after route has finished
setSignals(Signal.RED);
- for (Tile tile : path) try {
+ for (Tile tile : path) try { // remove route from tiles on path
tile.unset(this);
} catch (IllegalArgumentException e) {}
+
Tile lastTile = path.lastElement();
if (lastTile instanceof Contact) {
lastTile.setTrain(null);
@@ -447,7 +454,7 @@ public class Route extends BaseClass {
train.setWaitTime(endBlock.getWaitTime(train,train.direction()));
}
if (train.route == this) train.route = null;
- if (!train.onTrace(startBlock) && startBlock.train() == train) startBlock.setTrain(null);
+ if (startBlock.train() == train && !train.onTrace(startBlock)) startBlock.setTrain(null); // withdraw train from start block only if trace does not go back there
}
train = null;
}
diff --git a/src/main/java/de/srsoftware/web4rail/actions/Action.java b/src/main/java/de/srsoftware/web4rail/actions/Action.java
index bd730ab..76ada8b 100644
--- a/src/main/java/de/srsoftware/web4rail/actions/Action.java
+++ b/src/main/java/de/srsoftware/web4rail/actions/Action.java
@@ -44,7 +44,6 @@ public abstract class Action extends BaseClass {
AddRemoveTag.class,
BrakeCancel.class,
BrakeStart.class,
- BrakeStop.class,
ConditionalAction.class,
DelayedAction.class,
DetermineTrainInBlock.class,
diff --git a/src/main/java/de/srsoftware/web4rail/actions/ActionList.java b/src/main/java/de/srsoftware/web4rail/actions/ActionList.java
index 98546e0..c8e2f80 100644
--- a/src/main/java/de/srsoftware/web4rail/actions/ActionList.java
+++ b/src/main/java/de/srsoftware/web4rail/actions/ActionList.java
@@ -61,6 +61,20 @@ public class ActionList extends Action implements Iterable{
public void clear() {
while (!actions.isEmpty()) actions.firstElement().remove();
}
+
+ @Override
+ public boolean correspondsTo(Action other) {
+ if (other instanceof ActionList) {
+ ActionList otherAL = (ActionList) other;
+ if (actions.size() != otherAL.actions.size()) return false;
+ for (int i=0; i{
if (o instanceof JSONObject) {
JSONObject jsonObject = (JSONObject) o;
Action action = Action.create(jsonObject.getString(TYPE),this);
- if (action != null) add(action.load(jsonObject));
+ if (isSet(action)) add(action.load(jsonObject));
}
}
}
diff --git a/src/main/java/de/srsoftware/web4rail/actions/BrakeStop.java b/src/main/java/de/srsoftware/web4rail/actions/BrakeStop.java
deleted file mode 100644
index e3d94c6..0000000
--- a/src/main/java/de/srsoftware/web4rail/actions/BrakeStop.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package de.srsoftware.web4rail.actions;
-
-import de.srsoftware.web4rail.BaseClass;
-
-public class BrakeStop extends Action {
-
- public BrakeStop(BaseClass parent) {
- super(parent);
- }
-
- @Override
- public boolean fire(Context context) {
- if (isNull(context.route()) || isNull(context.route().train())) return false;
- context.route().brakeStop();
- return true;
- }
-}
diff --git a/src/main/java/de/srsoftware/web4rail/actions/DelayedAction.java b/src/main/java/de/srsoftware/web4rail/actions/DelayedAction.java
index a111870..22d9af1 100644
--- a/src/main/java/de/srsoftware/web4rail/actions/DelayedAction.java
+++ b/src/main/java/de/srsoftware/web4rail/actions/DelayedAction.java
@@ -15,15 +15,18 @@ import de.srsoftware.web4rail.tags.Input;
public class DelayedAction extends ActionList {
public static final String DELAY = "delay";
+ public static final String MIN_DELAY = "min_delay";
+ public static final String MAX_DELAY = "max_delay";
private static final int DEFAULT_DELAY = 1000;
- private int delay = DEFAULT_DELAY;
+ private int min_delay = DEFAULT_DELAY;
+ private int max_delay = DEFAULT_DELAY;
public DelayedAction(BaseClass parent) {
super(parent);
}
-
+
public boolean equals(DelayedAction other) {
- return (delay+":"+actions).equals(other.delay+":"+other.actions);
+ return (min_delay+":"+max_delay+":"+actions).equals(other.min_delay+":"+other.max_delay+":"+other.actions);
}
@Override
@@ -31,8 +34,8 @@ public class DelayedAction extends ActionList {
Application.threadPool.execute(new Thread() {
public void run() {
try {
- Thread.sleep(delay);
- LOG.debug("{} ms passed by, firing actions:",delay);
+ Thread.sleep(min_delay + (min_delay < max_delay ? random.nextInt(max_delay - min_delay) : 0));
+ LOG.debug("{} ms passed by, firing actions:",min_delay);
} catch (InterruptedException e) {
LOG.warn("Interrupted Exception thrown while waiting:",e);
}
@@ -44,38 +47,69 @@ public class DelayedAction extends ActionList {
@Override
public JSONObject json() {
- return super.json().put(DELAY, delay);
+ return super.json().put(MIN_DELAY, min_delay).put(MAX_DELAY, max_delay);
}
public DelayedAction load(JSONObject json) {
super.load(json);
- delay = json.getInt(DELAY);
+ if (json.has(DELAY)) {
+ min_delay = json.getInt(DELAY);
+ max_delay = json.getInt(DELAY);
+ }
+ if (json.has(MIN_DELAY)) min_delay = json.getInt(MIN_DELAY);
+ if (json.has(MAX_DELAY)) max_delay = json.getInt(MAX_DELAY);
return this;
}
@Override
protected Window properties(List