Browse Source

implemented small delay between setting signal to go and start of train. various GUI improvements

lookup-tables
Stephan Richter 5 years ago
parent
commit
d3c3051605
  1. 2
      pom.xml
  2. 10
      resources/css/style.css
  3. 9
      resources/translations/Application.de.translation
  4. 4
      src/main/java/de/srsoftware/web4rail/Device.java
  5. 48
      src/main/java/de/srsoftware/web4rail/Plan.java
  6. 39
      src/main/java/de/srsoftware/web4rail/Route.java
  7. 1
      src/main/java/de/srsoftware/web4rail/actions/Action.java
  8. 16
      src/main/java/de/srsoftware/web4rail/actions/ActionList.java
  9. 17
      src/main/java/de/srsoftware/web4rail/actions/BrakeStop.java
  10. 60
      src/main/java/de/srsoftware/web4rail/actions/DelayedAction.java
  11. 5
      src/main/java/de/srsoftware/web4rail/actions/PreserveRoute.java
  12. 9
      src/main/java/de/srsoftware/web4rail/actions/SetSignal.java
  13. 2
      src/main/java/de/srsoftware/web4rail/conditions/BlockFree.java
  14. 7
      src/main/java/de/srsoftware/web4rail/tags/Table.java
  15. 5
      src/main/java/de/srsoftware/web4rail/tiles/Block.java
  16. 8
      src/main/java/de/srsoftware/web4rail/tiles/Signal.java

2
pom.xml

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>de.srsoftware</groupId>
<artifactId>web4rail</artifactId>
<version>1.3.2</version>
<version>1.3.3</version>
<name>Web4Rail</name>
<packaging>jar</packaging>
<description>Java Model Railway Control</description>

10
resources/css/style.css

@ -261,11 +261,15 @@ h4,ul{ @@ -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{ @@ -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;

9
resources/translations/Application.de.translation

@ -1,4 +1,5 @@ @@ -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: @@ -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: {} @@ -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 @@ -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 @@ -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.

4
src/main/java/de/srsoftware/web4rail/Device.java

@ -1,9 +1,13 @@ @@ -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);
}

48
src/main/java/de/srsoftware/web4rail/Plan.java

