diff --git a/pom.xml b/pom.xml
index d18e830..fade0d1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -4,7 +4,7 @@
4.0.0
de.srsoftware
web4rail
- 1.5.27
+ 1.5.28
Web4Rail
jar
Java Model Railway Control
diff --git a/resources/js/plan.js b/resources/js/plan.js
index 7be17d8..1fb43fd 100644
--- a/resources/js/plan.js
+++ b/resources/js/plan.js
@@ -18,6 +18,23 @@ var clickHistory = [];
var messages = [];
var android = false;
+function addBlockDirections(){
+ $('.BlockH').each(function (){
+ let block = $(this);
+ let width = block.attr('viewBox').split(" ")[2];
+ block.append('');
+ block.append('');
+ block.html(block.html());
+ });
+ $('.BlockV').each(function (){
+ let block = $(this);
+ let height = block.attr('viewBox').split(" ")[3];
+ block.append('');
+ block.append('');
+ block.html(block.html());
+ });
+}
+
function addClass(data){
parts = data.split(" ");
$('#'+parts[0]).addClass(parts[1]);
@@ -63,6 +80,7 @@ function assign(context){
pendingAssignment = context;
closeWindows();
$(PLAN).css('cursor','help');
+ if (context.realm == 'train' && context.action == 'move')addBlockDirections();
return false;
}
@@ -101,6 +119,7 @@ function clickTile(x,y,shift){
request(pendingAssignment);
pendingAssignment = null;
$(PLAN).css('cursor','');
+ $('.direction').remove();
return false;
}
var json = {realm:'plan',action:'click',id:id};
diff --git a/resources/logback.xml b/resources/logback.xml
index ab98e5f..178bdde 100644
--- a/resources/logback.xml
+++ b/resources/logback.xml
@@ -8,7 +8,7 @@
- DEBUG
+ WARN
Brake, Contact, Feed, Route, e, u
diff --git a/src/main/java/de/srsoftware/web4rail/Destination.java b/src/main/java/de/srsoftware/web4rail/Destination.java
new file mode 100644
index 0000000..23e563c
--- /dev/null
+++ b/src/main/java/de/srsoftware/web4rail/Destination.java
@@ -0,0 +1,43 @@
+package de.srsoftware.web4rail;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import de.srsoftware.web4rail.Plan.Direction;
+import de.srsoftware.web4rail.tiles.Block;
+
+public class Destination {
+ private static final Logger LOG = LoggerFactory.getLogger(Destination.class);
+
+ private Direction enterDirection;
+ public Block block;
+
+ public Destination(Block block, Direction enterFrom) {
+ this.block = block;
+ this.enterDirection = enterFrom;
+ }
+
+ public Destination(Block block) {
+ this(block,null);
+ }
+
+ @SuppressWarnings("unused")
+ private Destination() {}
+
+ boolean accepts(Direction enterDirection) {
+ boolean result = this.enterDirection == null || enterDirection == null || this.enterDirection == enterDirection;
+ LOG.debug(BaseClass.t(result ? "{} accepts train from {}" : "{} does not accept train from {}",this,enterDirection.inverse()));
+ return result;
+ }
+
+ public String block() {
+ return block.id().toString();
+ };
+
+ @Override
+ public String toString() {
+ return enterDirection == null ? block.toString() : BaseClass.t("{} from {}",block,enterDirection.inverse());
+ }
+
+
+}
diff --git a/src/main/java/de/srsoftware/web4rail/Route.java b/src/main/java/de/srsoftware/web4rail/Route.java
index c82cd2d..c620e46 100644
--- a/src/main/java/de/srsoftware/web4rail/Route.java
+++ b/src/main/java/de/srsoftware/web4rail/Route.java
@@ -390,6 +390,14 @@ public class Route extends BaseClass {
return endBlock;
}
+ public Direction endDirection() {
+ return endDirection;
+ }
+
+ public boolean endsAt(Destination destination) {
+ return isSet(destination) && endBlock == destination.block && destination.accepts(endDirection);
+ }
+
public void finish(Train train) {
LOG.debug("{}.finish()",this);
if (isSet(context)) {
diff --git a/src/main/java/de/srsoftware/web4rail/actions/PreserveRoute.java b/src/main/java/de/srsoftware/web4rail/actions/PreserveRoute.java
index 50eb5e4..6ffe8e4 100644
--- a/src/main/java/de/srsoftware/web4rail/actions/PreserveRoute.java
+++ b/src/main/java/de/srsoftware/web4rail/actions/PreserveRoute.java
@@ -23,7 +23,7 @@ public class PreserveRoute extends Action {
// These are NOT errors:
if (!train.usesAutopilot()) return true; // do not reserve routes, when not in auto-mode
Block endBlock = route.endBlock();
- if (train.destination() == endBlock) return true; // do not reserve routes, when destination has been reached
+ if (route.endsAt(train.destination())) return true; // do not reserve routes, when destination has been reached
Integer waitTime = context.waitTime();
if (isSet(waitTime) && waitTime > 0) {
diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java
index 5697716..977e9dd 100644
--- a/src/main/java/de/srsoftware/web4rail/moving/Train.java
+++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java
@@ -23,6 +23,7 @@ import org.slf4j.LoggerFactory;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
+import de.srsoftware.web4rail.Destination;
import de.srsoftware.web4rail.LoadCallback;
import de.srsoftware.web4rail.Params;
import de.srsoftware.web4rail.Plan;
@@ -85,7 +86,8 @@ public class Train extends BaseClass implements Comparable {
private HashSet tags = new HashSet();
- private Block currentBlock,destination = null;
+ private Block currentBlock;
+ Destination destination = null;
HashSet trace = new HashSet();
private Vector lastBlocks = new Vector();
@@ -363,7 +365,7 @@ public class Train extends BaseClass implements Comparable {
return properties();
}
- public Block destination(){
+ public Destination destination(){
//LOG.debug("{}.destination()",this);
if (isNull(destination)) {
String destTag = destinationTag();
@@ -383,7 +385,7 @@ public class Train extends BaseClass implements Comparable {
break;
}
}
- destination = BaseClass.get(new Id(destTag));
+ destination = new Destination(BaseClass.get(new Id(destTag)));
}
}// else LOG.debug("→ heading towards {}",destination);
return destination;
@@ -395,7 +397,7 @@ public class Train extends BaseClass implements Comparable {
}
return null;
}
-
+
public String directedName() {
String result = name();
if (needsMainenance()) result+="⚠";
@@ -465,7 +467,7 @@ public class Train extends BaseClass implements Comparable {
direction = endedRoute.endDirection; // muss vor der Auswertung des Destination-Tags stehen!
Block endBlock = endedRoute.endBlock();
Block startBlock = endedRoute.startBlock();
- boolean resetDest = endBlock == destination;
+ boolean resetDest = endedRoute.endsAt(destination);
if (resetDest){
destination = null;
@@ -793,7 +795,7 @@ public class Train extends BaseClass implements Comparable {
Tag dest = new Tag("li").content(t("Destination")+COL);
if (isSet(destination)) {
- link("span",destination,Map.of(REALM,REALM_PLAN,ID,destination.id().toString(),ACTION,ACTION_CLICK),null).addTo(dest);
+ link("span",destination,Map.of(REALM,REALM_PLAN,ID,destination.block(),ACTION,ACTION_CLICK),null).addTo(dest);
new Button(t("Drop"),Map.of(REALM,REALM_TRAIN,ID,id,ACTION,ACTION_MOVE,DESTINATION,"")).addTo(dest);
}
button(t("Select from plan"),Map.of(ACTION,ACTION_MOVE,ASSIGN,DESTINATION)).addTo(dest);
@@ -869,7 +871,7 @@ public class Train extends BaseClass implements Comparable {
if (child == route) route = null;
//if (child == nextRoute) nextRoute = null; // TODO
if (child == currentBlock) currentBlock = null;
- if (child == destination) destination = null;
+ if (isSet(destination) && child == destination.block) destination = null;
if (child == routePrepper) routePrepper.stop();
cars.remove(child);
trace.remove(child);
@@ -947,22 +949,25 @@ public class Train extends BaseClass implements Comparable {
if (dest.isEmpty()) {
destination = null;
return properties();
- }
+ }
Tile tile = plan.get(new Id(dest), true);
if (isNull(tile)) return properties(t("Tile {} not known!",dest));
if (tile instanceof Block) {
+ Block block = (Block) tile;
+ Direction enterDirection = null;
if (shunting) {
boolean connection = currentBlock.routes().stream().anyMatch(route -> route.startBlock() == currentBlock && route.endBlock() == tile);
if (!connection) return t("No direct route from {} to {}",currentBlock,tile);
- }
+ } else enterDirection = block.determineDirection(dest);
- destination = (Block) tile;
+ destination = new Destination(block,enterDirection);
+
start(true);
return t("{} now heading for {}",this,destination);
}
return properties(t("{} is not a block!",tile));
}
-
+
public void setDestinationTrigger(Tile destinationTrigger) {
this.destinationTrigger = destinationTrigger;
}
diff --git a/src/main/java/de/srsoftware/web4rail/threads/RoutePrepper.java b/src/main/java/de/srsoftware/web4rail/threads/RoutePrepper.java
index 5395055..f3d41a9 100644
--- a/src/main/java/de/srsoftware/web4rail/threads/RoutePrepper.java
+++ b/src/main/java/de/srsoftware/web4rail/threads/RoutePrepper.java
@@ -9,6 +9,7 @@ import java.util.Vector;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
+import de.srsoftware.web4rail.Destination;
import de.srsoftware.web4rail.EventListener;
import de.srsoftware.web4rail.Plan.Direction;
import de.srsoftware.web4rail.Route;
@@ -44,8 +45,8 @@ public class RoutePrepper extends BaseClass implements Runnable{
return derived;
}
- public boolean endsAt(Block block) {
- return lastElement().endBlock() == block;
+ public boolean endsAt(Destination destination) {
+ return lastElement().endsAt(destination);
}
private Trail prepend(Trail trail) {
@@ -106,7 +107,7 @@ public class RoutePrepper extends BaseClass implements Runnable{
if (error) return new PriorityQueue<>();
- Block destination = train.destination();
+ Destination destination = train.destination();
Direction startDirection = c.direction();
LOG.debug("RoutePrepper.availableRoutes({},{},{}), dest = {}",startBlock,startDirection,train,destination);
@@ -232,7 +233,7 @@ public class RoutePrepper extends BaseClass implements Runnable{
if (error) return null;
- Block destination = train.destination();
+ Destination destination = train.destination();
Direction startDirection = context.direction();
@@ -241,7 +242,7 @@ public class RoutePrepper extends BaseClass implements Runnable{
PriorityQueue trails = new PriorityQueue<>();
for (Route route : startBlock.leavingRoutes()) {
- int score = (route.endBlock() == destination) ? 100_000 : 0;
+ int score = (route.endsAt(destination)) ? 100_000 : 0;
if (isSet(startDirection) && route.startDirection != startDirection) { // Route startet entgegen der aktuellen Fahrtrichtung des Zuges
if (!train.pushPull) continue; // Zug kann nicht wenden
@@ -253,7 +254,7 @@ public class RoutePrepper extends BaseClass implements Runnable{
if (!route.allowed(new Context(train).block(startBlock).direction(startDirection))) {
LOG.debug(" - {} not allowed for {}", route, train);
- if (route.endBlock() != destination) continue;
+ if (!route.endsAt(destination)) continue;
LOG.debug(" …overridden by destination of train!", route, train);
}
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Block.java b/src/main/java/de/srsoftware/web4rail/tiles/Block.java
index 5f0033b..6582fea 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/Block.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/Block.java
@@ -198,6 +198,11 @@ public abstract class Block extends StretchableTile{
return t("Trigger contact to learn new contact");
}
+ public List arrivingRoutes() {
+ return routes().stream().filter(route -> route.endBlock() == Block.this).collect(Collectors.toList());
+ }
+
+
@Override
protected HashSet classes() {
HashSet classes = super.classes();
@@ -243,6 +248,8 @@ public abstract class Block extends StretchableTile{
return internalContacts;
}
+ public abstract Direction determineDirection(String dest);
+
public abstract Direction directionA();
public abstract Direction directionB();
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/BlockH.java b/src/main/java/de/srsoftware/web4rail/tiles/BlockH.java
index 45c3fd4..f9cb52f 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/BlockH.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/BlockH.java
@@ -3,9 +3,12 @@ package de.srsoftware.web4rail.tiles;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
import de.srsoftware.web4rail.Connector;
import de.srsoftware.web4rail.Plan.Direction;
+import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.tiles.Turnout.State;
public class BlockH extends Block{
@@ -24,6 +27,16 @@ public class BlockH extends Block{
}
}
+ @Override
+ public Direction determineDirection(String id) {
+ Set endDirections = arrivingRoutes().stream().map(Route::endDirection).collect(Collectors.toSet());
+ if (endDirections.size()<2) return endDirections.stream().findAny().get();
+ if (stretch()<2) return null;
+ if (id().equals(id)) return directionB();
+ if (((x+stretch()-1)+"-"+y).equals(id)) return directionA();
+ return null;
+ }
+
@Override
public Direction directionA() {
return Direction.WEST;
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/BlockV.java b/src/main/java/de/srsoftware/web4rail/tiles/BlockV.java
index f3848c4..b36bcc9 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/BlockV.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/BlockV.java
@@ -3,8 +3,11 @@ package de.srsoftware.web4rail.tiles;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
import de.srsoftware.web4rail.Connector;
+import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.Plan.Direction;
import de.srsoftware.web4rail.tiles.Turnout.State;
@@ -24,6 +27,16 @@ public class BlockV extends Block{
}
}
+ @Override
+ public Direction determineDirection(String id) {
+ Set endDirections = arrivingRoutes().stream().map(Route::endDirection).collect(Collectors.toSet());
+ if (endDirections.size()<2) return endDirections.stream().findAny().get();
+ if (stretch()<2) return null;
+ if (id().equals(id)) return directionB();
+ if ((x+"-"+(y+stretch()-1)).equals(id)) return directionA();
+ return null;
+ }
+
@Override
public Direction directionA() {
return Direction.NORTH;
diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java
index 8b479bd..aa10fae 100644
--- a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java
+++ b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java
@@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Connector;
+import de.srsoftware.web4rail.Destination;
import de.srsoftware.web4rail.LoadCallback;
import de.srsoftware.web4rail.Params;
import de.srsoftware.web4rail.Plan;
@@ -539,8 +540,7 @@ public abstract class Tile extends BaseClass implements Comparable {
sb.append(", ");
sb.append(y);
sb.append(")");
- if (isSet(occupyingTrain))
- sb.append(title(occupyingTrain));
+ if (isSet(occupyingTrain)) sb.append(title(occupyingTrain));
return sb.toString();
}
@@ -553,7 +553,7 @@ public abstract class Tile extends BaseClass implements Comparable {
sb.append(" ");
sb.append(t(lengthUnit));
sb.append(")");
- Block dest = train.destination();
+ Destination dest = train.destination();
if (isSet(dest)) sb.append(" → ").append(dest);
sb.append(":\n");
train.cars().forEach(car -> sb.append("\t- ").append(car).append("\n"));