From b01c95bcac0490949325d9ed68acad5e35af0d89 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Thu, 11 Nov 2021 00:07:29 +0100 Subject: [PATCH] started to implement direction option on destination selection --- pom.xml | 2 +- resources/js/plan.js | 19 ++++++++ resources/logback.xml | 2 +- .../de/srsoftware/web4rail/Destination.java | 43 +++++++++++++++++++ .../java/de/srsoftware/web4rail/Route.java | 8 ++++ .../web4rail/actions/PreserveRoute.java | 2 +- .../de/srsoftware/web4rail/moving/Train.java | 27 +++++++----- .../web4rail/threads/RoutePrepper.java | 13 +++--- .../de/srsoftware/web4rail/tiles/Block.java | 7 +++ .../de/srsoftware/web4rail/tiles/BlockH.java | 13 ++++++ .../de/srsoftware/web4rail/tiles/BlockV.java | 13 ++++++ .../de/srsoftware/web4rail/tiles/Tile.java | 6 +-- 12 files changed, 132 insertions(+), 23 deletions(-) create mode 100644 src/main/java/de/srsoftware/web4rail/Destination.java 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"));