@ -9,7 +9,7 @@ import java.lang.reflect.InvocationTargetException; @@ -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{ @@ -650,7 +650,7 @@ public class Plan extends BaseClass{
return actions.addTo(actionMenu);
}
private Window properties(HashMap<String, String> params) {
public Window properties(HashMap<String, String> 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{ @@ -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<Device> 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{ @@ -719,8 +742,17 @@ public class Plan extends BaseClass{
Table table = new Table();
table.addHead(t("Name"),t("Start"),t("End"),t("Actions"));
List<Route> 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;

39
src/main/java/de/srsoftware/web4rail/Route.java

@ -24,7 +24,7 @@ import de.srsoftware.web4rail.Plan.Direction; @@ -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 { @@ -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<String,String>());
case ACTION_PROPS:
return route.properties();
case ACTION_UPDATE:
@ -319,11 +320,6 @@ public class Route extends BaseClass { @@ -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 { @@ -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<Turnout, Turnout.State> 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 { @@ -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 { @@ -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;
}

1
src/main/java/de/srsoftware/web4rail/actions/Action.java

@ -44,7 +44,6 @@ public abstract class Action extends BaseClass { @@ -44,7 +44,6 @@ public abstract class Action extends BaseClass {
AddRemoveTag.class,
BrakeCancel.class,
BrakeStart.class,
BrakeStop.class,
ConditionalAction.class,
DelayedAction.class,
DetermineTrainInBlock.class,

16
src/main/java/de/srsoftware/web4rail/actions/ActionList.java

@ -61,6 +61,20 @@ public class ActionList extends Action implements Iterable<Action>{ @@ -61,6 +61,20 @@ public class ActionList extends Action implements Iterable<Action>{
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<actions.size(); i++) {
if (!actions.get(i).correspondsTo(otherAL.actions.get(i))) return false;
}
return true;
}
return false;
}
public boolean drop(Action action) {
return actions.remove(action);
@ -125,7 +139,7 @@ public class ActionList extends Action implements Iterable<Action>{ @@ -125,7 +139,7 @@ public class ActionList extends Action implements Iterable<Action>{
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));
}
}
}

17
src/main/java/de/srsoftware/web4rail/actions/BrakeStop.java

@ -1,17 +0,0 @@ @@ -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;
}
}

60
src/main/java/de/srsoftware/web4rail/actions/DelayedAction.java

@ -15,15 +15,18 @@ import de.srsoftware.web4rail.tags.Input; @@ -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 { @@ -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 { @@ -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<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm) {
formInputs.add(t("Delay"),new Input(DELAY,delay).numeric().addTo(new Tag("span")).content(NBSP+"ms"));
formInputs.add(t("Minimum delay"),new Input(MIN_DELAY,min_delay).numeric().addTo(new Tag("span")).content(NBSP+"ms"));
formInputs.add(t("Maximum delay"),new Input(MAX_DELAY,max_delay).numeric().addTo(new Tag("span")).content(NBSP+"ms"));
return super.properties(preForm, formInputs, postForm);
}
public DelayedAction setMaxDelay(int max_delay) {
this.max_delay = max_delay;
return this;
}
public DelayedAction setMinDelay(int min_delay) {
this.min_delay = min_delay;
return this;
}
@Override
public String toString() {
return t("Wait {} ms, then:",delay);
public String toString() {
return t("Wait {} ms, then:",min_delay < max_delay ? min_delay+"…"+max_delay : min_delay);
}
@Override
protected Object update(HashMap<String, String> params) {
String d = params.get(DELAY);
if (d != null) try {
String d = params.get(MIN_DELAY);
if (isSet(d)) try {
int ms = Integer.parseInt(d);
if (ms < 0) throw new NumberFormatException(t("Delay must not be less than zero!"));
min_delay = ms;
} catch (NumberFormatException nfe) {
Window props = properties();
props.children().insertElementAt(new Tag("div").content(nfe.getMessage()), 2);
return props;
}
d = params.get(MAX_DELAY);
if (isSet(d)) try {
int ms = Integer.parseInt(d);
if (ms < 0) throw new NumberFormatException(t("Delay must not be less than zero!"));
delay = ms;
max_delay = ms;
} catch (NumberFormatException nfe) {
Window props = properties();
props.children().insertElementAt(new Tag("div").content(nfe.getMessage()), 2);
return props;
}
if (min_delay > max_delay) {
int dummy = min_delay;
min_delay = max_delay;
max_delay = dummy;
}
return super.update(params);
}
}

5
src/main/java/de/srsoftware/web4rail/actions/PreserveRoute.java

@ -19,10 +19,9 @@ public class PreserveRoute extends Action { @@ -19,10 +19,9 @@ public class PreserveRoute extends Action {
if (isNull(train)) return false;
if (isNull(route)) return false;
// These are NOT errors:
if (!train.usesAutopilot()) return true;
if (train.destination() == route.endBlock()) return true;
if (!train.usesAutopilot()) return true; // do not reserve routes, when not in auto-mode
if (train.destination() == route.endBlock()) return true; // do not reserve routes, when destination has been reached
Range waitTime = route.endBlock().getWaitTime(train,route.endDirection);
if (waitTime.max > 0) {

9
src/main/java/de/srsoftware/web4rail/actions/SetSignal.java

@ -23,6 +23,15 @@ public class SetSignal extends Action { @@ -23,6 +23,15 @@ public class SetSignal extends Action {
private Signal signal = null;
private String state = Signal.RED;
@Override
public boolean correspondsTo(Action other) {
if (other instanceof SetSignal) {
SetSignal otherSS = (SetSignal) other;
return otherSS.signal == this.signal;
}
return false;
}
@Override
public boolean fire(Context context) {
if (isNull(signal)) return false;

2
src/main/java/de/srsoftware/web4rail/conditions/BlockFree.java

@ -50,7 +50,7 @@ public class BlockFree extends Condition { @@ -50,7 +50,7 @@ public class BlockFree extends Condition {
@Override
public String toString() {
if (block == null) return t("[Click here to select block!]");
if (block == null) return "["+t("Click here to select block!")+"]";
return t(inverted ? "Block {} is occupied":"Block {} is free",block);
}

7
src/main/java/de/srsoftware/web4rail/tags/Table.java

@ -10,7 +10,7 @@ public class Table extends Tag{ @@ -10,7 +10,7 @@ public class Table extends Tag{
super("table");
}
public Table addRow(Object...cols) {
public Tag addRow(Object...cols) {
Tag row = new Tag("tr");
for (Object column : cols) {
Tag col = null;
@ -22,12 +22,13 @@ public class Table extends Tag{ @@ -22,12 +22,13 @@ public class Table extends Tag{
col.addTo(row);
}
row.addTo(this);
return this;
return row;
}
public Table addHead(Object...cols) {
Object[] tags = new Tag[cols.length];
for (int i=0; i<cols.length; i++) tags[i]= cols[i] instanceof Tag ? ((Tag)cols[i]).addTo(new Tag("th")) : new Tag("th").content(cols[i].toString());
return addRow(tags);
addRow(tags);
return this;
}
}

5
src/main/java/de/srsoftware/web4rail/tiles/Block.java

@ -2,6 +2,7 @@ package de.srsoftware.web4rail.tiles; @@ -2,6 +2,7 @@ package de.srsoftware.web4rail.tiles;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -305,7 +306,9 @@ public abstract class Block extends StretchableTile{ @@ -305,7 +306,9 @@ public abstract class Block extends StretchableTile{
if (isNull(exclude)) exclude = new Vector<Block>();
Select select = new Select(Block.class.getSimpleName());
new Tag("option").attr("value","0").content(t("unset")).addTo(select);
for (Block block : BaseClass.listElements(Block.class)) {
List<Block> blocks = BaseClass.listElements(Block.class);
Collections.sort(blocks, (b1,b2) -> b1.name.compareTo(b2.name));
for (Block block : blocks) {
if (exclude.contains(block)) continue;
Tag opt = select.addOption(block.id(), block);
if (block == preselected) opt.attr("selected", "selected");

8
src/main/java/de/srsoftware/web4rail/tiles/Signal.java

@ -44,6 +44,14 @@ public abstract class Signal extends Tile { @@ -44,6 +44,14 @@ public abstract class Signal extends Tile {
super();
}
public HashSet<Integer> addresses(){
HashSet<Integer> list = new HashSet<Integer>();
for (HashSet<int[]> commands : aspects.values()) {
for (int[] data : commands) list.add(data[0]);
}
return list;
}
@Override
protected Vector<String> classes() {
Vector<String> classes = super.classes();

Loading…
Cancel
Save