From da2ad054ed3a4e25d5e583dc55ffa5bcb6ec70a2 Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Sun, 21 Mar 2021 05:42:30 +0100 Subject: [PATCH] bugfixes --- pom.xml | 2 +- resources/logback.xml | 2 +- .../de/srsoftware/web4rail/BaseClass.java | 5 + .../de/srsoftware/web4rail/Constants.java | 5 +- .../java/de/srsoftware/web4rail/Plan.java | 10 + .../java/de/srsoftware/web4rail/Route.java | 9 +- .../web4rail/actions/DelayedAction.java | 2 + .../actions/DetermineTrainInBlock.java | 2 +- .../web4rail/actions/WaitForContact.java | 6 +- .../de/srsoftware/web4rail/moving/Train.java | 149 +++++++---- .../de/srsoftware/web4rail/tiles/Block.java | 201 +++++---------- .../web4rail/tiles/BlockContact.java | 17 +- .../de/srsoftware/web4rail/tiles/Bridge.java | 2 +- .../de/srsoftware/web4rail/tiles/Contact.java | 18 +- .../de/srsoftware/web4rail/tiles/Tile.java | 239 +++++++++--------- .../de/srsoftware/web4rail/tiles/Turnout.java | 4 +- .../srsoftware/web4rail/tiles/TurnoutL.java | 8 +- .../srsoftware/web4rail/tiles/TurnoutR.java | 8 +- 18 files changed, 344 insertions(+), 345 deletions(-) diff --git a/pom.xml b/pom.xml index 08863d5..d5233a3 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.srsoftware web4rail - 1.4.3 + 1.4.4 Web4Rail jar Java Model Railway Control diff --git a/resources/logback.xml b/resources/logback.xml index ea36924..d9f71c5 100644 --- a/resources/logback.xml +++ b/resources/logback.xml @@ -9,7 +9,7 @@ DEBUG - Brake, Contact, Feed, Route, Train + Brake, Contact, Feed, Route, Train, e diff --git a/src/main/java/de/srsoftware/web4rail/BaseClass.java b/src/main/java/de/srsoftware/web4rail/BaseClass.java index 887e4aa..baec0d9 100644 --- a/src/main/java/de/srsoftware/web4rail/BaseClass.java +++ b/src/main/java/de/srsoftware/web4rail/BaseClass.java @@ -315,6 +315,11 @@ public abstract class BaseClass implements Constants{ public Button button(String text) { return button(text,null); } + + public boolean debug(String tx, Object... fills) { + LOG.debug(tx, fills); + return false; + } public Form form(String id,List> elements) { Form form = new Form(id); diff --git a/src/main/java/de/srsoftware/web4rail/Constants.java b/src/main/java/de/srsoftware/web4rail/Constants.java index 4df1d7f..a02f77d 100644 --- a/src/main/java/de/srsoftware/web4rail/Constants.java +++ b/src/main/java/de/srsoftware/web4rail/Constants.java @@ -58,15 +58,18 @@ public interface Constants { public static final String DEFAULT_SPEED_UNIT = "km/h"; public static final String DEFAULT_LENGTH_UNIT = "mm"; public static final String DISABLED = "disabled"; - public static final String DIRECTION = "direction"; + public static final String DIRECTION = "direction"; public static final String GITHUB_URL = "https://github.com/srsoftware-de/Web4Rail"; public static final String ID = "id"; + public static final String LOCKED = "locked"; public static final String NAME = "name"; public static final String NBSP = " "; public static final String NOTES = "notes"; + public static final String OCCUPIED = "occupied"; public static final String PARENT = "parent"; public static final String PORT = "port"; public static final String RELAY = "relay"; + public static final String RESERVED = "reserved"; public static final String ROUTE = "route"; public static final String STATE = "state"; public static final String TURNOUT = "turnout"; diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java index 0580994..f845cd9 100644 --- a/src/main/java/de/srsoftware/web4rail/Plan.java +++ b/src/main/java/de/srsoftware/web4rail/Plan.java @@ -12,6 +12,7 @@ import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; @@ -160,6 +161,7 @@ public class Plan extends BaseClass{ private ControlUnit controlUnit = new ControlUnit(this); // the control unit, to which the plan is connected private Contact learningContact; private Configuration appConfig; + private LinkedList listeners = new LinkedList<>(); /** * creates a new plan, starts to send heart beats @@ -283,6 +285,10 @@ public class Plan extends BaseClass{ return t("Added {}",tile.getClass().getSimpleName()); } + public void alter() { + while (!listeners.isEmpty()) listeners.removeFirst().fire(); + } + /** * search all possible routes in the plan * @param params @@ -641,6 +647,10 @@ public class Plan extends BaseClass{ } return t(moved ? "Tile(s) moved.":"No tile moved."); } + + public void onChange(EventListener listener) { + listeners.add(listener); + } /** * adds a new tile to the plan on the client side diff --git a/src/main/java/de/srsoftware/web4rail/Route.java b/src/main/java/de/srsoftware/web4rail/Route.java index e8c77e5..e2076dc 100644 --- a/src/main/java/de/srsoftware/web4rail/Route.java +++ b/src/main/java/de/srsoftware/web4rail/Route.java @@ -4,7 +4,6 @@ import java.io.BufferedWriter; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -37,7 +36,6 @@ import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Input; import de.srsoftware.web4rail.tags.Table; import de.srsoftware.web4rail.tags.Window; -import de.srsoftware.web4rail.threads.BrakeProcess; import de.srsoftware.web4rail.threads.RoutePrepper; import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.BlockContact; @@ -389,7 +387,8 @@ public class Route extends BaseClass { public void finish(Train train) { LOG.debug("{}.finish()",this); - train.endRoute(endBlock,endDirection); + context.invalidate(); + train.endRoute(this); setSignals(Signal.RED); freeIgnoring(null); train = null; @@ -767,7 +766,7 @@ public class Route extends BaseClass { } public boolean reserveFor(Context newContext) { - LOG.debug("{}.reserverFor({})",this,newContext); + LOG.debug("{}.reserverFor ({})",this,newContext); context = newContext; for (Tile tile : path) { @@ -859,7 +858,7 @@ public class Route extends BaseClass { String cause = this+".start("+train.name()+")"; if (!startActions.fire(context,cause)) return false; // start actions failed } - + context.waitTime(endBlock.getWaitTime(train, endDirection).random()); 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 5cca381..3d726f7 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/DelayedAction.java +++ b/src/main/java/de/srsoftware/web4rail/actions/DelayedAction.java @@ -38,7 +38,9 @@ public class DelayedAction extends ActionList { @Override public void execute() { LOG.debug("{} ms passed by, firing actions:",delay); + if (context.invalidated()) return; DelayedAction.super.fire(context,cause); + plan.alter(); } }; return true; diff --git a/src/main/java/de/srsoftware/web4rail/actions/DetermineTrainInBlock.java b/src/main/java/de/srsoftware/web4rail/actions/DetermineTrainInBlock.java index ed71f16..74dc651 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/DetermineTrainInBlock.java +++ b/src/main/java/de/srsoftware/web4rail/actions/DetermineTrainInBlock.java @@ -24,7 +24,7 @@ public class DetermineTrainInBlock extends Action { @Override public boolean fire(Context context,Object cause) { context.block(block); - context.train(block.train()); + context.train(block.occupyingTrain()); return true; } diff --git a/src/main/java/de/srsoftware/web4rail/actions/WaitForContact.java b/src/main/java/de/srsoftware/web4rail/actions/WaitForContact.java index f5f9c83..c922c9b 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/WaitForContact.java +++ b/src/main/java/de/srsoftware/web4rail/actions/WaitForContact.java @@ -8,13 +8,13 @@ import org.json.JSONObject; import de.srsoftware.tools.Tag; import de.srsoftware.web4rail.BaseClass; +import de.srsoftware.web4rail.EventListener; import de.srsoftware.web4rail.LoadCallback; import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Input; import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.threads.DelayedExecution; import de.srsoftware.web4rail.tiles.Contact; -import de.srsoftware.web4rail.tiles.Contact.Listener; import de.srsoftware.web4rail.tiles.Tile; public class WaitForContact extends ActionList { @@ -35,9 +35,9 @@ public class WaitForContact extends ActionList { LOG.debug("{}.fire(...) called, waiting for {}.",this,contact); if (isNull(contact)) return false; fired = false; - Listener listener = new Listener() { + EventListener listener = new EventListener() { @Override - public void fired(Object cause) { + public void fire() { LOG.debug("{} triggered, firing {}",contact,actions); fired = true; contact.removeListener(this); diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java index a3522ef..25455ae 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Train.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java @@ -226,14 +226,14 @@ public class Train extends BaseClass implements Comparable { carList.addHead(t("Car"),t("Actions")); boolean first = true; - for (Car car : this.cars) { + for (Car car : cars) { Tag link = car.link(car.name()+(car.stockId.isEmpty() ? "" : " ("+car.stockId+")")); Tag buttons = new Tag("span"); car.button(t("turn within train"),Map.of(ACTION,ACTION_TURN)).addTo(buttons); if (!first) { car.button("↑",Map.of(ACTION,ACTION_MOVE)).addTo(buttons); - car.button(t("decouple"),Map.of(ACTION,ACTION_DECOUPLE)).addTo(buttons); + car.button(t("decouple"),Map.of(ACTION,ACTION_DECOUPLE,REALM,REALM_CAR)).addTo(buttons); } button(t("delete"),Map.of(ACTION,ACTION_DROP,CAR_ID,car.id().toString())).addTo(buttons); carList.addRow(link,buttons); @@ -275,7 +275,8 @@ public class Train extends BaseClass implements Comparable { } if (isSet(currentBlock)) { Tag ul = new Tag("ul"); - if (isSet(currentBlock.train()) && currentBlock.train() != this) currentBlock.train().link().addTo(new Tag("li")).addTo(ul); + Train trainInBlock = isSet(currentBlock) ? currentBlock.occupyingTrain() : null; + if (isSet(trainInBlock) && trainInBlock != this) trainInBlock.link().addTo(new Tag("li")).addTo(ul); for (Train tr : currentBlock.trains()) { if (tr == this) continue; Tag li = new Tag("li").addTo(ul); @@ -319,10 +320,13 @@ public class Train extends BaseClass implements Comparable { dummy.addAll(cars); cars = dummy; } else { - for (Car car : parkingTrain.cars) cars.add(car.train(this)); + for (Car car : parkingTrain.cars) { + cars.add(car.train(this)); + } } parkingTrain.remove(); + if (isSet(currentBlock)) currentBlock.setTrain(this); } private static Object create(HashMap params, Plan plan) { @@ -350,6 +354,28 @@ public class Train extends BaseClass implements Comparable { } public Block destination(){ + LOG.debug("{}.destination()",this); + if (isNull(destination)) { + String destTag = destinationTag(); + LOG.debug("→ processing \"{}\"...",destTag); + if (isSet(destTag)) { + destTag = destTag.split(DESTINATION_PREFIX)[1]; + LOG.debug("....processing \"{}\"…",destTag); + for (int i=destTag.length()-1; i>0; i--) { + switch (destTag.charAt(i)) { + case FLAG_SEPARATOR: + destTag = destTag.substring(0,i); + i=0; + break; + case SHUNTING_FLAG: + LOG.debug("....enabled shunting option"); + shunting = true; + break; + } + } + destination = BaseClass.get(new Id(destTag)); + } + }// else LOG.debug("→ heading towards {}",destination); return destination; } @@ -360,11 +386,11 @@ public class Train extends BaseClass implements Comparable { return null; } - public String directedName(Direction dir) { + public String directedName() { String result = name(); String mark = autopilot ? "ⓐ" : ""; - if (isNull(dir)) return result; - switch (dir) { + if (isNull(direction)) return result; + switch (direction) { case NORTH: case WEST: return '←'+mark+result; @@ -416,35 +442,75 @@ public class Train extends BaseClass implements Comparable { } } - public void endRoute(Block endBlock, Direction endDirection) { + public void endRoute(Route endedRoute) { BrakeProcess brake = endBrake(); + direction = endedRoute.endDirection; // muss vor der Auswertung des Destination-Tags stehen! + Block endBlock = endedRoute.endBlock(); + Block startBlock = endedRoute.startBlock(); + shunting = false; if (endBlock == destination) { - quitAutopilot(); destination = null; + + String destTag = destinationTag(); + if (isSet(destTag)) { + LOG.debug("destination list: {}",destTag); + String[] parts = destTag.split(Train.DESTINATION_PREFIX); + for (int i=0; i0; i--) { + switch (destId.charAt(i)) { + case Train.FLAG_SEPARATOR: + destId = destId.substring(0,i); + i=0; + break; + case Train.TURN_FLAG: + turn = true; + LOG.debug("Turn flag is set!"); + break; + } + } + if (destId.equals(endBlock.id().toString())) { + if (turn) turn(); + + // update destination tag: remove and add altered tag: + removeTag(destTag); + destTag = destTag.substring(parts[1].length()+1); + if (destTag.isEmpty()) { // no further destinations + destTag = null; + } else addTag(destTag); + } + } + + if (isNull(destTag)) { + quitAutopilot(); + plan.stream(t("{} reached it`s destination!",this)); + } + + } if (isSet(brake)) brake.updateTime(); Integer waitTime = route.waitTime(); nextPreparedRoute = route.dropNextPreparedRoute(); if ((!autopilot)|| isNull(nextPreparedRoute) || (isSet(waitTime) && waitTime > 0)) setSpeed(0); route = null; - direction = endDirection; - endBlock.add(this, direction); + endBlock.setTrain(this); currentBlock = endBlock; trace.add(endBlock); + if (!trace.contains(startBlock)) startBlock.dropTrain(this); stuckTrace = null; - if (autopilot) { - if (isNull(waitTime) || waitTime == 0) { - start(false); - } else if (isSet(waitTime) && waitTime > 0) { - new DelayedExecution(waitTime,this) { - - @Override - public void execute() { - if (autopilot) Train.this.start(false); - } - }; - plan.stream(t("{} waiting {} secs",this,(int)(waitTime/1000))); - } + if (autopilot) { + if (isNull(waitTime)) waitTime = 0; + if (waitTime>0) plan.stream(t("{} waiting {} secs",this,(int)(waitTime/1000))); + new DelayedExecution(waitTime,this) { + + @Override + public void execute() { + if (autopilot) Train.this.start(false); + } + }; } } @@ -566,16 +632,14 @@ public class Train extends BaseClass implements Comparable { public void afterLoad() { if (json.has(TRACE)) json.getJSONArray(TRACE).forEach(elem -> { Tile tile = plan.get(new Id(elem.toString()), false); - if (tile instanceof Block) { - ((Block)tile).add(Train.this, direction); - } else if (tile.setTrain(Train.this)); + tile.setTrain(Train.this); trace.add(tile); }); if (json.has(BLOCK)) {// do not move this up! during set, other fields will be referenced! currentBlock = (Block) plan.get(Id.from(json, BLOCK), false); if (isSet(currentBlock)) { currentBlock.setTrain(Train.this); - currentBlock.add(Train.this, direction); +// currentBlock.add(Train.this, direction); } } } @@ -773,10 +837,7 @@ public class Train extends BaseClass implements Comparable { LOG.debug("train.reverse();"); if (isSet(direction)) direction = direction.inverse(); - if (isSet(currentBlock)) { - currentBlock.set(this,direction); - plan.place(currentBlock); - } + if (isSet(currentBlock)) plan.place(currentBlock); return this; } @@ -805,10 +866,10 @@ public class Train extends BaseClass implements Comparable { return select; } - public void set(Block newBlock) { + public Train set(Block newBlock) { LOG.debug("{}.set({})",this,newBlock); if (isSet(currentBlock)) { - if (newBlock == currentBlock) return; + if (newBlock == currentBlock) return this; currentBlock.free(this); } currentBlock = newBlock; @@ -817,6 +878,7 @@ public class Train extends BaseClass implements Comparable { lastBlocks.add(newBlock); if (lastBlocks.size()>32) lastBlocks.remove(0); } + return this; } private Object setDestination(HashMap params) { @@ -899,7 +961,7 @@ public class Train extends BaseClass implements Comparable { if (remaining.cars.isEmpty()) return false; remaining.direction = this.direction; this.name = null; - currentBlock.add(remaining,direction); + currentBlock.addParkedTrain(remaining); remaining.currentBlock = currentBlock; plan.place(currentBlock); return true; @@ -926,15 +988,9 @@ public class Train extends BaseClass implements Comparable { routePrepper = null; if (isSet(failedRoute)) failedRoute.reset(); LOG.debug("Starting {} failed due to unavailable route!",this); - if (autopilot) new DelayedExecution(250,this) { - - @Override - public void execute() { - if (autopilot) { - Train.this.start(false); - } - } - }; + plan.onChange(()->{ // wait for state change of plan + if (autopilot) Train.this.start(false); + }); }); routePrepper.start(); @@ -1017,7 +1073,10 @@ public class Train extends BaseClass implements Comparable { LOG.debug("update({})",params); pushPull = params.containsKey(PUSH_PULL) && params.get(PUSH_PULL).equals("on"); shunting = params.containsKey(SHUNTING) && params.get(SHUNTING).equals("on"); - if (params.containsKey(NAME)) name = params.get(NAME); + if (params.containsKey(NAME)) { + name = params.get(NAME); + if (isSet(currentBlock)) plan.place(currentBlock); + } if (params.containsKey(TAGS)) { String[] parts = params.get(TAGS).replace(",", " ").split(" "); tags.clear(); diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Block.java b/src/main/java/de/srsoftware/web4rail/tiles/Block.java index 5dcaea8..6aad8f2 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Block.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Block.java @@ -3,6 +3,7 @@ package de.srsoftware.web4rail.tiles; import java.io.IOException; import java.util.Collection; import java.util.HashMap; +import java.util.HashSet; import java.util.Iterator; import java.util.LinkedList; import java.util.List; @@ -43,16 +44,14 @@ public abstract class Block extends StretchableTile{ private class TrainList implements Iterable{ private LinkedList trains = new LinkedList(); - private HashMap dirs = new HashMap(); - public void add(Train train, Direction direction) { + public void add(Train train) { trains.remove(train); trains.addFirst(train); - if (isSet(direction)) dirs.put(train, direction); } - - public Direction directionOf(Train train) { - return dirs.get(train); + + public boolean contains(Train t) { + return trains.contains(t); } public Train first() { @@ -77,18 +76,12 @@ public abstract class Block extends StretchableTile{ } public boolean remove(BaseClass b) { - dirs.remove(b); return trains.remove(b); } - - public void set(Train train, Direction newDirection) { - dirs.put(train, newDirection); - } - @Override public String toString() { - return trains.stream().map(t -> t+"→"+directionOf(t)).reduce((s1,s2) -> s1+", "+s2).orElse(t("empty")); + return trains.stream().map(t -> "["+t+"]→"+t.direction()).reduce((s1,s2) -> s1+", "+s2).orElse(t("empty")); } } private static final String ALLOW_TURN = "allowTurn"; @@ -100,12 +93,11 @@ public abstract class Block extends StretchableTile{ private static final String RAISE = "raise"; public static final String ACTION_ADD_CONTACT = "add_contact"; private static final String PARKED_TRAINS = "parked_trains"; - private static final String TRAINS = "trains"; public String name = "Block"; public boolean turnAllowed = false; private Vector internalContacts = new Vector(); - private TrainList trains = new TrainList(); + private TrainList parkedTrains = new TrainList(); public Block() { super(); @@ -191,10 +183,11 @@ public abstract class Block extends StretchableTile{ private Vector waitTimes = new Vector(); - public void add(Train train,Direction direction) { + public void addParkedTrain(Train train) { + if (parkedTrains.contains(train)) return; if (isNull(train)) return; train.register(); - trains.add(train,direction); + parkedTrains.add(train); } @@ -204,10 +197,17 @@ public abstract class Block extends StretchableTile{ return t("Trigger contact to learn new contact"); } + @Override + protected HashSet classes() { + HashSet classes = super.classes(); + if (!parkedTrains.isEmpty()) classes.add(OCCUPIED); + return classes; + } + @Override public Object click(boolean shift) throws IOException { - if (!trains.isEmpty() && !shift) return trains.first().properties(); - return super.click(false); + Train train = occupyingTrain(); + return !shift && isSet(train) ? train.properties() : properties(); } public int compareTo(Block other) { @@ -255,25 +255,15 @@ public abstract class Block extends StretchableTile{ return this; } - private void dropFirstTrain() { - Train train = trains.first(); - if (isSet(train)) { - train.dropTrace(); - train.set(null); - trains.remove(train); - } + public void dropTrain(Train t) { + parkedTrains.remove(t); + plan.place(this); } @Override - public boolean free(Train train) { - LOG.debug("{}.free({})",this,train); - Train firstTrain = trains.first(); - if (isNull(firstTrain)) return true; - if (firstTrain != train) return false; - trains.remove(train); - if (isSet(firstTrain)) { - super.free(train); - } else super.setTrain(firstTrain); + public boolean free(Train oldTrain) { + parkedTrains.remove(oldTrain); + if (!super.free(oldTrain)) return false; return true; } @@ -304,11 +294,10 @@ public abstract class Block extends StretchableTile{ @Override public boolean isFreeFor(Context context) { - Train train = context.train(); - if (is(Status.DISABLED)) return false; - if (trains.isEmpty()) return true; - if (trains.first() == train) return true; - return train.isShunting(); // block contains train(s), thus it is only free for shunting train + if (!super.isFreeFor(context)) return false; + Train train = context.train(); + if (isSet(occupyingTrain()) && occupyingTrain() == train) return true; + return parkedTrains.isEmpty() || parkedTrains.contains(train) || train.isShunting(); } @Override @@ -317,7 +306,7 @@ public abstract class Block extends StretchableTile{ json.put(NAME, name); json.put(ALLOW_TURN, turnAllowed); JSONArray jWaitTimes = new JSONArray(); - for (WaitTime wt : waitTimes) jWaitTimes.put(wt.json()); + waitTimes.forEach(wt -> jWaitTimes.put(wt.json())); json.put(WAIT_TIMES, jWaitTimes); JSONObject jContacts = null; for (BlockContact contact : internalContacts) { @@ -328,22 +317,22 @@ public abstract class Block extends StretchableTile{ } if (isSet(jContacts)) json.put(CONTACT, jContacts); json.remove(REALM_TRAIN); // is set by TRAINS field for blocks - if (!trains.isEmpty()) { + if (!parkedTrains.isEmpty()) { JSONArray jTrains = new JSONArray(); - for (Train train : trains) { + for (Train train : parkedTrains) { JSONObject to = new JSONObject(); to.put(ID, train.id()); - Direction dir = trains.directionOf(train); - if (isSet(dir)) to.put(DIRECTION, dir.toString()); +// Direction dir = parkedTrains.directionOf(train); +// if (isSet(dir)) to.put(DIRECTION, dir.toString()); jTrains.put(to); } - json.put(TRAINS, jTrains); + json.put(PARKED_TRAINS, jTrains); } return json; } public Train lastTrain() { - return trains.last(); + return parkedTrains.last(); } public List leavingRoutes() { @@ -387,26 +376,15 @@ public abstract class Block extends StretchableTile{ new LoadCallback() { @Override public void afterLoad() { - if (json.has(TRAINS)) { - JSONArray jTrains = json.getJSONArray(TRAINS); - for (Object o : jTrains) { + if (json.has(PARKED_TRAINS)) { + JSONArray jParkedTrains = json.getJSONArray(PARKED_TRAINS); + for (Object o : jParkedTrains) { if (o instanceof JSONObject) { - JSONObject to = (JSONObject) o; - Id tID = new Id(to.getString(ID)); - Train train = BaseClass.get(tID); - Direction direction = to.has(DIRECTION) ? Direction.valueOf(to.getString(DIRECTION)) : null; - if (isSet(train)) { - train.set(Block.this); - trains.add(train, direction); - status = Status.OCCUPIED; - } + JSONObject trainData = (JSONObject) o; + Train train = BaseClass.get(Id.from(trainData)); + if (isSet(train)) parkedTrains.add(train.set(Block.this)); } } - } else if (json.has(PARKED_TRAINS)) { // legacy - for (Object id : json.getJSONArray(PARKED_TRAINS)) { - Train train = BaseClass.get(new Id(id.toString())); - if (isSet(train)) trains.add(train,null); - } } } }; @@ -417,38 +395,20 @@ public abstract class Block extends StretchableTile{ @Override public boolean lockFor(Context context, boolean downgrade) { Train newTrain = context.train(); - Route route = context.route(); - LOG.debug("{}.lock({})",this,newTrain); - if (isNull(newTrain)) return false; - Train train = trains.first(); - if (isSet(train) && train != newTrain) return false; - switch (status) { - case DISABLED: - return false; - case OCCUPIED: - if (!downgrade) break; - case FREE: - case RESERVED: - status = Status.LOCKED; - Direction dir = trains.directionOf(train); - if (isSet(route) && this == route.endBlock()) dir = route.endDirection; - add(newTrain,dir); - plan.place(this); - break; - case LOCKED: - break; // do not downgrade - } - return true; + LOG.debug("{}.lockFor({})",this,newTrain); + Train train = lockingTrain(); + if (newTrain == train || parkedTrains.isEmpty() || parkedTrains.contains(newTrain) || newTrain.isShunting()) return super.lockFor(context, downgrade); + return false; } @Override protected Window properties(List
preForm, FormInput formInputs, List
postForm,String...errors) { formInputs.add(t("Name"),new Input(NAME, name)); formInputs.add("",new Checkbox(ALLOW_TURN,t("Turn allowed"),turnAllowed)); - formInputs.add(t("Train"),Train.selector(trains.first(), null)); + formInputs.add(t("Train"),Train.selector(parkedTrains.first(), null)); postForm.add(contactForm()); postForm.add(waitTimeForm()); - if (!trains.isEmpty()) postForm.add(trainList()); + if (!parkedTrains.isEmpty()) postForm.add(trainList()); return super.properties(preForm, formInputs, postForm,errors); } @@ -467,27 +427,10 @@ public abstract class Block extends StretchableTile{ @Override public boolean reserveFor(Context context) { Train newTrain = context.train(); - Route route = context.route(); - LOG.debug("{}.reserverFor({})",this,newTrain); - if (isNull(newTrain)) return false; - Train train = trains.first(); - if (isSet(train) && train != newTrain) return false; - switch (status) { - case DISABLED: - return false; - case FREE: - status = Status.RESERVED; - Direction dir = trains.directionOf(train); - if (isSet(route) && this == route.endBlock()) dir = route.endDirection; - add(newTrain,dir); - plan.place(this); - break; - case OCCUPIED: - case LOCKED: - case RESERVED: - break; // do not downgrade - } - return true; + LOG.debug("{}.lockFor({})",this,newTrain); + Train train = lockingTrain(); + if (newTrain == train || parkedTrains.isEmpty() || parkedTrains.contains(newTrain) || newTrain.isShunting()) return super.reserveFor(context); + return false; } public BlockContact register(BlockContact contact) { @@ -499,18 +442,13 @@ public abstract class Block extends StretchableTile{ public void removeChild(BaseClass child) { super.removeChild(child); internalContacts.remove(child); - if (trains.remove(child)) plan.place(this); + if (parkedTrains.remove(child)) plan.place(this); } public void removeContact(BlockContact blockContact) { internalContacts.remove(blockContact); } - public void set(Train train, Direction direction) { - trains.set(train,direction); - } - - public abstract List startPoints(); @Override @@ -518,7 +456,9 @@ public abstract class Block extends StretchableTile{ if (isNull(replacements)) replacements = new HashMap(); replacements.put("%text%",name); Vector trainNames = new Vector(); - for (Train train: trains) trainNames.add(train.directedName(trains.directionOf(train))); + Train lockingTrain = lockingTrain(); + if (isSet(lockingTrain) /*&& !parkedTrains.contains(lockingTrain)*/) trainNames.add(lockingTrain.directedName()); + for (Train train: parkedTrains) trainNames.add(train.directedName()); if (!trainNames.isEmpty())replacements.put("%text%",String.join(" | ", trainNames)); Tag tag = super.tag(replacements); tag.clazz(tag.get("class")+" Block"); @@ -535,20 +475,10 @@ public abstract class Block extends StretchableTile{ return name + " @ ("+x+","+y+")"; } - @Override - public Train train() { - return train(false); - } - - public Train train(boolean last) { - return last ? trains.last() : trains.first(); - } - - private Fieldset trainList() { Fieldset fieldset = new Fieldset(t("Trains")); Tag list = new Tag("ul"); - for (Train t : trains) { + for (Train t : parkedTrains) { if (isSet(t)) t.link("li", t).addTo(list); } list.addTo(fieldset); @@ -556,7 +486,7 @@ public abstract class Block extends StretchableTile{ } public List trains(){ - return trains.list(); + return parkedTrains.list(); } @Override @@ -565,15 +495,14 @@ public abstract class Block extends StretchableTile{ if (params.containsKey(Train.class.getSimpleName())) { Id trainId = Id.from(params,Train.class.getSimpleName()); if (trainId.equals(0)) { // remove first train - dropFirstTrain(); + free(occupyingTrain()); } else { - Train train = Train.get(trainId); - if (isSet(train) && train != trains.first()) { - dropFirstTrain(); - train.dropTrace(); - if (connections(train.direction()).isEmpty()) train.heading(null); - train.set(this); - trains.add(train,train.direction()); + Train newTrain = Train.get(trainId); + if (isSet(newTrain) && newTrain != occupyingTrain()) { + free(occupyingTrain()); + newTrain.dropTrace(); + if (connections(newTrain.direction()).isEmpty()) newTrain.heading(null); + newTrain.set(this); } } } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/BlockContact.java b/src/main/java/de/srsoftware/web4rail/tiles/BlockContact.java index d053835..92eeb0b 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/BlockContact.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/BlockContact.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.util.Map; import de.srsoftware.tools.Tag; -import de.srsoftware.web4rail.Route; import de.srsoftware.web4rail.moving.Train; public class BlockContact extends Contact { @@ -27,15 +26,25 @@ public class BlockContact extends Contact { Block block = ((Block)parent()); return new Id(block.name+":"+block.indexOf(this)); } + + @Override + public Train lockingTrain() { + return parent().lockingTrain(); + } @Override public Tag tag(Map replacements) throws IOException { - return ((Block)parent()).tag(replacements); + return parent().tag(replacements); + } + + @Override + public Train occupyingTrain() { + return parent().occupyingTrain(); } @Override - public Train train() { - return ((Block)parent()).train(); + public Block parent() { + return (Block) super.parent(); } @Override diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Bridge.java b/src/main/java/de/srsoftware/web4rail/tiles/Bridge.java index 4dcbff2..98123b0 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Bridge.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Bridge.java @@ -67,7 +67,7 @@ public abstract class Bridge extends Tile { @Override public boolean setTrain(Train newTrain) { - if (train() == newTrain) return true; + if (occupyingTrain() == newTrain) return true; if (!super.setTrain(newTrain)) return false; return isNull(counterpart) ? true : counterpart.setTrain(newTrain); } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Contact.java b/src/main/java/de/srsoftware/web4rail/tiles/Contact.java index cbf28c5..3ac8baa 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Contact.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Contact.java @@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory; import de.srsoftware.tools.Tag; import de.srsoftware.web4rail.Application; import de.srsoftware.web4rail.BaseClass; +import de.srsoftware.web4rail.EventListener; import de.srsoftware.web4rail.actions.Action; import de.srsoftware.web4rail.actions.ActionList; import de.srsoftware.web4rail.moving.Train; @@ -34,12 +35,8 @@ public class Contact extends Tile{ protected int addr = 0; private ActionList actions; private OffTimer timer = null; - private HashSet listeners = new HashSet(); + private HashSet listeners = new HashSet(); - public interface Listener{ - public void fired(Object cause); - } - public Contact() { actions = new ActionList(this); } @@ -82,15 +79,16 @@ public class Contact extends Tile{ if (isSet(timer)) return; timer = new OffTimer(); } else { - LOG.debug("{} activated.",this); state = true; stream(); if (isSet(timer)) timer.abort(); - Train train = train(); + Train train = lockingTrain(); Context context = isSet(train) ? train.contact(this) : new Context(this); actions.fire(context,"Contact("+addr+")"); - for (Listener listener : listeners) listener.fired("Contact("+addr+")"); + for (EventListener listener : listeners) listener.fire(); + + plan.alter(); } } @@ -105,7 +103,7 @@ public class Contact extends Tile{ return this; } - public void addListener(Listener l) { + public void addListener(EventListener l) { listeners.add(l); } @@ -205,7 +203,7 @@ public class Contact extends Tile{ super.removeChild(child); } - public void removeListener(Listener listener) { + public void removeListener(EventListener listener) { listeners.remove(listener); } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java index 9157059..3d774a1 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.LoadCallback; import de.srsoftware.web4rail.Plan; import de.srsoftware.web4rail.Plan.Direction; import de.srsoftware.web4rail.Route; @@ -39,20 +40,6 @@ import de.srsoftware.web4rail.tags.Window; * */ public abstract class Tile extends BaseClass implements Comparable { - public enum Status { - DISABLED("disabled"), FREE("free"), RESERVED("reserved"), LOCKED("locked"), OCCUPIED("occupied"); - - private String tx; - - Status(String s) { - tx = s; - } - - @Override - public String toString() { - return tx; - } - } protected static Logger LOG = LoggerFactory.getLogger(Tile.class); private static int DEFAUT_LENGTH = 100; // 10cm @@ -65,11 +52,11 @@ public abstract class Tile extends BaseClass implements Comparable { private static final String Y = "y"; private boolean isTrack = true; + private boolean disabled; private int length = DEFAUT_LENGTH; protected Direction oneWay = null; private TreeSet routes = new TreeSet<>((r1, r2) -> r1.toString().compareTo(r2.toString())); - private Train train = null; - protected Status status = Status.FREE; + private Train reservingTrain,lockingTrain,occupyingTrain; public Integer x = null; public Integer y = null; @@ -81,13 +68,19 @@ public abstract class Tile extends BaseClass implements Comparable { HashSet classes = new HashSet(); classes.add("tile"); classes.add(getClass().getSimpleName()); - if (!is(Status.FREE)) classes.add(status.toString()); + if (isSet(reservingTrain)) classes.add(RESERVED); + if (isSet(lockingTrain)) classes.add(LOCKED); + if (isSet(occupyingTrain)) classes.add(OCCUPIED); return classes; } public Object click(boolean shift) throws IOException { LOG.debug("{}.click()", getClass().getSimpleName()); - if (isSet(train) && shift) return train.properties(); + if (!shift) { + if (isSet(occupyingTrain)) return occupyingTrain.properties(); + if (isSet(lockingTrain)) return lockingTrain.properties(); + } + return properties(); } @@ -105,10 +98,12 @@ public abstract class Tile extends BaseClass implements Comparable { return new HashMap<>(); } - public boolean free(Train t) { - if (isSet(train) && t != train) return false; - train = null; - status = Status.FREE; + public boolean free(Train oldTrain) { + if (isNull(oldTrain)) return false; + if (isSet(reservingTrain) && reservingTrain != oldTrain) return false; + if (isSet(lockingTrain) && lockingTrain != oldTrain) return false; + if (isSet(occupyingTrain) && occupyingTrain != oldTrain) return false; + reservingTrain = lockingTrain = occupyingTrain = null; plan.place(this); return true; } @@ -134,48 +129,44 @@ public abstract class Tile extends BaseClass implements Comparable { plan.place(tile); } - public boolean is(Status... states) { - for (Status s : states) { - if (status == s) return true; - } - return false; + public boolean isDisabled() { + return disabled; } public boolean isFreeFor(Context newTrain) { LOG.debug("{}.isFreeFor({})", this, newTrain); - if (is(Status.DISABLED)) { + if (isDisabled()) { LOG.debug("{} is disabled!", this); return false; } - - if (isNull(train)) { - LOG.debug("→ free"); - return true; + + Train train = newTrain.train(); + + if (isSet(reservingTrain) && reservingTrain != train) { + LOG.debug("{} is reserved for {}",reservingTrain); + return false; // nicht in reservierten Block einfahren! } - if (newTrain.train() == train) { // during train.reserveNext, we may encounter, parts, that are already reserved - // by the respective train, but having another route. do not compare routes - // in that case! - LOG.debug("already reserved by {} → true", train); - return true; + if (isSet(lockingTrain) && lockingTrain != train) { + LOG.debug("{} is locked for {}",lockingTrain); + return false; // nicht in reservierten Block einfahren! } - if (isSet(newTrain.train()) && newTrain.train().isShunting()) { - LOG.debug("occupied by {}. Allowed for shunting {}", train, newTrain.train()); - return true; + if (isSet(occupyingTrain) && occupyingTrain != train) { + LOG.debug("{} is occupied by {}",occupyingTrain); + return train.isShunting(); // nur in belegte Blöcke einfahren, wenn Rangiermodus aktiv! } - LOG.debug("occupied by {} → false", train); - return false; + return true; } - + public JSONObject json() { JSONObject json = super.json(); json.put(TYPE, getClass().getSimpleName()); if (isSet(x) && isSet(y)) json.put(POS, new JSONObject(Map.of(X, x, Y, y))); if (isSet(oneWay)) json.put(ONEW_WAY, oneWay); - if (is(Status.DISABLED)) json.put(DISABLED, true); - if (isSet(train)) json.put(REALM_TRAIN, train.id()); + if (disabled) json.put(DISABLED, true); + if (isSet(occupyingTrain)) json.put(REALM_TRAIN, occupyingTrain.id()); json.put(LENGTH, length); return json; } @@ -221,19 +212,53 @@ public abstract class Tile extends BaseClass implements Comparable { } public Tile load(JSONObject json) { - if (json.has(ID)) json.remove(ID); // id should be created from cordinates + if (json.has(ID)) json.remove(ID); // id should be created from coordinates super.load(json); if (json.has(POS)) { JSONObject pos = json.getJSONObject(POS); x = pos.getInt(X); y = pos.getInt(Y); } - if (json.has(DISABLED) && json.getBoolean(DISABLED)) status = Status.DISABLED; + if (json.has(DISABLED)) disabled = json.getBoolean(DISABLED); if (json.has(LENGTH)) length = json.getInt(LENGTH); if (json.has(ONEW_WAY)) oneWay = Direction.valueOf(json.getString(ONEW_WAY)); + if (json.has(REALM_TRAIN)) + new LoadCallback() { + + @Override + public void afterLoad() { + occupyingTrain = Train.get(new Id(json.getString(REALM_TRAIN))); + } + }; return this; } - + + public boolean lockFor(Context context,boolean downgrade) { + Train newTrain = context.train(); + LOG.debug("{}.lockFor({})",this,newTrain); + if (isNull(newTrain)) return false; + if (isSet(reservingTrain) && reservingTrain != newTrain) return debug("{} already reserved for {}",this,reservingTrain); + if (isSet(lockingTrain)) { + if (lockingTrain != newTrain) return debug("{} already locked by {}",this,lockingTrain); + return true; // already locked! + } + if (isSet(occupyingTrain)) { + if (occupyingTrain != newTrain && !newTrain.isShunting()) return debug("{} already occupied by {}",this,occupyingTrain); + lockingTrain = newTrain; + if (!downgrade) return true; + } + lockingTrain = newTrain; + reservingTrain = occupyingTrain = null; + plan.place(this); + return true; + } + + public Train lockingTrain() { + if (isSet(lockingTrain)) return lockingTrain; + if (isSet(occupyingTrain)) return occupyingTrain; + return null; + } + public boolean move(int dx, int dy) { int destX = x + (dx > 0 ? width() : dx); int destY = y + (dy > 0 ? height() : dy); @@ -250,6 +275,10 @@ public abstract class Tile extends BaseClass implements Comparable { protected void noTrack() { isTrack = false; } + + public Train occupyingTrain() { + return occupyingTrain; + } public Tile position(int x, int y) { this.x = x; @@ -266,18 +295,18 @@ public abstract class Tile extends BaseClass implements Comparable { String... errors) { Fieldset fieldset = null; - if (isSet(train)) { + if (isSet(occupyingTrain)) { fieldset = new Fieldset(t("Train")); - train.link("span", t("Train") + ":" + NBSP + train + NBSP).addTo(fieldset); - if (isSet(train.route())) { - train.button(t("stop"), Map.of(ACTION, ACTION_STOP)).addTo(fieldset); + occupyingTrain.link("span", t("Train") + ":" + NBSP + occupyingTrain + NBSP).addTo(fieldset); + if (isSet(occupyingTrain.route())) { + occupyingTrain.button(t("stop"), Map.of(ACTION, ACTION_STOP)).addTo(fieldset); } else { - train.button(t("depart"), Map.of(ACTION, ACTION_START)).addTo(fieldset); + occupyingTrain.button(t("depart"), Map.of(ACTION, ACTION_START)).addTo(fieldset); } - if (train.usesAutopilot()) { - train.button(t("quit autopilot"), Map.of(ACTION, ACTION_QUIT)).addTo(fieldset); + if (occupyingTrain.usesAutopilot()) { + occupyingTrain.button(t("quit autopilot"), Map.of(ACTION, ACTION_QUIT)).addTo(fieldset); } else { - train.button(t("auto"), Map.of(ACTION, ACTION_AUTO)).addTo(fieldset); + occupyingTrain.button(t("auto"), Map.of(ACTION, ACTION_AUTO)).addTo(fieldset); } } @@ -286,8 +315,8 @@ public abstract class Tile extends BaseClass implements Comparable { if (isTrack) { formInputs.add(t("Length"), new Input(LENGTH, length).numeric().addTo(new Tag("span")).content(NBSP + lengthUnit)); - Checkbox checkbox = new Checkbox(DISABLED, t("disabled"), is(Status.DISABLED)); - if (is(Status.DISABLED)) checkbox.clazz("disabled"); + Checkbox checkbox = new Checkbox(DISABLED, t("disabled"), disabled); + if (disabled) checkbox.clazz("disabled"); formInputs.add(t("State"), checkbox); } @@ -373,21 +402,15 @@ public abstract class Tile extends BaseClass implements Comparable { } public boolean setTrain(Train newTrain) { - if (isNull(newTrain)) return false; - if (isSet(train) && newTrain != train) return false; - switch (status) { // bisheriger Status - case DISABLED: - return false; - case FREE: - case RESERVED: - case LOCKED: - train = newTrain; - status = Status.OCCUPIED; - plan.place(this); - break; - case OCCUPIED: - break; - } + if (disabled) return false; + if (isNull(newTrain)) return false; + if (isSet(reservingTrain) && newTrain != reservingTrain) return false; + if (isSet(lockingTrain) && newTrain != lockingTrain) return false; + if (isSet(occupyingTrain) && newTrain != occupyingTrain) return false; + if (occupyingTrain == newTrain) return true; + occupyingTrain = newTrain; + reservingTrain = lockingTrain = null; + plan.place(this); return true; } @@ -456,10 +479,6 @@ public abstract class Tile extends BaseClass implements Comparable { return t("{}({},{})", getClass().getSimpleName(), x, y); } - public Train train() { - return train; - } - @Override public BaseClass remove() { while (!routes.isEmpty()) routes.first().remove(); @@ -473,61 +492,40 @@ public abstract class Tile extends BaseClass implements Comparable { LOG.debug("Removing {} from {}", childAsString, this); if (child instanceof Route) routes.remove(child); - if (child == train) train = null; + if (child == reservingTrain) reservingTrain = null; + if (child == lockingTrain) lockingTrain = null; + if (child == occupyingTrain) occupyingTrain = null; super.removeChild(child); plan.place(this); } - public boolean lockFor(Context context,boolean downgrade) { - Train newTrain = context.train(); - LOG.debug("{}.lockFor({})",this,newTrain); - if (isNull(newTrain)) return false; - if (isSet(train) && train != newTrain) return false; - switch (status) { - case DISABLED: - return false; - case OCCUPIED: - if (!downgrade) break; - case FREE: - case RESERVED: - status = Status.LOCKED; - plan.place(this); - break; - case LOCKED: - break; // already locked - } - return true; - } public boolean reserveFor(Context context) { Train newTrain = context.train(); LOG.debug("{}.reserverFor({})",this,newTrain); if (isNull(newTrain)) return false; - if (isSet(train) && train != newTrain) return false; - switch (status) { - case DISABLED: - return false; - case FREE: - status = Status.RESERVED; - train = newTrain; - plan.place(this); - break; - case OCCUPIED: - case LOCKED: - case RESERVED: - break; // do not downgrade + if (isSet(reservingTrain)) { + if (reservingTrain != newTrain) return debug("{} already reserved for {}",this,reservingTrain); + return true; // already reserved for newTrain + } + if (isSet(lockingTrain)) { + if (lockingTrain != newTrain) return debug("{} already locked by {}",this,lockingTrain); + return true; // do not downgrade! } + if (isSet(occupyingTrain)) { + if (occupyingTrain != newTrain && !newTrain.isShunting()) return debug("{} already occupied by {}",this,occupyingTrain); + return true; // do not downgrade! + } + reservingTrain = newTrain; + plan.place(this); return true; } public void setEnabled(boolean enabled) { - if (!enabled) { - status = Status.DISABLED; - } else if (is(Status.DISABLED)) { // Status nur ändern, wenn er bisher DISABLED war - status = isNull(train) ? Status.FREE : Status.OCCUPIED; - } - plan.place(this); + boolean show = (disabled == enabled); + disabled = !enabled; + if (show) plan.place(this); } public Tile update(HashMap params) { @@ -540,11 +538,8 @@ public abstract class Tile extends BaseClass implements Comparable { oneWay = null; } } - if ("on".equals(params.get(DISABLED))) { - status = Status.DISABLED; - } else { - status = isSet(train) ? Status.OCCUPIED : Status.FREE; - } + disabled = "on".equals(params.get(DISABLED)); + String len = params.get(LENGTH); if (isSet(len)) length(Integer.parseInt(len)); super.update(params); diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java b/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java index b0be00b..cdb75d1 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Turnout.java @@ -15,6 +15,7 @@ import de.srsoftware.web4rail.Command; import de.srsoftware.web4rail.Command.Reply; import de.srsoftware.web4rail.Device; import de.srsoftware.web4rail.Protocol; +import de.srsoftware.web4rail.moving.Train; import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Input; import de.srsoftware.web4rail.tags.Radio; @@ -159,7 +160,8 @@ public abstract class Turnout extends Tile implements Device{ } public Reply state(State newState) { - if (is(Status.LOCKED,Status.OCCUPIED) && newState != state) return new Reply(415, t("{} locked by {}!",this,train())); + Train lockingTrain = lockingTrain(); + if (isSet(lockingTrain) && newState != state) return new Reply(415, t("{} locked by {}!",this,lockingTrain)); if (address == 0) { sleep(300); state = newState; diff --git a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java index 811fa5c..2779e33 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.List; -import de.srsoftware.web4rail.moving.Train; import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Input; import de.srsoftware.web4rail.tags.Window; @@ -16,12 +15,7 @@ public abstract class TurnoutL extends Turnout { @Override public Object click(boolean shift) throws IOException { Object o = super.click(shift); - if (!shift) { - Train train = train(); - if (isSet(train)) { - plan.stream(t("{} is locked by {}!",this,train)); - } else state(state == State.STRAIGHT ? State.LEFT : State.STRAIGHT); - } + if (!shift) state(state == State.STRAIGHT ? State.LEFT : State.STRAIGHT); return o; } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java index 6c22028..f639c71 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java @@ -4,7 +4,6 @@ import java.io.IOException; import java.util.HashMap; import java.util.List; -import de.srsoftware.web4rail.moving.Train; import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Input; import de.srsoftware.web4rail.tags.Window; @@ -16,12 +15,7 @@ public abstract class TurnoutR extends Turnout { @Override public Object click(boolean shift) throws IOException { Object o = super.click(shift); - if (!shift) { - Train train = train(); - if (isSet(train)) { - plan.stream(t("{} is locked by {}!",this,train)); - } else state(state == State.STRAIGHT ? State.RIGHT : State.STRAIGHT); - } + if (!shift) state(state == State.STRAIGHT ? State.RIGHT : State.STRAIGHT); return o; }