diff --git a/pom.xml b/pom.xml
index 70b1264..1a071c2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
de.srsoftware
web4rail
- 1.4.46
+ 1.5.0
Web4Rail
jar
Java Model Railway Control
diff --git a/src/main/java/de/srsoftware/web4rail/devices/Decoder.java b/src/main/java/de/srsoftware/web4rail/devices/Decoder.java
index 8bb1c65..7f9c637 100644
--- a/src/main/java/de/srsoftware/web4rail/devices/Decoder.java
+++ b/src/main/java/de/srsoftware/web4rail/devices/Decoder.java
@@ -45,7 +45,6 @@ public class Decoder extends BaseClass implements Constants, Device {
private static final String CV = "cv";
private static final String NUM_FUNCTIONS = "numFunctions";
private String type;
- private Locomotive loco;
private int numFunctions = 2;
private int step;
private boolean reverse;
@@ -78,22 +77,26 @@ public class Decoder extends BaseClass implements Constants, Device {
}
private Window dismount() {
- if (isNull(loco)) return properties();
- Locomotive locomotive = loco;
+ Locomotive locomotive = parent();
+ if (isNull(locomotive)) return properties();
locomotive.removeDecoder(this);
- loco = null;
+ parent(null);
addLogEntry(t("Removed decoder from \"{}\".",locomotive));
return locomotive.properties();
}
public StringBuilder functions() {
- HashSet enabledFunctions = new HashSet<>();
- for (Function fun : loco.functions()) {
- if (fun.enabled(this)) enabledFunctions.add(fun.index());
- }
-
+ Locomotive loco = parent();
StringBuilder sb = new StringBuilder();
- for (int i=1; i<=numFunctions; i++) sb.append(" ").append(enabledFunctions.contains(i)?1:0);
+
+ if (isSet(loco)) {
+ HashSet enabledFunctions = new HashSet<>();
+ for (Function fun : loco.functions()) {
+ if (fun.enabled(this)) enabledFunctions.add(fun.index());
+ }
+
+ for (int i=1; i<=numFunctions; i++) sb.append(" ").append(enabledFunctions.contains(i)?1:0);
+ }
return sb;
}
@@ -162,6 +165,12 @@ public class Decoder extends BaseClass implements Constants, Device {
public int numFunctions() {
return numFunctions ;
}
+
+ @Override
+ public Locomotive parent() {
+ BaseClass p = super.parent();
+ return p instanceof Locomotive ? (Locomotive) p : null;
+ }
private Window program(Params params) {
String error = null;
@@ -239,6 +248,7 @@ public class Decoder extends BaseClass implements Constants, Device {
formInputs.add(t("Protocol"),div);
formInputs.add(t("Address"),new Tag("span").content(""+address()));
formInputs.add(t("Number of functions"),new Input(NUM_FUNCTIONS,numFunctions).numeric());
+ Locomotive loco = parent();
if (isSet(loco)) formInputs.add(t("Locomotive"),loco.button(loco.name()));
postForm.add(programming());
return super.properties(preForm, formInputs, postForm, errorMessages);
@@ -270,15 +280,15 @@ public class Decoder extends BaseClass implements Constants, Device {
selector.addOption(-1,t("no decoder"));
selector.addOption(0,t("new decoder"));
for (Decoder d: decoders) {
- if (freeOnly && isSet(d.loco)) continue;
+ if (freeOnly && isSet(d.parent())) continue;
selector.addOption(d.id(), d);
}
return selector;
}
public Decoder setLoco(Locomotive locomotive, boolean log) {
- loco = locomotive;
- if (log) addLogEntry(t("Mounted into \"{}\".",loco));
+ parent(locomotive);
+ if (log) addLogEntry(t("Mounted into \"{}\".",locomotive));
locomotive.setDecoder(this,log);
return this;
}
@@ -332,11 +342,7 @@ public class Decoder extends BaseClass implements Constants, Device {
if (params.containsKey(TYPE)) type = params.getString(TYPE);
if (params.containsKey(Device.PROTOCOL)) setProtocol(Protocol.valueOf(params.getString(Device.PROTOCOL)));
if (params.containsKey(NUM_FUNCTIONS)) numFunctions = params.getInt(NUM_FUNCTIONS);
+ Locomotive loco = parent();
return isSet(loco) ? loco.properties() : properties();
}
-
-
-
-
-
}
diff --git a/src/main/java/de/srsoftware/web4rail/functions/Function.java b/src/main/java/de/srsoftware/web4rail/functions/Function.java
index 01ef4e3..4c8114f 100644
--- a/src/main/java/de/srsoftware/web4rail/functions/Function.java
+++ b/src/main/java/de/srsoftware/web4rail/functions/Function.java
@@ -49,6 +49,10 @@ public abstract class Function extends BaseClass{
return null;
}
+ public boolean enabled() {
+ return enabled;
+ }
+
public boolean enabled(Decoder decoder) {
return enabled;
}
@@ -101,8 +105,9 @@ public abstract class Function extends BaseClass{
return selector;
}
- public void setState(boolean enabled) {
+ public Function setState(boolean enabled) {
this.enabled = enabled;
+ return this;
}
@Override
diff --git a/src/main/java/de/srsoftware/web4rail/functions/FunctionList.java b/src/main/java/de/srsoftware/web4rail/functions/FunctionList.java
index 9f62821..f8e9bef 100644
--- a/src/main/java/de/srsoftware/web4rail/functions/FunctionList.java
+++ b/src/main/java/de/srsoftware/web4rail/functions/FunctionList.java
@@ -44,4 +44,13 @@ public class FunctionList extends HashSet implements Constants{
stream().filter(fun -> name.equals(fun.name())).forEach(fun -> fun.setState(enabled));
return this;
}
+
+
+ public HashSet with(String name) {
+ HashSet subset = new HashSet<>();
+ for (Function f: this) {
+ if (f.name().equals(name)) subset.add(f);
+ }
+ return subset;
+ }
}
diff --git a/src/main/java/de/srsoftware/web4rail/functions/HeadLight.java b/src/main/java/de/srsoftware/web4rail/functions/HeadLight.java
index 0080048..b0d0b94 100644
--- a/src/main/java/de/srsoftware/web4rail/functions/HeadLight.java
+++ b/src/main/java/de/srsoftware/web4rail/functions/HeadLight.java
@@ -1,5 +1,14 @@
package de.srsoftware.web4rail.functions;
-public class HeadLight extends DirectedFunction {
+import de.srsoftware.web4rail.devices.Decoder;
+import de.srsoftware.web4rail.moving.Locomotive;
+public class HeadLight extends DirectedFunction {
+ @Override
+ public boolean enabled(Decoder decoder) {
+ Locomotive loco = decoder.parent();
+ if (isNull(loco) || !loco.isFirst()) return false;
+ boolean result = isSet(loco) && loco.isFirst() && super.enabled(decoder);
+ return result;
+ }
}
diff --git a/src/main/java/de/srsoftware/web4rail/functions/TailLight.java b/src/main/java/de/srsoftware/web4rail/functions/TailLight.java
index 4fc926a..1a5fcb5 100644
--- a/src/main/java/de/srsoftware/web4rail/functions/TailLight.java
+++ b/src/main/java/de/srsoftware/web4rail/functions/TailLight.java
@@ -1,5 +1,13 @@
package de.srsoftware.web4rail.functions;
-public class TailLight extends DirectedFunction {
+import de.srsoftware.web4rail.devices.Decoder;
+import de.srsoftware.web4rail.moving.Locomotive;
+public class TailLight extends DirectedFunction {
+ @Override
+ public boolean enabled(Decoder decoder) {
+ Locomotive loco = decoder.parent();
+ if (isNull(loco) || !loco.isLast()) return false;
+ return super.enabled(decoder);
+ }
}
diff --git a/src/main/java/de/srsoftware/web4rail/moving/Car.java b/src/main/java/de/srsoftware/web4rail/moving/Car.java
index 5bf7636..4b6ff7e 100644
--- a/src/main/java/de/srsoftware/web4rail/moving/Car.java
+++ b/src/main/java/de/srsoftware/web4rail/moving/Car.java
@@ -65,6 +65,8 @@ public class Car extends BaseClass implements Comparable{
protected int maxSpeedReverse = 0;
protected boolean orientation = FORWARD;
protected long distanceCounter = 0;
+
+ private boolean isFirst,isLast;
public Car(String name) {
this(name,null);
@@ -146,6 +148,24 @@ public class Car extends BaseClass implements Comparable{
public long drivenDistance() {
return distanceCounter;
}
+
+ public boolean isFirst() {
+ return isFirst;
+ }
+
+ public Car isFirst(boolean first) {
+ isFirst = first;
+ return this;
+ }
+
+ public boolean isLast() {
+ return isLast;
+ }
+
+ public Car isLast(boolean last) {
+ isLast = last;
+ return this;
+ }
public JSONObject json() {
JSONObject json = super.json();
diff --git a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java
index 5821f1d..9027c05 100644
--- a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java
+++ b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java
@@ -3,6 +3,7 @@ package de.srsoftware.web4rail.moving;
import java.io.IOException;
import java.util.Comparator;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Vector;
@@ -100,23 +101,24 @@ public class Locomotive extends Car implements Constants{
public static Fieldset cockpit(BaseClass locoOrTrain) {
int speed = 0;
String realm = null;
- Train train = null;
+ final Train train;
final Locomotive loco;
int maxSpeed = 0;
String id = null;
if (locoOrTrain instanceof Locomotive) {
- loco = (Locomotive) locoOrTrain;
+ loco = (Locomotive) locoOrTrain;
+ train = null;
realm = REALM_LOCO;
speed = loco.speed;
maxSpeed = loco.orientation ? loco.maxSpeedForward : loco.maxSpeedReverse;
id = "loco_"+loco.id();
} else if (locoOrTrain instanceof Train) {
+ loco = null;
train = (Train)locoOrTrain;
realm = REALM_TRAIN;
speed = train.speed;
maxSpeed = train.maxSpeed();
id = "train_"+train.id();
- loco = null;
} else return null;
HashMap params = new HashMap(Map.of(REALM,realm,ID,locoOrTrain.id()));
@@ -178,7 +180,12 @@ public class Locomotive extends Car implements Constants{
}
if (isSet(train)) {
-
+ train.functionNames().sorted().forEach(name -> {
+ Button btn = train.button(name, Map.of(ACTION,ACTION_TOGGLE_FUNCTION,FUNCTION,name));
+ if (train.functionEnabled(name)) btn.clazz("active");
+ btn.addTo(functions);
+
+ });
}
functions.addTo(fieldset);
@@ -222,7 +229,7 @@ public class Locomotive extends Car implements Constants{
return new Button(t("Save"), form).addTo(form).addTo(fieldset);
}
- private Stream functionNames() {
+ public Stream functionNames() {
return functions.stream().map(Function::name).sorted().distinct();
}
@@ -230,6 +237,10 @@ public class Locomotive extends Car implements Constants{
return functions;
}
+ public HashSet functions(String name){
+ return functions.with(name);
+ }
+
@Override
public JSONObject json() {
JSONObject json = super.json();
diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java
index 37e3bb6..a73cf07 100644
--- a/src/main/java/de/srsoftware/web4rail/moving/Train.java
+++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java
@@ -7,7 +7,6 @@ import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
@@ -29,6 +28,7 @@ import de.srsoftware.web4rail.Params;
import de.srsoftware.web4rail.Plan;
import de.srsoftware.web4rail.Plan.Direction;
import de.srsoftware.web4rail.Route;
+import de.srsoftware.web4rail.functions.Function;
import de.srsoftware.web4rail.tags.Button;
import de.srsoftware.web4rail.tags.Checkbox;
import de.srsoftware.web4rail.tags.Fieldset;
@@ -100,7 +100,6 @@ public class Train extends BaseClass implements Comparable {
private Route nextPreparedRoute;
private BrakeProcess brake;
- private HashMap functions = new HashMap<>();
public static Object action(Params params, Plan plan) throws IOException {
String action = params.getString(ACTION);
@@ -532,6 +531,16 @@ public class Train extends BaseClass implements Comparable {
return setSpeed(speed+steps);
}
+ public boolean functionEnabled(String name) {
+ return locos().flatMap(
+ loco -> loco.functions().stream().filter(f -> f.enabled() && f.name().equals(name))
+ ).findAny().isPresent();
+ }
+
+ public Stream functionNames() {
+ return locos().flatMap(Locomotive::functionNames).distinct();
+ }
+
private boolean hasLoco() {
return locos().count() > 0;
}
@@ -1057,7 +1066,14 @@ public class Train extends BaseClass implements Comparable {
private Object toggleFunction(Params params) {
String name = params.getString(FUNCTION);
String error = isNull(name) ? t("No function name passed to toggleFunction(…)") : null;
- // TODO
+ boolean enable = !functionEnabled(name);
+ locos().forEach(loco -> {
+ Function any = null;
+ for (Function f : loco.functions(name)) {
+ any = f.setState(enable);
+ }
+ if (isSet(any)) loco.decoder().queue();
+ });
return properties(error);
}
@@ -1074,12 +1090,18 @@ public class Train extends BaseClass implements Comparable {
*/
public Train turn() {
LOG.debug("{}.turn()",this);
- setSpeed(0);
- for (Car car : cars) car.turn();
reverse(cars);
+ updateEnds();
+ for (Car car : cars) car.turn();
return reverse();
}
+ private void updateEnds() {
+ for (Car car : cars) car.isFirst(false).isLast(false);
+ cars.firstElement().isFirst(true);
+ cars.lastElement().isLast(true);
+ }
+
public void unTrace(Tile tile) {
if (isSet(trace)) trace.remove(tile);
if (isSet(stuckTrace)) stuckTrace.remove(tile);