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