bugfixes
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<groupId>de.srsoftware</groupId>
|
<groupId>de.srsoftware</groupId>
|
||||||
<artifactId>web4rail</artifactId>
|
<artifactId>web4rail</artifactId>
|
||||||
<version>1.4.3</version>
|
<version>1.4.4</version>
|
||||||
<name>Web4Rail</name>
|
<name>Web4Rail</name>
|
||||||
<packaging>jar</packaging>
|
<packaging>jar</packaging>
|
||||||
<description>Java Model Railway Control</description>
|
<description>Java Model Railway Control</description>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
</encoder>
|
</encoder>
|
||||||
<filter class="de.srsoftware.web4rail.ThreadFilter">
|
<filter class="de.srsoftware.web4rail.ThreadFilter">
|
||||||
<level>DEBUG</level>
|
<level>DEBUG</level>
|
||||||
<keywords>Brake, Contact, Feed, Route, Train</keywords>
|
<keywords>Brake, Contact, Feed, Route, Train, e</keywords>
|
||||||
</filter>
|
</filter>
|
||||||
</appender>
|
</appender>
|
||||||
|
|
||||||
|
|||||||
@@ -316,6 +316,11 @@ public abstract class BaseClass implements Constants{
|
|||||||
return button(text,null);
|
return button(text,null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean debug(String tx, Object... fills) {
|
||||||
|
LOG.debug(tx, fills);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public Form form(String id,List<Map.Entry<String, Tag>> elements) {
|
public Form form(String id,List<Map.Entry<String, Tag>> elements) {
|
||||||
Form form = new Form(id);
|
Form form = new Form(id);
|
||||||
|
|
||||||
|
|||||||
@@ -61,12 +61,15 @@ public interface Constants {
|
|||||||
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 GITHUB_URL = "https://github.com/srsoftware-de/Web4Rail";
|
||||||
public static final String ID = "id";
|
public static final String ID = "id";
|
||||||
|
public static final String LOCKED = "locked";
|
||||||
public static final String NAME = "name";
|
public static final String NAME = "name";
|
||||||
public static final String NBSP = " ";
|
public static final String NBSP = " ";
|
||||||
public static final String NOTES = "notes";
|
public static final String NOTES = "notes";
|
||||||
|
public static final String OCCUPIED = "occupied";
|
||||||
public static final String PARENT = "parent";
|
public static final String PARENT = "parent";
|
||||||
public static final String PORT = "port";
|
public static final String PORT = "port";
|
||||||
public static final String RELAY = "relay";
|
public static final String RELAY = "relay";
|
||||||
|
public static final String RESERVED = "reserved";
|
||||||
public static final String ROUTE = "route";
|
public static final String ROUTE = "route";
|
||||||
public static final String STATE = "state";
|
public static final String STATE = "state";
|
||||||
public static final String TURNOUT = "turnout";
|
public static final String TURNOUT = "turnout";
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import java.util.Collection;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
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 ControlUnit controlUnit = new ControlUnit(this); // the control unit, to which the plan is connected
|
||||||
private Contact learningContact;
|
private Contact learningContact;
|
||||||
private Configuration appConfig;
|
private Configuration appConfig;
|
||||||
|
private LinkedList<EventListener> listeners = new LinkedList<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a new plan, starts to send heart beats
|
* creates a new plan, starts to send heart beats
|
||||||
@@ -283,6 +285,10 @@ public class Plan extends BaseClass{
|
|||||||
return t("Added {}",tile.getClass().getSimpleName());
|
return t("Added {}",tile.getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void alter() {
|
||||||
|
while (!listeners.isEmpty()) listeners.removeFirst().fire();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* search all possible routes in the plan
|
* search all possible routes in the plan
|
||||||
* @param params
|
* @param params
|
||||||
@@ -642,6 +648,10 @@ public class Plan extends BaseClass{
|
|||||||
return t(moved ? "Tile(s) moved.":"No tile moved.");
|
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
|
* adds a new tile to the plan on the client side
|
||||||
* @param tile
|
* @param tile
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import java.io.BufferedWriter;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
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.Input;
|
||||||
import de.srsoftware.web4rail.tags.Table;
|
import de.srsoftware.web4rail.tags.Table;
|
||||||
import de.srsoftware.web4rail.tags.Window;
|
import de.srsoftware.web4rail.tags.Window;
|
||||||
import de.srsoftware.web4rail.threads.BrakeProcess;
|
|
||||||
import de.srsoftware.web4rail.threads.RoutePrepper;
|
import de.srsoftware.web4rail.threads.RoutePrepper;
|
||||||
import de.srsoftware.web4rail.tiles.Block;
|
import de.srsoftware.web4rail.tiles.Block;
|
||||||
import de.srsoftware.web4rail.tiles.BlockContact;
|
import de.srsoftware.web4rail.tiles.BlockContact;
|
||||||
@@ -389,7 +387,8 @@ public class Route extends BaseClass {
|
|||||||
|
|
||||||
public void finish(Train train) {
|
public void finish(Train train) {
|
||||||
LOG.debug("{}.finish()",this);
|
LOG.debug("{}.finish()",this);
|
||||||
train.endRoute(endBlock,endDirection);
|
context.invalidate();
|
||||||
|
train.endRoute(this);
|
||||||
setSignals(Signal.RED);
|
setSignals(Signal.RED);
|
||||||
freeIgnoring(null);
|
freeIgnoring(null);
|
||||||
train = null;
|
train = null;
|
||||||
|
|||||||
@@ -38,7 +38,9 @@ public class DelayedAction extends ActionList {
|
|||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
LOG.debug("{} ms passed by, firing actions:",delay);
|
LOG.debug("{} ms passed by, firing actions:",delay);
|
||||||
|
if (context.invalidated()) return;
|
||||||
DelayedAction.super.fire(context,cause);
|
DelayedAction.super.fire(context,cause);
|
||||||
|
plan.alter();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ public class DetermineTrainInBlock extends Action {
|
|||||||
@Override
|
@Override
|
||||||
public boolean fire(Context context,Object cause) {
|
public boolean fire(Context context,Object cause) {
|
||||||
context.block(block);
|
context.block(block);
|
||||||
context.train(block.train());
|
context.train(block.occupyingTrain());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,13 +8,13 @@ import org.json.JSONObject;
|
|||||||
|
|
||||||
import de.srsoftware.tools.Tag;
|
import de.srsoftware.tools.Tag;
|
||||||
import de.srsoftware.web4rail.BaseClass;
|
import de.srsoftware.web4rail.BaseClass;
|
||||||
|
import de.srsoftware.web4rail.EventListener;
|
||||||
import de.srsoftware.web4rail.LoadCallback;
|
import de.srsoftware.web4rail.LoadCallback;
|
||||||
import de.srsoftware.web4rail.tags.Fieldset;
|
import de.srsoftware.web4rail.tags.Fieldset;
|
||||||
import de.srsoftware.web4rail.tags.Input;
|
import de.srsoftware.web4rail.tags.Input;
|
||||||
import de.srsoftware.web4rail.tags.Window;
|
import de.srsoftware.web4rail.tags.Window;
|
||||||
import de.srsoftware.web4rail.threads.DelayedExecution;
|
import de.srsoftware.web4rail.threads.DelayedExecution;
|
||||||
import de.srsoftware.web4rail.tiles.Contact;
|
import de.srsoftware.web4rail.tiles.Contact;
|
||||||
import de.srsoftware.web4rail.tiles.Contact.Listener;
|
|
||||||
import de.srsoftware.web4rail.tiles.Tile;
|
import de.srsoftware.web4rail.tiles.Tile;
|
||||||
|
|
||||||
public class WaitForContact extends ActionList {
|
public class WaitForContact extends ActionList {
|
||||||
@@ -35,9 +35,9 @@ public class WaitForContact extends ActionList {
|
|||||||
LOG.debug("{}.fire(...) called, waiting for {}.",this,contact);
|
LOG.debug("{}.fire(...) called, waiting for {}.",this,contact);
|
||||||
if (isNull(contact)) return false;
|
if (isNull(contact)) return false;
|
||||||
fired = false;
|
fired = false;
|
||||||
Listener listener = new Listener() {
|
EventListener listener = new EventListener() {
|
||||||
@Override
|
@Override
|
||||||
public void fired(Object cause) {
|
public void fire() {
|
||||||
LOG.debug("{} triggered, firing {}",contact,actions);
|
LOG.debug("{} triggered, firing {}",contact,actions);
|
||||||
fired = true;
|
fired = true;
|
||||||
contact.removeListener(this);
|
contact.removeListener(this);
|
||||||
|
|||||||
@@ -226,14 +226,14 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
carList.addHead(t("Car"),t("Actions"));
|
carList.addHead(t("Car"),t("Actions"));
|
||||||
|
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (Car car : this.cars) {
|
for (Car car : cars) {
|
||||||
Tag link = car.link(car.name()+(car.stockId.isEmpty() ? "" : " ("+car.stockId+")"));
|
Tag link = car.link(car.name()+(car.stockId.isEmpty() ? "" : " ("+car.stockId+")"));
|
||||||
Tag buttons = new Tag("span");
|
Tag buttons = new Tag("span");
|
||||||
|
|
||||||
car.button(t("turn within train"),Map.of(ACTION,ACTION_TURN)).addTo(buttons);
|
car.button(t("turn within train"),Map.of(ACTION,ACTION_TURN)).addTo(buttons);
|
||||||
if (!first) {
|
if (!first) {
|
||||||
car.button("↑",Map.of(ACTION,ACTION_MOVE)).addTo(buttons);
|
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);
|
button(t("delete"),Map.of(ACTION,ACTION_DROP,CAR_ID,car.id().toString())).addTo(buttons);
|
||||||
carList.addRow(link,buttons);
|
carList.addRow(link,buttons);
|
||||||
@@ -275,7 +275,8 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
}
|
}
|
||||||
if (isSet(currentBlock)) {
|
if (isSet(currentBlock)) {
|
||||||
Tag ul = new Tag("ul");
|
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()) {
|
for (Train tr : currentBlock.trains()) {
|
||||||
if (tr == this) continue;
|
if (tr == this) continue;
|
||||||
Tag li = new Tag("li").addTo(ul);
|
Tag li = new Tag("li").addTo(ul);
|
||||||
@@ -319,10 +320,13 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
dummy.addAll(cars);
|
dummy.addAll(cars);
|
||||||
cars = dummy;
|
cars = dummy;
|
||||||
} else {
|
} else {
|
||||||
for (Car car : parkingTrain.cars) cars.add(car.train(this));
|
for (Car car : parkingTrain.cars) {
|
||||||
|
cars.add(car.train(this));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parkingTrain.remove();
|
parkingTrain.remove();
|
||||||
|
if (isSet(currentBlock)) currentBlock.setTrain(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Object create(HashMap<String, String> params, Plan plan) {
|
private static Object create(HashMap<String, String> params, Plan plan) {
|
||||||
@@ -350,6 +354,28 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Block destination(){
|
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;
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -360,11 +386,11 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String directedName(Direction dir) {
|
public String directedName() {
|
||||||
String result = name();
|
String result = name();
|
||||||
String mark = autopilot ? "ⓐ" : "";
|
String mark = autopilot ? "ⓐ" : "";
|
||||||
if (isNull(dir)) return result;
|
if (isNull(direction)) return result;
|
||||||
switch (dir) {
|
switch (direction) {
|
||||||
case NORTH:
|
case NORTH:
|
||||||
case WEST:
|
case WEST:
|
||||||
return '←'+mark+result;
|
return '←'+mark+result;
|
||||||
@@ -416,26 +442,68 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void endRoute(Block endBlock, Direction endDirection) {
|
public void endRoute(Route endedRoute) {
|
||||||
BrakeProcess brake = endBrake();
|
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) {
|
if (endBlock == destination) {
|
||||||
quitAutopilot();
|
|
||||||
destination = null;
|
destination = null;
|
||||||
|
|
||||||
|
String destTag = destinationTag();
|
||||||
|
if (isSet(destTag)) {
|
||||||
|
LOG.debug("destination list: {}",destTag);
|
||||||
|
String[] parts = destTag.split(Train.DESTINATION_PREFIX);
|
||||||
|
for (int i=0; i<parts.length;i++) LOG.debug(" part {}: {}",i+1,parts[i]);
|
||||||
|
String destId = parts[1];
|
||||||
|
LOG.debug("destination tag: {}",destId);
|
||||||
|
boolean turn = false;
|
||||||
|
|
||||||
|
for (int i=destId.length()-1; i>0; 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();
|
if (isSet(brake)) brake.updateTime();
|
||||||
Integer waitTime = route.waitTime();
|
Integer waitTime = route.waitTime();
|
||||||
nextPreparedRoute = route.dropNextPreparedRoute();
|
nextPreparedRoute = route.dropNextPreparedRoute();
|
||||||
if ((!autopilot)|| isNull(nextPreparedRoute) || (isSet(waitTime) && waitTime > 0)) setSpeed(0);
|
if ((!autopilot)|| isNull(nextPreparedRoute) || (isSet(waitTime) && waitTime > 0)) setSpeed(0);
|
||||||
route = null;
|
route = null;
|
||||||
direction = endDirection;
|
endBlock.setTrain(this);
|
||||||
endBlock.add(this, direction);
|
|
||||||
currentBlock = endBlock;
|
currentBlock = endBlock;
|
||||||
trace.add(endBlock);
|
trace.add(endBlock);
|
||||||
|
if (!trace.contains(startBlock)) startBlock.dropTrain(this);
|
||||||
stuckTrace = null;
|
stuckTrace = null;
|
||||||
if (autopilot) {
|
if (autopilot) {
|
||||||
if (isNull(waitTime) || waitTime == 0) {
|
if (isNull(waitTime)) waitTime = 0;
|
||||||
start(false);
|
if (waitTime>0) plan.stream(t("{} waiting {} secs",this,(int)(waitTime/1000)));
|
||||||
} else if (isSet(waitTime) && waitTime > 0) {
|
|
||||||
new DelayedExecution(waitTime,this) {
|
new DelayedExecution(waitTime,this) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -443,8 +511,6 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
if (autopilot) Train.this.start(false);
|
if (autopilot) Train.this.start(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
plan.stream(t("{} waiting {} secs",this,(int)(waitTime/1000)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -566,16 +632,14 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
public void afterLoad() {
|
public void afterLoad() {
|
||||||
if (json.has(TRACE)) json.getJSONArray(TRACE).forEach(elem -> {
|
if (json.has(TRACE)) json.getJSONArray(TRACE).forEach(elem -> {
|
||||||
Tile tile = plan.get(new Id(elem.toString()), false);
|
Tile tile = plan.get(new Id(elem.toString()), false);
|
||||||
if (tile instanceof Block) {
|
tile.setTrain(Train.this);
|
||||||
((Block)tile).add(Train.this, direction);
|
|
||||||
} else if (tile.setTrain(Train.this));
|
|
||||||
trace.add(tile);
|
trace.add(tile);
|
||||||
});
|
});
|
||||||
if (json.has(BLOCK)) {// do not move this up! during set, other fields will be referenced!
|
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);
|
currentBlock = (Block) plan.get(Id.from(json, BLOCK), false);
|
||||||
if (isSet(currentBlock)) {
|
if (isSet(currentBlock)) {
|
||||||
currentBlock.setTrain(Train.this);
|
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<Train> {
|
|||||||
LOG.debug("train.reverse();");
|
LOG.debug("train.reverse();");
|
||||||
|
|
||||||
if (isSet(direction)) direction = direction.inverse();
|
if (isSet(direction)) direction = direction.inverse();
|
||||||
if (isSet(currentBlock)) {
|
if (isSet(currentBlock)) plan.place(currentBlock);
|
||||||
currentBlock.set(this,direction);
|
|
||||||
plan.place(currentBlock);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -805,10 +866,10 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
return select;
|
return select;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(Block newBlock) {
|
public Train set(Block newBlock) {
|
||||||
LOG.debug("{}.set({})",this,newBlock);
|
LOG.debug("{}.set({})",this,newBlock);
|
||||||
if (isSet(currentBlock)) {
|
if (isSet(currentBlock)) {
|
||||||
if (newBlock == currentBlock) return;
|
if (newBlock == currentBlock) return this;
|
||||||
currentBlock.free(this);
|
currentBlock.free(this);
|
||||||
}
|
}
|
||||||
currentBlock = newBlock;
|
currentBlock = newBlock;
|
||||||
@@ -817,6 +878,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
lastBlocks.add(newBlock);
|
lastBlocks.add(newBlock);
|
||||||
if (lastBlocks.size()>32) lastBlocks.remove(0);
|
if (lastBlocks.size()>32) lastBlocks.remove(0);
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Object setDestination(HashMap<String, String> params) {
|
private Object setDestination(HashMap<String, String> params) {
|
||||||
@@ -899,7 +961,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
if (remaining.cars.isEmpty()) return false;
|
if (remaining.cars.isEmpty()) return false;
|
||||||
remaining.direction = this.direction;
|
remaining.direction = this.direction;
|
||||||
this.name = null;
|
this.name = null;
|
||||||
currentBlock.add(remaining,direction);
|
currentBlock.addParkedTrain(remaining);
|
||||||
remaining.currentBlock = currentBlock;
|
remaining.currentBlock = currentBlock;
|
||||||
plan.place(currentBlock);
|
plan.place(currentBlock);
|
||||||
return true;
|
return true;
|
||||||
@@ -926,15 +988,9 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
routePrepper = null;
|
routePrepper = null;
|
||||||
if (isSet(failedRoute)) failedRoute.reset();
|
if (isSet(failedRoute)) failedRoute.reset();
|
||||||
LOG.debug("Starting {} failed due to unavailable route!",this);
|
LOG.debug("Starting {} failed due to unavailable route!",this);
|
||||||
if (autopilot) new DelayedExecution(250,this) {
|
plan.onChange(()->{ // wait for state change of plan
|
||||||
|
if (autopilot) Train.this.start(false);
|
||||||
@Override
|
});
|
||||||
public void execute() {
|
|
||||||
if (autopilot) {
|
|
||||||
Train.this.start(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
|
|
||||||
routePrepper.start();
|
routePrepper.start();
|
||||||
@@ -1017,7 +1073,10 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
LOG.debug("update({})",params);
|
LOG.debug("update({})",params);
|
||||||
pushPull = params.containsKey(PUSH_PULL) && params.get(PUSH_PULL).equals("on");
|
pushPull = params.containsKey(PUSH_PULL) && params.get(PUSH_PULL).equals("on");
|
||||||
shunting = params.containsKey(SHUNTING) && params.get(SHUNTING).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)) {
|
if (params.containsKey(TAGS)) {
|
||||||
String[] parts = params.get(TAGS).replace(",", " ").split(" ");
|
String[] parts = params.get(TAGS).replace(",", " ").split(" ");
|
||||||
tags.clear();
|
tags.clear();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package de.srsoftware.web4rail.tiles;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -43,16 +44,14 @@ public abstract class Block extends StretchableTile{
|
|||||||
private class TrainList implements Iterable<Train>{
|
private class TrainList implements Iterable<Train>{
|
||||||
|
|
||||||
private LinkedList<Train> trains = new LinkedList<Train>();
|
private LinkedList<Train> trains = new LinkedList<Train>();
|
||||||
private HashMap<Train, Direction> dirs = new HashMap<Train, Direction>();
|
|
||||||
|
|
||||||
public void add(Train train, Direction direction) {
|
public void add(Train train) {
|
||||||
trains.remove(train);
|
trains.remove(train);
|
||||||
trains.addFirst(train);
|
trains.addFirst(train);
|
||||||
if (isSet(direction)) dirs.put(train, direction);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Direction directionOf(Train train) {
|
public boolean contains(Train t) {
|
||||||
return dirs.get(train);
|
return trains.contains(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Train first() {
|
public Train first() {
|
||||||
@@ -77,18 +76,12 @@ public abstract class Block extends StretchableTile{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(BaseClass b) {
|
public boolean remove(BaseClass b) {
|
||||||
dirs.remove(b);
|
|
||||||
return trains.remove(b);
|
return trains.remove(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void set(Train train, Direction newDirection) {
|
|
||||||
dirs.put(train, newDirection);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
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";
|
private static final String ALLOW_TURN = "allowTurn";
|
||||||
@@ -100,12 +93,11 @@ public abstract class Block extends StretchableTile{
|
|||||||
private static final String RAISE = "raise";
|
private static final String RAISE = "raise";
|
||||||
public static final String ACTION_ADD_CONTACT = "add_contact";
|
public static final String ACTION_ADD_CONTACT = "add_contact";
|
||||||
private static final String PARKED_TRAINS = "parked_trains";
|
private static final String PARKED_TRAINS = "parked_trains";
|
||||||
private static final String TRAINS = "trains";
|
|
||||||
|
|
||||||
public String name = "Block";
|
public String name = "Block";
|
||||||
public boolean turnAllowed = false;
|
public boolean turnAllowed = false;
|
||||||
private Vector<BlockContact> internalContacts = new Vector<BlockContact>();
|
private Vector<BlockContact> internalContacts = new Vector<BlockContact>();
|
||||||
private TrainList trains = new TrainList();
|
private TrainList parkedTrains = new TrainList();
|
||||||
|
|
||||||
public Block() {
|
public Block() {
|
||||||
super();
|
super();
|
||||||
@@ -191,10 +183,11 @@ public abstract class Block extends StretchableTile{
|
|||||||
|
|
||||||
private Vector<WaitTime> waitTimes = new Vector<WaitTime>();
|
private Vector<WaitTime> waitTimes = new Vector<WaitTime>();
|
||||||
|
|
||||||
public void add(Train train,Direction direction) {
|
public void addParkedTrain(Train train) {
|
||||||
|
if (parkedTrains.contains(train)) return;
|
||||||
if (isNull(train)) return;
|
if (isNull(train)) return;
|
||||||
train.register();
|
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");
|
return t("Trigger contact to learn new contact");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected HashSet<String> classes() {
|
||||||
|
HashSet<String> classes = super.classes();
|
||||||
|
if (!parkedTrains.isEmpty()) classes.add(OCCUPIED);
|
||||||
|
return classes;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object click(boolean shift) throws IOException {
|
public Object click(boolean shift) throws IOException {
|
||||||
if (!trains.isEmpty() && !shift) return trains.first().properties();
|
Train train = occupyingTrain();
|
||||||
return super.click(false);
|
return !shift && isSet(train) ? train.properties() : properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(Block other) {
|
public int compareTo(Block other) {
|
||||||
@@ -255,25 +255,15 @@ public abstract class Block extends StretchableTile{
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void dropFirstTrain() {
|
public void dropTrain(Train t) {
|
||||||
Train train = trains.first();
|
parkedTrains.remove(t);
|
||||||
if (isSet(train)) {
|
plan.place(this);
|
||||||
train.dropTrace();
|
|
||||||
train.set(null);
|
|
||||||
trains.remove(train);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean free(Train train) {
|
public boolean free(Train oldTrain) {
|
||||||
LOG.debug("{}.free({})",this,train);
|
parkedTrains.remove(oldTrain);
|
||||||
Train firstTrain = trains.first();
|
if (!super.free(oldTrain)) return false;
|
||||||
if (isNull(firstTrain)) return true;
|
|
||||||
if (firstTrain != train) return false;
|
|
||||||
trains.remove(train);
|
|
||||||
if (isSet(firstTrain)) {
|
|
||||||
super.free(train);
|
|
||||||
} else super.setTrain(firstTrain);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,11 +294,10 @@ public abstract class Block extends StretchableTile{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isFreeFor(Context context) {
|
public boolean isFreeFor(Context context) {
|
||||||
|
if (!super.isFreeFor(context)) return false;
|
||||||
Train train = context.train();
|
Train train = context.train();
|
||||||
if (is(Status.DISABLED)) return false;
|
if (isSet(occupyingTrain()) && occupyingTrain() == train) return true;
|
||||||
if (trains.isEmpty()) return true;
|
return parkedTrains.isEmpty() || parkedTrains.contains(train) || train.isShunting();
|
||||||
if (trains.first() == train) return true;
|
|
||||||
return train.isShunting(); // block contains train(s), thus it is only free for shunting train
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -317,7 +306,7 @@ public abstract class Block extends StretchableTile{
|
|||||||
json.put(NAME, name);
|
json.put(NAME, name);
|
||||||
json.put(ALLOW_TURN, turnAllowed);
|
json.put(ALLOW_TURN, turnAllowed);
|
||||||
JSONArray jWaitTimes = new JSONArray();
|
JSONArray jWaitTimes = new JSONArray();
|
||||||
for (WaitTime wt : waitTimes) jWaitTimes.put(wt.json());
|
waitTimes.forEach(wt -> jWaitTimes.put(wt.json()));
|
||||||
json.put(WAIT_TIMES, jWaitTimes);
|
json.put(WAIT_TIMES, jWaitTimes);
|
||||||
JSONObject jContacts = null;
|
JSONObject jContacts = null;
|
||||||
for (BlockContact contact : internalContacts) {
|
for (BlockContact contact : internalContacts) {
|
||||||
@@ -328,22 +317,22 @@ public abstract class Block extends StretchableTile{
|
|||||||
}
|
}
|
||||||
if (isSet(jContacts)) json.put(CONTACT, jContacts);
|
if (isSet(jContacts)) json.put(CONTACT, jContacts);
|
||||||
json.remove(REALM_TRAIN); // is set by TRAINS field for blocks
|
json.remove(REALM_TRAIN); // is set by TRAINS field for blocks
|
||||||
if (!trains.isEmpty()) {
|
if (!parkedTrains.isEmpty()) {
|
||||||
JSONArray jTrains = new JSONArray();
|
JSONArray jTrains = new JSONArray();
|
||||||
for (Train train : trains) {
|
for (Train train : parkedTrains) {
|
||||||
JSONObject to = new JSONObject();
|
JSONObject to = new JSONObject();
|
||||||
to.put(ID, train.id());
|
to.put(ID, train.id());
|
||||||
Direction dir = trains.directionOf(train);
|
// Direction dir = parkedTrains.directionOf(train);
|
||||||
if (isSet(dir)) to.put(DIRECTION, dir.toString());
|
// if (isSet(dir)) to.put(DIRECTION, dir.toString());
|
||||||
jTrains.put(to);
|
jTrains.put(to);
|
||||||
}
|
}
|
||||||
json.put(TRAINS, jTrains);
|
json.put(PARKED_TRAINS, jTrains);
|
||||||
}
|
}
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Train lastTrain() {
|
public Train lastTrain() {
|
||||||
return trains.last();
|
return parkedTrains.last();
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Route> leavingRoutes() {
|
public List<Route> leavingRoutes() {
|
||||||
@@ -387,27 +376,16 @@ public abstract class Block extends StretchableTile{
|
|||||||
new LoadCallback() {
|
new LoadCallback() {
|
||||||
@Override
|
@Override
|
||||||
public void afterLoad() {
|
public void afterLoad() {
|
||||||
if (json.has(TRAINS)) {
|
if (json.has(PARKED_TRAINS)) {
|
||||||
JSONArray jTrains = json.getJSONArray(TRAINS);
|
JSONArray jParkedTrains = json.getJSONArray(PARKED_TRAINS);
|
||||||
for (Object o : jTrains) {
|
for (Object o : jParkedTrains) {
|
||||||
if (o instanceof JSONObject) {
|
if (o instanceof JSONObject) {
|
||||||
JSONObject to = (JSONObject) o;
|
JSONObject trainData = (JSONObject) o;
|
||||||
Id tID = new Id(to.getString(ID));
|
Train train = BaseClass.get(Id.from(trainData));
|
||||||
Train train = BaseClass.get(tID);
|
if (isSet(train)) parkedTrains.add(train.set(Block.this));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} 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
|
@Override
|
||||||
public boolean lockFor(Context context, boolean downgrade) {
|
public boolean lockFor(Context context, boolean downgrade) {
|
||||||
Train newTrain = context.train();
|
Train newTrain = context.train();
|
||||||
Route route = context.route();
|
LOG.debug("{}.lockFor({})",this,newTrain);
|
||||||
LOG.debug("{}.lock({})",this,newTrain);
|
Train train = lockingTrain();
|
||||||
if (isNull(newTrain)) return false;
|
if (newTrain == train || parkedTrains.isEmpty() || parkedTrains.contains(newTrain) || newTrain.isShunting()) return super.lockFor(context, downgrade);
|
||||||
Train train = trains.first();
|
|
||||||
if (isSet(train) && train != newTrain) return false;
|
|
||||||
switch (status) {
|
|
||||||
case DISABLED:
|
|
||||||
return false;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm,String...errors) {
|
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm,String...errors) {
|
||||||
formInputs.add(t("Name"),new Input(NAME, name));
|
formInputs.add(t("Name"),new Input(NAME, name));
|
||||||
formInputs.add("",new Checkbox(ALLOW_TURN,t("Turn allowed"),turnAllowed));
|
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(contactForm());
|
||||||
postForm.add(waitTimeForm());
|
postForm.add(waitTimeForm());
|
||||||
if (!trains.isEmpty()) postForm.add(trainList());
|
if (!parkedTrains.isEmpty()) postForm.add(trainList());
|
||||||
return super.properties(preForm, formInputs, postForm,errors);
|
return super.properties(preForm, formInputs, postForm,errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,27 +427,10 @@ public abstract class Block extends StretchableTile{
|
|||||||
@Override
|
@Override
|
||||||
public boolean reserveFor(Context context) {
|
public boolean reserveFor(Context context) {
|
||||||
Train newTrain = context.train();
|
Train newTrain = context.train();
|
||||||
Route route = context.route();
|
LOG.debug("{}.lockFor({})",this,newTrain);
|
||||||
LOG.debug("{}.reserverFor({})",this,newTrain);
|
Train train = lockingTrain();
|
||||||
if (isNull(newTrain)) return false;
|
if (newTrain == train || parkedTrains.isEmpty() || parkedTrains.contains(newTrain) || newTrain.isShunting()) return super.reserveFor(context);
|
||||||
Train train = trains.first();
|
|
||||||
if (isSet(train) && train != newTrain) return false;
|
|
||||||
switch (status) {
|
|
||||||
case DISABLED:
|
|
||||||
return false;
|
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BlockContact register(BlockContact contact) {
|
public BlockContact register(BlockContact contact) {
|
||||||
@@ -499,18 +442,13 @@ public abstract class Block extends StretchableTile{
|
|||||||
public void removeChild(BaseClass child) {
|
public void removeChild(BaseClass child) {
|
||||||
super.removeChild(child);
|
super.removeChild(child);
|
||||||
internalContacts.remove(child);
|
internalContacts.remove(child);
|
||||||
if (trains.remove(child)) plan.place(this);
|
if (parkedTrains.remove(child)) plan.place(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeContact(BlockContact blockContact) {
|
public void removeContact(BlockContact blockContact) {
|
||||||
internalContacts.remove(blockContact);
|
internalContacts.remove(blockContact);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void set(Train train, Direction direction) {
|
|
||||||
trains.set(train,direction);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public abstract List<Connector> startPoints();
|
public abstract List<Connector> startPoints();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -518,7 +456,9 @@ public abstract class Block extends StretchableTile{
|
|||||||
if (isNull(replacements)) replacements = new HashMap<String, Object>();
|
if (isNull(replacements)) replacements = new HashMap<String, Object>();
|
||||||
replacements.put("%text%",name);
|
replacements.put("%text%",name);
|
||||||
Vector<String> trainNames = new Vector<String>();
|
Vector<String> trainNames = new Vector<String>();
|
||||||
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));
|
if (!trainNames.isEmpty())replacements.put("%text%",String.join(" | ", trainNames));
|
||||||
Tag tag = super.tag(replacements);
|
Tag tag = super.tag(replacements);
|
||||||
tag.clazz(tag.get("class")+" Block");
|
tag.clazz(tag.get("class")+" Block");
|
||||||
@@ -535,20 +475,10 @@ public abstract class Block extends StretchableTile{
|
|||||||
return name + " @ ("+x+","+y+")";
|
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() {
|
private Fieldset trainList() {
|
||||||
Fieldset fieldset = new Fieldset(t("Trains"));
|
Fieldset fieldset = new Fieldset(t("Trains"));
|
||||||
Tag list = new Tag("ul");
|
Tag list = new Tag("ul");
|
||||||
for (Train t : trains) {
|
for (Train t : parkedTrains) {
|
||||||
if (isSet(t)) t.link("li", t).addTo(list);
|
if (isSet(t)) t.link("li", t).addTo(list);
|
||||||
}
|
}
|
||||||
list.addTo(fieldset);
|
list.addTo(fieldset);
|
||||||
@@ -556,7 +486,7 @@ public abstract class Block extends StretchableTile{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public List<Train> trains(){
|
public List<Train> trains(){
|
||||||
return trains.list();
|
return parkedTrains.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -565,15 +495,14 @@ public abstract class Block extends StretchableTile{
|
|||||||
if (params.containsKey(Train.class.getSimpleName())) {
|
if (params.containsKey(Train.class.getSimpleName())) {
|
||||||
Id trainId = Id.from(params,Train.class.getSimpleName());
|
Id trainId = Id.from(params,Train.class.getSimpleName());
|
||||||
if (trainId.equals(0)) { // remove first train
|
if (trainId.equals(0)) { // remove first train
|
||||||
dropFirstTrain();
|
free(occupyingTrain());
|
||||||
} else {
|
} else {
|
||||||
Train train = Train.get(trainId);
|
Train newTrain = Train.get(trainId);
|
||||||
if (isSet(train) && train != trains.first()) {
|
if (isSet(newTrain) && newTrain != occupyingTrain()) {
|
||||||
dropFirstTrain();
|
free(occupyingTrain());
|
||||||
train.dropTrace();
|
newTrain.dropTrace();
|
||||||
if (connections(train.direction()).isEmpty()) train.heading(null);
|
if (connections(newTrain.direction()).isEmpty()) newTrain.heading(null);
|
||||||
train.set(this);
|
newTrain.set(this);
|
||||||
trains.add(train,train.direction());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import java.io.IOException;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import de.srsoftware.tools.Tag;
|
import de.srsoftware.tools.Tag;
|
||||||
import de.srsoftware.web4rail.Route;
|
|
||||||
import de.srsoftware.web4rail.moving.Train;
|
import de.srsoftware.web4rail.moving.Train;
|
||||||
|
|
||||||
public class BlockContact extends Contact {
|
public class BlockContact extends Contact {
|
||||||
@@ -29,13 +28,23 @@ public class BlockContact extends Contact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Tag tag(Map<String, Object> replacements) throws IOException {
|
public Train lockingTrain() {
|
||||||
return ((Block)parent()).tag(replacements);
|
return parent().lockingTrain();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Train train() {
|
public Tag tag(Map<String, Object> replacements) throws IOException {
|
||||||
return ((Block)parent()).train();
|
return parent().tag(replacements);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Train occupyingTrain() {
|
||||||
|
return parent().occupyingTrain();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Block parent() {
|
||||||
|
return (Block) super.parent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ public abstract class Bridge extends Tile {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setTrain(Train newTrain) {
|
public boolean setTrain(Train newTrain) {
|
||||||
if (train() == newTrain) return true;
|
if (occupyingTrain() == newTrain) return true;
|
||||||
if (!super.setTrain(newTrain)) return false;
|
if (!super.setTrain(newTrain)) return false;
|
||||||
return isNull(counterpart) ? true : counterpart.setTrain(newTrain);
|
return isNull(counterpart) ? true : counterpart.setTrain(newTrain);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import de.srsoftware.tools.Tag;
|
import de.srsoftware.tools.Tag;
|
||||||
import de.srsoftware.web4rail.Application;
|
import de.srsoftware.web4rail.Application;
|
||||||
import de.srsoftware.web4rail.BaseClass;
|
import de.srsoftware.web4rail.BaseClass;
|
||||||
|
import de.srsoftware.web4rail.EventListener;
|
||||||
import de.srsoftware.web4rail.actions.Action;
|
import de.srsoftware.web4rail.actions.Action;
|
||||||
import de.srsoftware.web4rail.actions.ActionList;
|
import de.srsoftware.web4rail.actions.ActionList;
|
||||||
import de.srsoftware.web4rail.moving.Train;
|
import de.srsoftware.web4rail.moving.Train;
|
||||||
@@ -34,11 +35,7 @@ public class Contact extends Tile{
|
|||||||
protected int addr = 0;
|
protected int addr = 0;
|
||||||
private ActionList actions;
|
private ActionList actions;
|
||||||
private OffTimer timer = null;
|
private OffTimer timer = null;
|
||||||
private HashSet<Listener> listeners = new HashSet<Listener>();
|
private HashSet<EventListener> listeners = new HashSet<EventListener>();
|
||||||
|
|
||||||
public interface Listener{
|
|
||||||
public void fired(Object cause);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Contact() {
|
public Contact() {
|
||||||
actions = new ActionList(this);
|
actions = new ActionList(this);
|
||||||
@@ -82,15 +79,16 @@ public class Contact extends Tile{
|
|||||||
if (isSet(timer)) return;
|
if (isSet(timer)) return;
|
||||||
timer = new OffTimer();
|
timer = new OffTimer();
|
||||||
} else {
|
} else {
|
||||||
LOG.debug("{} activated.",this);
|
|
||||||
state = true;
|
state = true;
|
||||||
stream();
|
stream();
|
||||||
if (isSet(timer)) timer.abort();
|
if (isSet(timer)) timer.abort();
|
||||||
Train train = train();
|
Train train = lockingTrain();
|
||||||
Context context = isSet(train) ? train.contact(this) : new Context(this);
|
Context context = isSet(train) ? train.contact(this) : new Context(this);
|
||||||
actions.fire(context,"Contact("+addr+")");
|
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;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addListener(Listener l) {
|
public void addListener(EventListener l) {
|
||||||
listeners.add(l);
|
listeners.add(l);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,7 +203,7 @@ public class Contact extends Tile{
|
|||||||
super.removeChild(child);
|
super.removeChild(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void removeListener(Listener listener) {
|
public void removeListener(EventListener listener) {
|
||||||
listeners.remove(listener);
|
listeners.remove(listener);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import de.srsoftware.tools.Tag;
|
import de.srsoftware.tools.Tag;
|
||||||
import de.srsoftware.web4rail.BaseClass;
|
import de.srsoftware.web4rail.BaseClass;
|
||||||
import de.srsoftware.web4rail.Connector;
|
import de.srsoftware.web4rail.Connector;
|
||||||
|
import de.srsoftware.web4rail.LoadCallback;
|
||||||
import de.srsoftware.web4rail.Plan;
|
import de.srsoftware.web4rail.Plan;
|
||||||
import de.srsoftware.web4rail.Plan.Direction;
|
import de.srsoftware.web4rail.Plan.Direction;
|
||||||
import de.srsoftware.web4rail.Route;
|
import de.srsoftware.web4rail.Route;
|
||||||
@@ -39,20 +40,6 @@ import de.srsoftware.web4rail.tags.Window;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
||||||
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);
|
protected static Logger LOG = LoggerFactory.getLogger(Tile.class);
|
||||||
private static int DEFAUT_LENGTH = 100; // 10cm
|
private static int DEFAUT_LENGTH = 100; // 10cm
|
||||||
@@ -65,11 +52,11 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
private static final String Y = "y";
|
private static final String Y = "y";
|
||||||
|
|
||||||
private boolean isTrack = true;
|
private boolean isTrack = true;
|
||||||
|
private boolean disabled;
|
||||||
private int length = DEFAUT_LENGTH;
|
private int length = DEFAUT_LENGTH;
|
||||||
protected Direction oneWay = null;
|
protected Direction oneWay = null;
|
||||||
private TreeSet<Route> routes = new TreeSet<>((r1, r2) -> r1.toString().compareTo(r2.toString()));
|
private TreeSet<Route> routes = new TreeSet<>((r1, r2) -> r1.toString().compareTo(r2.toString()));
|
||||||
private Train train = null;
|
private Train reservingTrain,lockingTrain,occupyingTrain;
|
||||||
protected Status status = Status.FREE;
|
|
||||||
public Integer x = null;
|
public Integer x = null;
|
||||||
public Integer y = null;
|
public Integer y = null;
|
||||||
|
|
||||||
@@ -81,13 +68,19 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
HashSet<String> classes = new HashSet<String>();
|
HashSet<String> classes = new HashSet<String>();
|
||||||
classes.add("tile");
|
classes.add("tile");
|
||||||
classes.add(getClass().getSimpleName());
|
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;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object click(boolean shift) throws IOException {
|
public Object click(boolean shift) throws IOException {
|
||||||
LOG.debug("{}.click()", getClass().getSimpleName());
|
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();
|
return properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,10 +98,12 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
return new HashMap<>();
|
return new HashMap<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean free(Train t) {
|
public boolean free(Train oldTrain) {
|
||||||
if (isSet(train) && t != train) return false;
|
if (isNull(oldTrain)) return false;
|
||||||
train = null;
|
if (isSet(reservingTrain) && reservingTrain != oldTrain) return false;
|
||||||
status = Status.FREE;
|
if (isSet(lockingTrain) && lockingTrain != oldTrain) return false;
|
||||||
|
if (isSet(occupyingTrain) && occupyingTrain != oldTrain) return false;
|
||||||
|
reservingTrain = lockingTrain = occupyingTrain = null;
|
||||||
plan.place(this);
|
plan.place(this);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -134,39 +129,35 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
plan.place(tile);
|
plan.place(tile);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean is(Status... states) {
|
public boolean isDisabled() {
|
||||||
for (Status s : states) {
|
return disabled;
|
||||||
if (status == s) return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isFreeFor(Context newTrain) {
|
public boolean isFreeFor(Context newTrain) {
|
||||||
LOG.debug("{}.isFreeFor({})", this, newTrain);
|
LOG.debug("{}.isFreeFor({})", this, newTrain);
|
||||||
if (is(Status.DISABLED)) {
|
if (isDisabled()) {
|
||||||
LOG.debug("{} is disabled!", this);
|
LOG.debug("{} is disabled!", this);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNull(train)) {
|
Train train = newTrain.train();
|
||||||
LOG.debug("→ free");
|
|
||||||
return true;
|
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
|
if (isSet(lockingTrain) && lockingTrain != train) {
|
||||||
// by the respective train, but having another route. do not compare routes
|
LOG.debug("{} is locked for {}",lockingTrain);
|
||||||
// in that case!
|
return false; // nicht in reservierten Block einfahren!
|
||||||
LOG.debug("already reserved by {} → true", train);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSet(newTrain.train()) && newTrain.train().isShunting()) {
|
if (isSet(occupyingTrain) && occupyingTrain != train) {
|
||||||
LOG.debug("occupied by {}. Allowed for shunting {}", train, newTrain.train());
|
LOG.debug("{} is occupied by {}",occupyingTrain);
|
||||||
return true;
|
return train.isShunting(); // nur in belegte Blöcke einfahren, wenn Rangiermodus aktiv!
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug("occupied by {} → false", train);
|
return true;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public JSONObject json() {
|
public JSONObject json() {
|
||||||
@@ -174,8 +165,8 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
json.put(TYPE, getClass().getSimpleName());
|
json.put(TYPE, getClass().getSimpleName());
|
||||||
if (isSet(x) && isSet(y)) json.put(POS, new JSONObject(Map.of(X, x, Y, y)));
|
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 (isSet(oneWay)) json.put(ONEW_WAY, oneWay);
|
||||||
if (is(Status.DISABLED)) json.put(DISABLED, true);
|
if (disabled) json.put(DISABLED, true);
|
||||||
if (isSet(train)) json.put(REALM_TRAIN, train.id());
|
if (isSet(occupyingTrain)) json.put(REALM_TRAIN, occupyingTrain.id());
|
||||||
json.put(LENGTH, length);
|
json.put(LENGTH, length);
|
||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
@@ -221,19 +212,53 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Tile load(JSONObject json) {
|
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);
|
super.load(json);
|
||||||
if (json.has(POS)) {
|
if (json.has(POS)) {
|
||||||
JSONObject pos = json.getJSONObject(POS);
|
JSONObject pos = json.getJSONObject(POS);
|
||||||
x = pos.getInt(X);
|
x = pos.getInt(X);
|
||||||
y = pos.getInt(Y);
|
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(LENGTH)) length = json.getInt(LENGTH);
|
||||||
if (json.has(ONEW_WAY)) oneWay = Direction.valueOf(json.getString(ONEW_WAY));
|
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;
|
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) {
|
public boolean move(int dx, int dy) {
|
||||||
int destX = x + (dx > 0 ? width() : dx);
|
int destX = x + (dx > 0 ? width() : dx);
|
||||||
int destY = y + (dy > 0 ? height() : dy);
|
int destY = y + (dy > 0 ? height() : dy);
|
||||||
@@ -251,6 +276,10 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
isTrack = false;
|
isTrack = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Train occupyingTrain() {
|
||||||
|
return occupyingTrain;
|
||||||
|
}
|
||||||
|
|
||||||
public Tile position(int x, int y) {
|
public Tile position(int x, int y) {
|
||||||
this.x = x;
|
this.x = x;
|
||||||
this.y = y;
|
this.y = y;
|
||||||
@@ -266,18 +295,18 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
String... errors) {
|
String... errors) {
|
||||||
Fieldset fieldset = null;
|
Fieldset fieldset = null;
|
||||||
|
|
||||||
if (isSet(train)) {
|
if (isSet(occupyingTrain)) {
|
||||||
fieldset = new Fieldset(t("Train"));
|
fieldset = new Fieldset(t("Train"));
|
||||||
train.link("span", t("Train") + ":" + NBSP + train + NBSP).addTo(fieldset);
|
occupyingTrain.link("span", t("Train") + ":" + NBSP + occupyingTrain + NBSP).addTo(fieldset);
|
||||||
if (isSet(train.route())) {
|
if (isSet(occupyingTrain.route())) {
|
||||||
train.button(t("stop"), Map.of(ACTION, ACTION_STOP)).addTo(fieldset);
|
occupyingTrain.button(t("stop"), Map.of(ACTION, ACTION_STOP)).addTo(fieldset);
|
||||||
} else {
|
} 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()) {
|
if (occupyingTrain.usesAutopilot()) {
|
||||||
train.button(t("quit autopilot"), Map.of(ACTION, ACTION_QUIT)).addTo(fieldset);
|
occupyingTrain.button(t("quit autopilot"), Map.of(ACTION, ACTION_QUIT)).addTo(fieldset);
|
||||||
} else {
|
} 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<Tile> {
|
|||||||
if (isTrack) {
|
if (isTrack) {
|
||||||
formInputs.add(t("Length"),
|
formInputs.add(t("Length"),
|
||||||
new Input(LENGTH, length).numeric().addTo(new Tag("span")).content(NBSP + lengthUnit));
|
new Input(LENGTH, length).numeric().addTo(new Tag("span")).content(NBSP + lengthUnit));
|
||||||
Checkbox checkbox = new Checkbox(DISABLED, t("disabled"), is(Status.DISABLED));
|
Checkbox checkbox = new Checkbox(DISABLED, t("disabled"), disabled);
|
||||||
if (is(Status.DISABLED)) checkbox.clazz("disabled");
|
if (disabled) checkbox.clazz("disabled");
|
||||||
formInputs.add(t("State"), checkbox);
|
formInputs.add(t("State"), checkbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -373,21 +402,15 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean setTrain(Train newTrain) {
|
public boolean setTrain(Train newTrain) {
|
||||||
|
if (disabled) return false;
|
||||||
if (isNull(newTrain)) return false;
|
if (isNull(newTrain)) return false;
|
||||||
if (isSet(train) && newTrain != train) return false;
|
if (isSet(reservingTrain) && newTrain != reservingTrain) return false;
|
||||||
switch (status) { // bisheriger Status
|
if (isSet(lockingTrain) && newTrain != lockingTrain) return false;
|
||||||
case DISABLED:
|
if (isSet(occupyingTrain) && newTrain != occupyingTrain) return false;
|
||||||
return false;
|
if (occupyingTrain == newTrain) return true;
|
||||||
case FREE:
|
occupyingTrain = newTrain;
|
||||||
case RESERVED:
|
reservingTrain = lockingTrain = null;
|
||||||
case LOCKED:
|
|
||||||
train = newTrain;
|
|
||||||
status = Status.OCCUPIED;
|
|
||||||
plan.place(this);
|
plan.place(this);
|
||||||
break;
|
|
||||||
case OCCUPIED:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -456,10 +479,6 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
return t("{}({},{})", getClass().getSimpleName(), x, y);
|
return t("{}({},{})", getClass().getSimpleName(), x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Train train() {
|
|
||||||
return train;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BaseClass remove() {
|
public BaseClass remove() {
|
||||||
while (!routes.isEmpty()) routes.first().remove();
|
while (!routes.isEmpty()) routes.first().remove();
|
||||||
@@ -473,61 +492,40 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
LOG.debug("Removing {} from {}", childAsString, this);
|
LOG.debug("Removing {} from {}", childAsString, this);
|
||||||
if (child instanceof Route) routes.remove(child);
|
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);
|
super.removeChild(child);
|
||||||
plan.place(this);
|
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) {
|
public boolean reserveFor(Context context) {
|
||||||
Train newTrain = context.train();
|
Train newTrain = context.train();
|
||||||
LOG.debug("{}.reserverFor({})",this,newTrain);
|
LOG.debug("{}.reserverFor({})",this,newTrain);
|
||||||
if (isNull(newTrain)) return false;
|
if (isNull(newTrain)) return false;
|
||||||
if (isSet(train) && train != newTrain) return false;
|
if (isSet(reservingTrain)) {
|
||||||
switch (status) {
|
if (reservingTrain != newTrain) return debug("{} already reserved for {}",this,reservingTrain);
|
||||||
case DISABLED:
|
return true; // already reserved for newTrain
|
||||||
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(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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEnabled(boolean enabled) {
|
public void setEnabled(boolean enabled) {
|
||||||
if (!enabled) {
|
boolean show = (disabled == enabled);
|
||||||
status = Status.DISABLED;
|
disabled = !enabled;
|
||||||
} else if (is(Status.DISABLED)) { // Status nur ändern, wenn er bisher DISABLED war
|
if (show) plan.place(this);
|
||||||
status = isNull(train) ? Status.FREE : Status.OCCUPIED;
|
|
||||||
}
|
|
||||||
plan.place(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Tile update(HashMap<String, String> params) {
|
public Tile update(HashMap<String, String> params) {
|
||||||
@@ -540,11 +538,8 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
oneWay = null;
|
oneWay = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ("on".equals(params.get(DISABLED))) {
|
disabled = "on".equals(params.get(DISABLED));
|
||||||
status = Status.DISABLED;
|
|
||||||
} else {
|
|
||||||
status = isSet(train) ? Status.OCCUPIED : Status.FREE;
|
|
||||||
}
|
|
||||||
String len = params.get(LENGTH);
|
String len = params.get(LENGTH);
|
||||||
if (isSet(len)) length(Integer.parseInt(len));
|
if (isSet(len)) length(Integer.parseInt(len));
|
||||||
super.update(params);
|
super.update(params);
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import de.srsoftware.web4rail.Command;
|
|||||||
import de.srsoftware.web4rail.Command.Reply;
|
import de.srsoftware.web4rail.Command.Reply;
|
||||||
import de.srsoftware.web4rail.Device;
|
import de.srsoftware.web4rail.Device;
|
||||||
import de.srsoftware.web4rail.Protocol;
|
import de.srsoftware.web4rail.Protocol;
|
||||||
|
import de.srsoftware.web4rail.moving.Train;
|
||||||
import de.srsoftware.web4rail.tags.Fieldset;
|
import de.srsoftware.web4rail.tags.Fieldset;
|
||||||
import de.srsoftware.web4rail.tags.Input;
|
import de.srsoftware.web4rail.tags.Input;
|
||||||
import de.srsoftware.web4rail.tags.Radio;
|
import de.srsoftware.web4rail.tags.Radio;
|
||||||
@@ -159,7 +160,8 @@ public abstract class Turnout extends Tile implements Device{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Reply state(State newState) {
|
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) {
|
if (address == 0) {
|
||||||
sleep(300);
|
sleep(300);
|
||||||
state = newState;
|
state = newState;
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import java.io.IOException;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.srsoftware.web4rail.moving.Train;
|
|
||||||
import de.srsoftware.web4rail.tags.Fieldset;
|
import de.srsoftware.web4rail.tags.Fieldset;
|
||||||
import de.srsoftware.web4rail.tags.Input;
|
import de.srsoftware.web4rail.tags.Input;
|
||||||
import de.srsoftware.web4rail.tags.Window;
|
import de.srsoftware.web4rail.tags.Window;
|
||||||
@@ -16,12 +15,7 @@ public abstract class TurnoutL extends Turnout {
|
|||||||
@Override
|
@Override
|
||||||
public Object click(boolean shift) throws IOException {
|
public Object click(boolean shift) throws IOException {
|
||||||
Object o = super.click(shift);
|
Object o = super.click(shift);
|
||||||
if (!shift) {
|
if (!shift) state(state == State.STRAIGHT ? State.LEFT : State.STRAIGHT);
|
||||||
Train train = train();
|
|
||||||
if (isSet(train)) {
|
|
||||||
plan.stream(t("{} is locked by {}!",this,train));
|
|
||||||
} else state(state == State.STRAIGHT ? State.LEFT : State.STRAIGHT);
|
|
||||||
}
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import java.io.IOException;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import de.srsoftware.web4rail.moving.Train;
|
|
||||||
import de.srsoftware.web4rail.tags.Fieldset;
|
import de.srsoftware.web4rail.tags.Fieldset;
|
||||||
import de.srsoftware.web4rail.tags.Input;
|
import de.srsoftware.web4rail.tags.Input;
|
||||||
import de.srsoftware.web4rail.tags.Window;
|
import de.srsoftware.web4rail.tags.Window;
|
||||||
@@ -16,12 +15,7 @@ public abstract class TurnoutR extends Turnout {
|
|||||||
@Override
|
@Override
|
||||||
public Object click(boolean shift) throws IOException {
|
public Object click(boolean shift) throws IOException {
|
||||||
Object o = super.click(shift);
|
Object o = super.click(shift);
|
||||||
if (!shift) {
|
if (!shift) state(state == State.STRAIGHT ? State.RIGHT : State.STRAIGHT);
|
||||||
Train train = train();
|
|
||||||
if (isSet(train)) {
|
|
||||||
plan.stream(t("{} is locked by {}!",this,train));
|
|
||||||
} else state(state == State.STRAIGHT ? State.RIGHT : State.STRAIGHT);
|
|
||||||
}
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user