Started clean re-implementation of
- reserving route
- preparing route
- locking route
New implementation now properly handles stop event from user.
Next things to implement:
- tracing train upon contact activation, taking care of:
- causing contact
- train's last position
- route
- plan.freeBehindTrain
- finish event, keeping brake processor in mind
This commit is contained in:
@@ -3,11 +3,13 @@ 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;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Vector;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
@@ -20,6 +22,7 @@ import de.srsoftware.web4rail.BaseClass;
|
||||
import de.srsoftware.web4rail.Connector;
|
||||
import de.srsoftware.web4rail.Plan.Direction;
|
||||
import de.srsoftware.web4rail.Range;
|
||||
import de.srsoftware.web4rail.Route;
|
||||
import de.srsoftware.web4rail.moving.Train;
|
||||
import de.srsoftware.web4rail.tags.Button;
|
||||
import de.srsoftware.web4rail.tags.Checkbox;
|
||||
@@ -35,6 +38,53 @@ import de.srsoftware.web4rail.tags.Window;
|
||||
*/
|
||||
public abstract class Block extends StretchableTile{
|
||||
protected static Logger LOG = LoggerFactory.getLogger(Block.class);
|
||||
|
||||
private class TrainList implements Iterable<Train>{
|
||||
|
||||
private LinkedList<Train> trains = new LinkedList<Train>();
|
||||
private HashMap<Train, Direction> dirs = new HashMap<Train, Direction>();
|
||||
|
||||
public void add(Train train, Direction direction) {
|
||||
trains.remove(train);
|
||||
trains.addFirst(train);
|
||||
if (isSet(direction)) dirs.put(train, direction);
|
||||
}
|
||||
|
||||
public Direction directionOf(Train train) {
|
||||
return dirs.get(train);
|
||||
}
|
||||
|
||||
public Train first() {
|
||||
return trains.isEmpty() ? null : trains.getFirst();
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return trains.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<Train> iterator() {
|
||||
return trains.iterator();
|
||||
}
|
||||
|
||||
public Train last() {
|
||||
return trains.isEmpty() ? null : trains.getLast();
|
||||
}
|
||||
|
||||
public List<Train> list() {
|
||||
return new Vector<>(trains);
|
||||
}
|
||||
|
||||
public boolean remove(BaseClass b) {
|
||||
dirs.remove(b);
|
||||
return trains.remove(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return trains.toString();
|
||||
}
|
||||
}
|
||||
private static final String ALLOW_TURN = "allowTurn";
|
||||
private static final String NAME = "name";
|
||||
private static final String NO_TAG = "[default]";
|
||||
@@ -44,11 +94,12 @@ 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 = "parked_trains";
|
||||
|
||||
public String name = "Block";
|
||||
public boolean turnAllowed = false;
|
||||
private Vector<BlockContact> internalContacts = new Vector<BlockContact>();
|
||||
private Vector<Train> parkedTrains = new Vector<Train>();
|
||||
private TrainList trains = new TrainList();
|
||||
|
||||
public Block() {
|
||||
super();
|
||||
@@ -134,9 +185,9 @@ public abstract class Block extends StretchableTile{
|
||||
|
||||
private Vector<WaitTime> waitTimes = new Vector<WaitTime>();
|
||||
|
||||
public void add(Train parkedTrain) {
|
||||
parkedTrain.register();
|
||||
parkedTrains.add(parkedTrain);
|
||||
public void add(Train train,Direction direction) {
|
||||
train.register();
|
||||
trains.add(train,direction);
|
||||
}
|
||||
|
||||
|
||||
@@ -147,22 +198,17 @@ public abstract class Block extends StretchableTile{
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canNeEnteredBy(Train newTrain) {
|
||||
if (!super.canNeEnteredBy(newTrain)) return false;
|
||||
if (parkedTrains.isEmpty()) return true;
|
||||
return isNull(newTrain) ? false : newTrain.isShunting(); // block contains train(s), thus it is only free for shunting train
|
||||
}
|
||||
|
||||
@Override
|
||||
protected HashSet<String> classes() {
|
||||
HashSet<String> classes = super.classes();
|
||||
if (!parkedTrains.isEmpty()) classes.add(Status.OCCUPIED.toString());
|
||||
return classes;
|
||||
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
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object click(boolean shift) throws IOException {
|
||||
if (isSet(train) && !shift) return train.properties();
|
||||
if (!trains.isEmpty() && !shift) return trains.first().properties();
|
||||
return super.click(false);
|
||||
}
|
||||
|
||||
@@ -211,6 +257,27 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean free(Train train) {
|
||||
LOG.debug("{}.free()");
|
||||
Train firstTrain = trains.first();
|
||||
if (isNull(firstTrain)) return true;
|
||||
if (firstTrain != train) return false;
|
||||
trains.remove(train);
|
||||
status = trains.isEmpty() ? Status.FREE : Status.OCCUPIED;
|
||||
plan.place(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
private WaitTime getWaitTime(String tag) {
|
||||
if (tag == null) return null;
|
||||
for (WaitTime wt : waitTimes) {
|
||||
@@ -252,9 +319,9 @@ public abstract class Block extends StretchableTile{
|
||||
}
|
||||
}
|
||||
if (isSet(jContacts)) json.put(CONTACT, jContacts);
|
||||
if (!parkedTrains.isEmpty()) {
|
||||
if (!trains.isEmpty()) {
|
||||
JSONArray ptids = new JSONArray();
|
||||
for (Train parked : parkedTrains) {
|
||||
for (Train parked : trains) {
|
||||
if (isSet(parked)) ptids.put(parked.id().toString());
|
||||
}
|
||||
json.put(PARKED_TRAINS, ptids);
|
||||
@@ -262,6 +329,11 @@ public abstract class Block extends StretchableTile{
|
||||
return json;
|
||||
}
|
||||
|
||||
public Train lastTrain() {
|
||||
return trains.last();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If arguments are given, the first is taken as content, the second as tag type.
|
||||
* If no content is supplied, name is set as content.
|
||||
@@ -294,44 +366,61 @@ public abstract class Block extends StretchableTile{
|
||||
} catch (JSONException e) {}
|
||||
}
|
||||
}
|
||||
if (json.has(PARKED_TRAINS)) {
|
||||
if (json.has(TRAINS)) {
|
||||
JSONArray jTrains = json.getJSONArray(TRAINS);
|
||||
for (Object o : jTrains) {
|
||||
if (o instanceof JSONObject) {
|
||||
JSONObject to = (JSONObject) o;
|
||||
Train train = BaseClass.get(new Id(to.getString(ID)));
|
||||
Direction direction = to.has(DIRECTION) ? Direction.valueOf(to.getString(DIRECTION)) : null;
|
||||
if (isSet(train)) trains.add(train, direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (json.has(PARKED_TRAINS)) { // legacy
|
||||
JSONArray ptids = json.getJSONArray(PARKED_TRAINS);
|
||||
for (Object id : ptids) {
|
||||
Train train = BaseClass.get(new Id(id.toString()));
|
||||
if (isSet(train)) parkedTrains.add(train);
|
||||
if (isSet(train)) trains.add(train,null);
|
||||
}
|
||||
}
|
||||
return super.load(json);
|
||||
}
|
||||
|
||||
private Fieldset parkedTrainList() {
|
||||
Fieldset fieldset = new Fieldset(t("parked trains"));
|
||||
Tag list = new Tag("ul");
|
||||
for (Train t : parkedTrains) {
|
||||
if (isSet(t)) t.link("li", t).addTo(list);
|
||||
@Override
|
||||
public boolean lockFor(Context context) {
|
||||
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 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 OCCUPIED:
|
||||
case LOCKED:
|
||||
break; // do not downgrade
|
||||
}
|
||||
list.addTo(fieldset);
|
||||
return fieldset;
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<Train> parkedTrains(){
|
||||
return parkedTrains;
|
||||
}
|
||||
|
||||
public Train parkedTrain(boolean last) {
|
||||
if (parkedTrains.isEmpty()) return null;
|
||||
return last ? parkedTrains.lastElement() : parkedTrains.firstElement();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm,String...errors) {
|
||||
formInputs.add(t("Name"),new Input(NAME, name));
|
||||
formInputs.add("",new Checkbox(ALLOW_TURN,t("Turn allowed"),turnAllowed));
|
||||
formInputs.add(t("Train"),Train.selector(train, null));
|
||||
formInputs.add(t("Train"),Train.selector(trains.first(), null));
|
||||
postForm.add(contactForm());
|
||||
postForm.add(waitTimeForm());
|
||||
if (!parkedTrains.isEmpty()) postForm.add(parkedTrainList());
|
||||
if (!trains.isEmpty()) postForm.add(trainList());
|
||||
return super.properties(preForm, formInputs, postForm,errors);
|
||||
}
|
||||
|
||||
@@ -346,6 +435,32 @@ public abstract class Block extends StretchableTile{
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean reserveFor(Context context) {
|
||||
Train newTrain = context.train();
|
||||
Route route = context.route();
|
||||
LOG.debug("{}.reserverFor({})",this,newTrain);
|
||||
if (isNull(newTrain)) return false;
|
||||
Train train = trains.first();
|
||||
if (isSet(train) && train != newTrain) return false;
|
||||
switch (status) {
|
||||
case DISABLED:
|
||||
return false;
|
||||
case FREE:
|
||||
status = Status.RESERVED;
|
||||
Direction dir = trains.directionOf(train);
|
||||
if (isSet(route) && this == route.endBlock()) dir = route.endDirection;
|
||||
add(newTrain,dir);
|
||||
plan.place(this);
|
||||
break;
|
||||
case OCCUPIED:
|
||||
case LOCKED:
|
||||
case RESERVED:
|
||||
break; // do not downgrade
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public BlockContact register(BlockContact contact) {
|
||||
internalContacts.add(contact);
|
||||
@@ -356,13 +471,17 @@ public abstract class Block extends StretchableTile{
|
||||
public void removeChild(BaseClass child) {
|
||||
super.removeChild(child);
|
||||
internalContacts.remove(child);
|
||||
if (parkedTrains.remove(child)) plan.place(this);
|
||||
if (trains.remove(child)) plan.place(this);
|
||||
}
|
||||
|
||||
public void removeContact(BlockContact blockContact) {
|
||||
internalContacts.remove(blockContact);
|
||||
}
|
||||
|
||||
public List<Route> routes(Direction direction) {
|
||||
return routes().stream().filter(route -> route.startBlock() == Block.this).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
public abstract List<Connector> startPoints();
|
||||
|
||||
@Override
|
||||
@@ -370,10 +489,7 @@ public abstract class Block extends StretchableTile{
|
||||
if (isNull(replacements)) replacements = new HashMap<String, Object>();
|
||||
replacements.put("%text%",name);
|
||||
Vector<String> trainNames = new Vector<String>();
|
||||
if (isSet(train)) trainNames.add(train.directedName());
|
||||
for (Train t:parkedTrains) {
|
||||
if (isSet(t)) trainNames.add(t.directedName());
|
||||
}
|
||||
for (Train train: trains) trainNames.add(train.directedName(trains.directionOf(train)));
|
||||
if (!trainNames.isEmpty())replacements.put("%text%",String.join(" | ", trainNames));
|
||||
Tag tag = super.tag(replacements);
|
||||
tag.clazz(tag.get("class")+" Block");
|
||||
@@ -390,23 +506,45 @@ public abstract class Block extends StretchableTile{
|
||||
return name + " @ ("+x+","+y+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Train train() {
|
||||
return train(false);
|
||||
}
|
||||
|
||||
public Train train(boolean last) {
|
||||
return last ? trains.last() : trains.first();
|
||||
}
|
||||
|
||||
|
||||
private Fieldset trainList() {
|
||||
Fieldset fieldset = new Fieldset(t("Trains"));
|
||||
Tag list = new Tag("ul");
|
||||
for (Train t : trains) {
|
||||
if (isSet(t)) t.link("li", t).addTo(list);
|
||||
}
|
||||
list.addTo(fieldset);
|
||||
return fieldset;
|
||||
}
|
||||
|
||||
public List<Train> trains(){
|
||||
return trains.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tile update(HashMap<String, String> params) {
|
||||
if (params.containsKey(NAME)) name=params.get(NAME);
|
||||
if (params.containsKey(Train.class.getSimpleName())) {
|
||||
Id trainId = Id.from(params,Train.class.getSimpleName());
|
||||
if (trainId.equals(0)) {
|
||||
if (isSet(train)) {
|
||||
train.dropTrace();
|
||||
train.set(null);
|
||||
}
|
||||
train = null;
|
||||
if (trainId.equals(0)) { // remove first train
|
||||
dropFirstTrain();
|
||||
} else {
|
||||
Train newTrain = Train.get(trainId);
|
||||
if (isSet(newTrain) && newTrain != train) {
|
||||
newTrain.dropTrace();
|
||||
if (connections(newTrain.direction()).isEmpty()) newTrain.heading(null);
|
||||
newTrain.set(this);
|
||||
Train train = Train.get(trainId);
|
||||
if (isSet(train) && train != trains.first()) {
|
||||
dropFirstTrain();
|
||||
train.dropTrace();
|
||||
if (connections(train.direction()).isEmpty()) train.heading(null);
|
||||
train.set(this);
|
||||
trains.add(train,train.direction());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,7 @@ public class BlockContact extends Contact {
|
||||
|
||||
@Override
|
||||
public Train train() {
|
||||
train = ((Block)parent()).train();
|
||||
return train;
|
||||
return ((Block)parent()).train();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -42,9 +42,9 @@ public abstract class Bridge extends Tile {
|
||||
protected abstract Connector connector();
|
||||
|
||||
@Override
|
||||
public void free() {
|
||||
if (isSet(counterpart) && counterpart.train != null) counterpart.free();
|
||||
super.free();
|
||||
public boolean free(Train train) {
|
||||
if (!super.free(train)) return false;
|
||||
return isSet(counterpart) ? counterpart.free(train) : true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,10 +68,10 @@ public abstract class Bridge extends Tile {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setState(Status newState, Train newTrain) {
|
||||
if (train == newTrain && is(newState)) return true;
|
||||
if (!super.setState(newState,newTrain)) return false;
|
||||
return isNull(counterpart) ? true : counterpart.setState(newState,newTrain);
|
||||
public boolean setTrain(Train newTrain) {
|
||||
if (train() == newTrain) return true;
|
||||
if (!super.setTrain(newTrain)) return false;
|
||||
return isNull(counterpart) ? true : counterpart.setTrain(newTrain);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -18,6 +18,7 @@ import de.srsoftware.web4rail.Application;
|
||||
import de.srsoftware.web4rail.BaseClass;
|
||||
import de.srsoftware.web4rail.actions.Action;
|
||||
import de.srsoftware.web4rail.actions.ActionList;
|
||||
import de.srsoftware.web4rail.moving.Train;
|
||||
import de.srsoftware.web4rail.tags.Fieldset;
|
||||
import de.srsoftware.web4rail.tags.Input;
|
||||
import de.srsoftware.web4rail.tags.Select;
|
||||
@@ -84,11 +85,8 @@ public class Contact extends Tile{
|
||||
LOG.debug("{} activated.",this);
|
||||
state = true;
|
||||
if (isSet(timer)) timer.abort();
|
||||
Context context = new Context(this);
|
||||
if (isSet(train())) {
|
||||
train.contact(this);
|
||||
context.train(train);
|
||||
}
|
||||
Train train = train();
|
||||
Context context = isSet(train) ? train.contact(this) : new Context(this);
|
||||
actions.fire(context,"Contact("+addr+")");
|
||||
|
||||
for (Listener listener : listeners) listener.fired("Contact("+addr+")");
|
||||
|
||||
@@ -38,109 +38,81 @@ import de.srsoftware.web4rail.tags.Window;
|
||||
* @author Stephan Richter, SRSoftware
|
||||
*
|
||||
*/
|
||||
public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
||||
public enum Status{
|
||||
FREE("free"),
|
||||
ALLOCATED("allocated"),
|
||||
LOCKED("locked"),
|
||||
OCCUPIED("occupied");
|
||||
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 final String LENGTH = "length";
|
||||
private static final String ONEW_WAY = "one_way";
|
||||
private static final String POS = "pos";
|
||||
private static final String TYPE = "type";
|
||||
private static final String X = "x";
|
||||
private static final String Y = "y";
|
||||
|
||||
private boolean disabled = false;
|
||||
private boolean isTrack = true;
|
||||
private int length = DEFAUT_LENGTH;
|
||||
protected Direction oneWay = null;
|
||||
private TreeSet<Route> routes = new TreeSet<>((r1,r2)->r1.toString().compareTo(r2.toString()));
|
||||
private Status status = Status.FREE;
|
||||
protected Train train = null;
|
||||
public Integer x = null;
|
||||
public Integer y = null;
|
||||
|
||||
|
||||
private static final String LENGTH = "length";
|
||||
private static final String ONEW_WAY = "one_way";
|
||||
private static final String POS = "pos";
|
||||
private static final String TYPE = "type";
|
||||
private static final String X = "x";
|
||||
private static final String Y = "y";
|
||||
|
||||
private boolean isTrack = true;
|
||||
private int length = DEFAUT_LENGTH;
|
||||
protected Direction oneWay = null;
|
||||
private TreeSet<Route> routes = new TreeSet<>((r1, r2) -> r1.toString().compareTo(r2.toString()));
|
||||
private Train train = null;
|
||||
protected Status status = Status.FREE;
|
||||
public Integer x = null;
|
||||
public Integer y = null;
|
||||
|
||||
public void add(Route route) {
|
||||
this.routes.add(route);
|
||||
}
|
||||
|
||||
public boolean canNeEnteredBy(Train newTrain) {
|
||||
LOG.debug("{}.canNeEnteredBy({})",this,newTrain);
|
||||
if (disabled) {
|
||||
LOG.debug("{} is disabled!",this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isNull(train)) {
|
||||
LOG.debug("→ free");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newTrain == train) { // during train.reserveNext, we may encounter, parts, that are already reserved by the respective train, but having another route. do not compare routes in that case!
|
||||
LOG.debug("already reserved by {} → true",train);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isSet(newTrain) && newTrain.isShunting()) {
|
||||
LOG.debug("occupied by {}. Allowed for shunting {}",train,newTrain);
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG.debug("occupied by {} → false",train);
|
||||
return false;
|
||||
}
|
||||
|
||||
protected HashSet<String> classes(){
|
||||
protected HashSet<String> classes() {
|
||||
HashSet<String> classes = new HashSet<String>();
|
||||
classes.add("tile");
|
||||
classes.add(getClass().getSimpleName());
|
||||
classes.add(getClass().getSimpleName());
|
||||
if (!is(Status.FREE)) classes.add(status.toString());
|
||||
if (disabled) classes.add(DISABLED);
|
||||
return classes;
|
||||
}
|
||||
|
||||
public Object click(boolean shift) throws IOException {
|
||||
LOG.debug("{}.click()",getClass().getSimpleName());
|
||||
LOG.debug("{}.click()", getClass().getSimpleName());
|
||||
if (isSet(train) && shift) return train.properties();
|
||||
return properties();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(Tile other) {
|
||||
if (x == other.x) return y-other.y;
|
||||
if (x == other.x) return y - other.y;
|
||||
return x - other.x;
|
||||
}
|
||||
|
||||
|
||||
public JSONObject config() {
|
||||
return new JSONObject();
|
||||
}
|
||||
|
||||
public Map<Connector,Turnout.State> connections(Direction from){
|
||||
|
||||
public Map<Connector, Turnout.State> connections(Direction from) {
|
||||
return new HashMap<>();
|
||||
}
|
||||
|
||||
public void free() {
|
||||
|
||||
public boolean free(Train t) {
|
||||
if (t != train) return false;
|
||||
train = null;
|
||||
status = Status.FREE;
|
||||
plan.place(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public int height() {
|
||||
return 1;
|
||||
}
|
||||
@@ -148,60 +120,89 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
||||
public Id id() {
|
||||
return Tile.id(x, y);
|
||||
}
|
||||
|
||||
|
||||
public static Id id(int x, int y) {
|
||||
return new Id(x+"-"+y);
|
||||
return new Id(x + "-" + y);
|
||||
}
|
||||
|
||||
private static void inflate(String clazz, JSONObject json, Plan plan) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, IOException {
|
||||
clazz = Tile.class.getName().replace(".Tile", "."+clazz);
|
||||
|
||||
private static void inflate(String clazz, JSONObject json,
|
||||
Plan plan) throws InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException, ClassNotFoundException, IOException {
|
||||
clazz = Tile.class.getName().replace(".Tile", "." + clazz);
|
||||
Tile tile = (Tile) Tile.class.getClassLoader().loadClass(clazz).getDeclaredConstructor().newInstance();
|
||||
tile.load(json).register();
|
||||
if (tile instanceof TileWithShadow) ((TileWithShadow)tile).placeShadows();
|
||||
if (tile instanceof TileWithShadow) ((TileWithShadow) tile).placeShadows();
|
||||
plan.place(tile);
|
||||
}
|
||||
|
||||
public boolean is(Status...states) {
|
||||
for (Status s: states) {
|
||||
|
||||
public boolean is(Status... states) {
|
||||
for (Status s : states) {
|
||||
if (status == s) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isFreeFor(Context newTrain) {
|
||||
LOG.debug("{}.isFreeFor({})", this, newTrain);
|
||||
if (is(Status.DISABLED)) {
|
||||
LOG.debug("{} is disabled!", this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isNull(train)) {
|
||||
LOG.debug("→ free");
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newTrain.train() == train) { // during train.reserveNext, we may encounter, parts, that are already reserved
|
||||
// by the respective train, but having another route. do not compare routes
|
||||
// in that case!
|
||||
LOG.debug("already reserved by {} → true", train);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isSet(newTrain.train()) && newTrain.train().isShunting()) {
|
||||
LOG.debug("occupied by {}. Allowed for shunting {}", train, newTrain.train());
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG.debug("occupied by {} → false", train);
|
||||
return false;
|
||||
}
|
||||
|
||||
public JSONObject json() {
|
||||
JSONObject json = super.json();
|
||||
json.put(TYPE, getClass().getSimpleName());
|
||||
if (isSet(x) && isSet(y)) json.put(POS, new JSONObject(Map.of(X,x,Y,y)));
|
||||
if (isSet(oneWay)) json.put(ONEW_WAY, oneWay);
|
||||
if (disabled) json.put(DISABLED, true);
|
||||
if (isSet(train)) json.put(REALM_TRAIN, train.id());
|
||||
if (isSet(x) && isSet(y)) json.put(POS, new JSONObject(Map.of(X, x, Y, y)));
|
||||
if (isSet(oneWay)) json.put(ONEW_WAY, oneWay);
|
||||
if (is(Status.DISABLED)) json.put(DISABLED, true);
|
||||
if (isSet(train)) json.put(REALM_TRAIN, train.id());
|
||||
json.put(LENGTH, length);
|
||||
return json;
|
||||
}
|
||||
|
||||
|
||||
public int length() {
|
||||
return length;
|
||||
}
|
||||
|
||||
|
||||
public Tile length(int newLength) {
|
||||
length = Math.max(0, newLength);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If arguments are given, the first is taken as content, the second as tag type.
|
||||
* If no content is supplied, id() is set as content.
|
||||
* If no type is supplied, "span" is preset.
|
||||
* If arguments are given, the first is taken as content, the second as tag
|
||||
* type. If no content is supplied, id() is set as content. If no type is
|
||||
* supplied, "span" is preset.
|
||||
*
|
||||
* @param args
|
||||
* @return
|
||||
*/
|
||||
public Tag link(String...args) {
|
||||
String tx = args.length<1 ? id()+NBSP : args[0];
|
||||
String type = args.length<2 ? "span" : args[1];
|
||||
return super.link(type, (Object)tx, Map.of(ACTION,ACTION_CLICK));
|
||||
public Tag link(String... args) {
|
||||
String tx = args.length < 1 ? id() + NBSP : args[0];
|
||||
String type = args.length < 2 ? "span" : args[1];
|
||||
return super.link(type, (Object) tx, Map.of(ACTION, ACTION_CLICK));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void load(Object object, Plan plan) {
|
||||
if (object instanceof JSONObject) {
|
||||
JSONObject json = (JSONObject) object;
|
||||
@@ -210,10 +211,12 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
||||
clazz = AlterDirection.class.getSimpleName();
|
||||
}
|
||||
try {
|
||||
Tile.inflate(clazz,json,plan);
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | ClassNotFoundException | IOException e) {
|
||||
Tile.inflate(clazz, json, plan);
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException | NoSuchMethodException | SecurityException | ClassNotFoundException
|
||||
| IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,89 +226,92 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
||||
if (json.has(POS)) {
|
||||
JSONObject pos = json.getJSONObject(POS);
|
||||
x = pos.getInt(X);
|
||||
y = pos.getInt(Y);
|
||||
y = pos.getInt(Y);
|
||||
}
|
||||
if (json.has(DISABLED)) disabled = json.getBoolean(DISABLED);
|
||||
if (json.has(LENGTH)) length = json.getInt(LENGTH);
|
||||
if (json.has(ONEW_WAY)) oneWay = Direction.valueOf(json.getString(ONEW_WAY));
|
||||
if (json.has(DISABLED) && json.getBoolean(DISABLED)) status = Status.DISABLED;
|
||||
if (json.has(LENGTH)) length = json.getInt(LENGTH);
|
||||
if (json.has(ONEW_WAY)) oneWay = Direction.valueOf(json.getString(ONEW_WAY));
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public boolean move(int dx, int dy) {
|
||||
int destX = x+(dx > 0 ? width() : dx);
|
||||
int destY = y+(dy > 0 ? height() : dy);
|
||||
int destX = x + (dx > 0 ? width() : dx);
|
||||
int destY = y + (dy > 0 ? height() : dy);
|
||||
if (destX < 0 || destY < 0) return false;
|
||||
|
||||
Tile tileAtDestination = plan.get(id(destX, destY),true);
|
||||
|
||||
Tile tileAtDestination = plan.get(id(destX, destY), true);
|
||||
if (isSet(tileAtDestination) && !tileAtDestination.move(dx, dy)) return false;
|
||||
plan.drop(this);
|
||||
position(x+dx, y+dy);
|
||||
plan.drop(this);
|
||||
position(x + dx, y + dy);
|
||||
plan.place(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
protected void noTrack() {
|
||||
isTrack = false;
|
||||
isTrack = false;
|
||||
}
|
||||
|
||||
|
||||
public Tile position(int x, int y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public List<Direction> possibleDirections() {
|
||||
return new Vector<Plan.Direction>();
|
||||
}
|
||||
|
||||
|
||||
@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) {
|
||||
Fieldset fieldset = null;
|
||||
|
||||
|
||||
if (isSet(train)) {
|
||||
fieldset = new Fieldset(t("Train"));
|
||||
train.link("span", t("Train")+":"+NBSP+train+NBSP).addTo(fieldset);
|
||||
train.link("span", t("Train") + ":" + NBSP + train + NBSP).addTo(fieldset);
|
||||
if (isSet(train.route())) {
|
||||
train.button(t("stop"), Map.of(ACTION,ACTION_STOP)).addTo(fieldset);
|
||||
train.button(t("stop"), Map.of(ACTION, ACTION_STOP)).addTo(fieldset);
|
||||
} else {
|
||||
train.button(t("depart"), Map.of(ACTION,ACTION_START)).addTo(fieldset);
|
||||
train.button(t("depart"), Map.of(ACTION, ACTION_START)).addTo(fieldset);
|
||||
}
|
||||
if (train.usesAutopilot()) {
|
||||
train.button(t("quit autopilot"), Map.of(ACTION,ACTION_QUIT)).addTo(fieldset);
|
||||
train.button(t("quit autopilot"), Map.of(ACTION, ACTION_QUIT)).addTo(fieldset);
|
||||
} else {
|
||||
train.button(t("auto"), Map.of(ACTION,ACTION_AUTO)).addTo(fieldset);
|
||||
train.button(t("auto"), Map.of(ACTION, ACTION_AUTO)).addTo(fieldset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isSet(fieldset)) preForm.add(fieldset);
|
||||
|
||||
|
||||
if (isTrack) {
|
||||
formInputs.add(t("Length"),new Input(LENGTH,length).numeric().addTo(new Tag("span")).content(NBSP+lengthUnit));
|
||||
Checkbox checkbox = new Checkbox(DISABLED, t("disabled"),disabled);
|
||||
if (disabled) checkbox.clazz("disabled");
|
||||
formInputs.add(t("State"),checkbox);
|
||||
formInputs.add(t("Length"),
|
||||
new Input(LENGTH, length).numeric().addTo(new Tag("span")).content(NBSP + lengthUnit));
|
||||
Checkbox checkbox = new Checkbox(DISABLED, t("disabled"), is(Status.DISABLED));
|
||||
if (is(Status.DISABLED)) checkbox.clazz("disabled");
|
||||
formInputs.add(t("State"), checkbox);
|
||||
}
|
||||
|
||||
|
||||
List<Direction> pd = possibleDirections();
|
||||
if (!pd.isEmpty()) {
|
||||
Tag div = new Tag("div");
|
||||
new Radio("oneway","none",t("No"),isNull(oneWay)).addTo(div);
|
||||
for (Direction d:pd) {
|
||||
new Radio("oneway",d.toString(),t(d.toString()),d == oneWay).addTo(div);
|
||||
new Radio("oneway", "none", t("No"), isNull(oneWay)).addTo(div);
|
||||
for (Direction d : pd) {
|
||||
new Radio("oneway", d.toString(), t(d.toString()), d == oneWay).addTo(div);
|
||||
}
|
||||
formInputs.add(t("One way"),div);
|
||||
formInputs.add(t("One way"), div);
|
||||
}
|
||||
|
||||
|
||||
if (!routes.isEmpty()) {
|
||||
fieldset = new Fieldset(t("Routes")).id("props-routes");
|
||||
Tag routeList = new Tag("ol");
|
||||
boolean empty = true;
|
||||
for (Route route : routes) {
|
||||
if (route.isDisabled()) continue;
|
||||
Tag li = route.link("span", route.name()+(route.isDisabled()?" ["+t("disabled")+"]" : "")+NBSP).addTo(new Tag("li").clazz("link"));
|
||||
route.button(t("delete route"),Map.of(ACTION,ACTION_DROP)).addTo(li);
|
||||
button(t("simplify name"), Map.of(ACTION,ACTION_AUTO,ROUTE,route.id().toString())).addTo(li);
|
||||
Tag li = route
|
||||
.link("span", route.name() + (route.isDisabled() ? " [" + t("disabled") + "]" : "") + NBSP)
|
||||
.addTo(new Tag("li").clazz("link"));
|
||||
route.button(t("delete route"), Map.of(ACTION, ACTION_DROP)).addTo(li);
|
||||
button(t("simplify name"), Map.of(ACTION, ACTION_AUTO, ROUTE, route.id().toString())).addTo(li);
|
||||
li.addTo(routeList);
|
||||
empty = false;
|
||||
}
|
||||
@@ -314,14 +320,16 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
||||
routeList.addTo(fieldset);
|
||||
postForm.add(fieldset);
|
||||
}
|
||||
|
||||
|
||||
routeList = new Tag("ol");
|
||||
empty = true;
|
||||
for (Route route : routes) {
|
||||
if (!route.isDisabled()) continue;
|
||||
Tag li = route.link("span", route.name()+(route.isDisabled()?" ["+t("disabled")+"]" : "")+NBSP).addTo(new Tag("li").clazz("link"));
|
||||
route.button(t("delete route"),Map.of(ACTION,ACTION_DROP)).addTo(li);
|
||||
button(t("simplify name"), Map.of(ACTION,ACTION_AUTO,ROUTE,route.id().toString())).addTo(li);
|
||||
Tag li = route
|
||||
.link("span", route.name() + (route.isDisabled() ? " [" + t("disabled") + "]" : "") + NBSP)
|
||||
.addTo(new Tag("li").clazz("link"));
|
||||
route.button(t("delete route"), Map.of(ACTION, ACTION_DROP)).addTo(li);
|
||||
button(t("simplify name"), Map.of(ACTION, ACTION_AUTO, ROUTE, route.id().toString())).addTo(li);
|
||||
li.addTo(routeList);
|
||||
empty = false;
|
||||
}
|
||||
@@ -330,84 +338,90 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
||||
routeList.addTo(fieldset);
|
||||
}
|
||||
}
|
||||
|
||||
return super.properties(preForm, formInputs, postForm,errors);
|
||||
|
||||
return super.properties(preForm, formInputs, postForm, errors);
|
||||
}
|
||||
|
||||
|
||||
private static String replace(String line, Entry<String, Object> replacement) {
|
||||
String key = replacement.getKey();
|
||||
String key = replacement.getKey();
|
||||
Object val = replacement.getValue();
|
||||
int start = line.indexOf(key);
|
||||
int len = key.length();
|
||||
while (start>0) {
|
||||
int end = line.indexOf("\"",start);
|
||||
int end2 = line.indexOf("<",start);
|
||||
if (end2>0 && (end<0 || end2<end)) end=end2;
|
||||
while (start > 0) {
|
||||
int end = line.indexOf("\"", start);
|
||||
int end2 = line.indexOf("<", start);
|
||||
if (end2 > 0 && (end < 0 || end2 < end)) end = end2;
|
||||
String tag = line.substring(start, end);
|
||||
if (tag.length()>len) val = Integer.parseInt(tag.substring(len)) + (int) val;
|
||||
line = line.replace(tag, ""+val);
|
||||
if (tag.length() > len) val = Integer.parseInt(tag.substring(len)) + (int) val;
|
||||
line = line.replace(tag, "" + val);
|
||||
start = line.indexOf(key);
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
public TreeSet<Route> routes() {
|
||||
return routes;
|
||||
}
|
||||
|
||||
|
||||
public static void saveAll(String filename) throws IOException {
|
||||
BufferedWriter file = new BufferedWriter(new FileWriter(filename));
|
||||
for (Tile tile : BaseClass.listElements(Tile.class)) {
|
||||
if (isNull(tile) || tile instanceof Shadow || tile instanceof BlockContact) continue;
|
||||
file.append(tile.json()+"\n");
|
||||
file.append(tile.json() + "\n");
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
|
||||
public boolean setState(Status newState,Train newTrain) {
|
||||
|
||||
public boolean setTrain(Train newTrain) {
|
||||
if (isNull(newTrain)) return false;
|
||||
if (isSet(train) && newTrain != train) return false; // already locked by other train
|
||||
if (is(Status.OCCUPIED,newState)) return true; // do not downgrade occupied tiles, accept current state
|
||||
train = newTrain;
|
||||
status = newState;
|
||||
plan.place(this);
|
||||
if (isSet(train) && newTrain != train) return false;
|
||||
switch (status) { // bisheriger Status
|
||||
case DISABLED:
|
||||
return false;
|
||||
case FREE:
|
||||
case RESERVED:
|
||||
case LOCKED:
|
||||
train = newTrain;
|
||||
status = Status.OCCUPIED;
|
||||
plan.place(this);
|
||||
break;
|
||||
case OCCUPIED:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Tag tag(Map<String,Object> replacements) throws IOException {
|
||||
int width = 100*width();
|
||||
int height = 100*height();
|
||||
|
||||
public Tag tag(Map<String, Object> replacements) throws IOException {
|
||||
int width = 100 * width();
|
||||
int height = 100 * height();
|
||||
if (isNull(replacements)) replacements = new HashMap<String, Object>();
|
||||
replacements.put("%width%",width);
|
||||
replacements.put("%height%",height);
|
||||
replacements.put("%width%", width);
|
||||
replacements.put("%height%", height);
|
||||
String style = "";
|
||||
Tag svg = new Tag("svg")
|
||||
.id(isSet(x) && isSet(y) ? id().toString() : getClass().getSimpleName())
|
||||
.clazz(classes())
|
||||
.size(100,100)
|
||||
.attr("name", getClass().getSimpleName())
|
||||
.attr("viewbox", "0 0 "+width+" "+height);
|
||||
if (isSet(x)) style="left: "+(30*x)+"px; top: "+(30*y)+"px;";
|
||||
if (width()>1) style+=" width: "+(30*width())+"px;";
|
||||
if (height()>1) style+=" height: "+(30*height())+"px;";
|
||||
|
||||
Tag svg = new Tag("svg").id(isSet(x) && isSet(y) ? id().toString() : getClass().getSimpleName())
|
||||
.clazz(classes()).size(100, 100).attr("name", getClass().getSimpleName())
|
||||
.attr("viewbox", "0 0 " + width + " " + height);
|
||||
if (isSet(x)) style = "left: " + (30 * x) + "px; top: " + (30 * y) + "px;";
|
||||
if (width() > 1) style += " width: " + (30 * width()) + "px;";
|
||||
if (height() > 1) style += " height: " + (30 * height()) + "px;";
|
||||
|
||||
if (!style.isEmpty()) svg.style(style);
|
||||
|
||||
File file = new File(System.getProperty("user.dir")+"/resources/svg/"+getClass().getSimpleName()+".svg");
|
||||
File file = new File(System.getProperty("user.dir") + "/resources/svg/" + getClass().getSimpleName() + ".svg");
|
||||
if (file.exists()) {
|
||||
Scanner scanner = new Scanner(file, StandardCharsets.UTF_8);
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while (scanner.hasNextLine()) {
|
||||
String line = scanner.nextLine();
|
||||
if (line.startsWith("<svg") || line.endsWith("svg>")) continue;
|
||||
for (Entry<String, Object> replacement : replacements.entrySet()) line = replace(line,replacement);
|
||||
sb.append(line+"\n");
|
||||
for (Entry<String, Object> replacement : replacements.entrySet()) line = replace(line, replacement);
|
||||
sb.append(line + "\n");
|
||||
}
|
||||
scanner.close();
|
||||
svg.content(sb.toString());
|
||||
|
||||
|
||||
if (isSet(oneWay)) {
|
||||
switch (oneWay) {
|
||||
switch (oneWay) {
|
||||
case EAST:
|
||||
new Tag("polygon").clazz("oneway").attr("points", "100,50 75,35 75,65").addTo(svg);
|
||||
break;
|
||||
@@ -426,54 +440,97 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
||||
String title = title();
|
||||
if (isSet(title)) new Tag("title").content(title()).addTo(svg);
|
||||
} else {
|
||||
new Tag("title").content(t("No display defined for this tile ({})",getClass().getSimpleName())).addTo(svg);
|
||||
new Tag("text")
|
||||
.pos(35,70)
|
||||
.content("?")
|
||||
.addTo(svg);
|
||||
new Tag("title").content(t("No display defined for this tile ({})", getClass().getSimpleName())).addTo(svg);
|
||||
new Tag("text").pos(35, 70).content("?").addTo(svg);
|
||||
}
|
||||
|
||||
return svg;
|
||||
}
|
||||
|
||||
|
||||
public String title() {
|
||||
return getClass().getSimpleName() + " @ ("+x+", "+y+")";
|
||||
return getClass().getSimpleName() + " @ (" + x + ", " + y + ")";
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return t("{}({},{})",getClass().getSimpleName(),x,y) ;
|
||||
return t("{}({},{})", getClass().getSimpleName(), x, y);
|
||||
}
|
||||
|
||||
|
||||
public Train train() {
|
||||
return train;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public BaseClass remove() {
|
||||
while (!routes.isEmpty()) routes.first().remove();
|
||||
return super.remove();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void removeChild(BaseClass child) {
|
||||
String childAsString = child.toString();
|
||||
if (childAsString.length()>20) childAsString = childAsString.substring(0, 20)+"…";
|
||||
LOG.debug("Removing {} from {}",childAsString,this);
|
||||
if (childAsString.length() > 20) childAsString = childAsString.substring(0, 20) + "…";
|
||||
LOG.debug("Removing {} from {}", childAsString, this);
|
||||
if (child instanceof Route) routes.remove(child);
|
||||
|
||||
|
||||
if (child == train) train = null;
|
||||
super.removeChild(child);
|
||||
plan.place(this);
|
||||
}
|
||||
|
||||
public void setEnabled(boolean newState) {
|
||||
disabled = !newState;
|
||||
public boolean lockFor(Context context) {
|
||||
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 FREE:
|
||||
case RESERVED:
|
||||
status = Status.LOCKED;
|
||||
plan.place(this);
|
||||
break;
|
||||
case OCCUPIED:
|
||||
case LOCKED:
|
||||
break; // do not downgrade
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public boolean reserveFor(Context context) {
|
||||
Train newTrain = context.train();
|
||||
LOG.debug("{}.reserverFor({})",this,newTrain);
|
||||
if (isNull(newTrain)) return false;
|
||||
if (isSet(train) && train != newTrain) return false;
|
||||
switch (status) {
|
||||
case DISABLED:
|
||||
return false;
|
||||
case FREE:
|
||||
status = Status.RESERVED;
|
||||
train = newTrain;
|
||||
plan.place(this);
|
||||
break;
|
||||
case OCCUPIED:
|
||||
case LOCKED:
|
||||
case RESERVED:
|
||||
break; // do not downgrade
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
if (!enabled) {
|
||||
status = Status.DISABLED;
|
||||
} else if (is(Status.DISABLED)) { // Status nur ändern, wenn er bisher DISABLED war
|
||||
status = isNull(train) ? Status.FREE : Status.OCCUPIED;
|
||||
}
|
||||
plan.place(this);
|
||||
}
|
||||
|
||||
|
||||
public Tile update(HashMap<String, String> params) {
|
||||
LOG.debug("{}.update({})",getClass().getSimpleName(),params);
|
||||
LOG.debug("{}.update({})", getClass().getSimpleName(), params);
|
||||
String oneWayDir = params.get("oneway");
|
||||
if (isSet(oneWayDir)) {
|
||||
try {
|
||||
@@ -482,17 +539,15 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
||||
oneWay = null;
|
||||
}
|
||||
}
|
||||
disabled = "on".equals(params.get(DISABLED));
|
||||
if ("on".equals(params.get(DISABLED))) status = Status.DISABLED;
|
||||
String len = params.get(LENGTH);
|
||||
if (isSet(len)) length(Integer.parseInt(len));
|
||||
super.update(params);
|
||||
plan.place(this);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
public int width() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ public abstract class Turnout extends Tile implements Device{
|
||||
}
|
||||
|
||||
public Reply state(State newState) {
|
||||
if (is(Status.LOCKED,Status.OCCUPIED) && newState != state) return new Reply(415, t("{} locked by {}!",this,train));
|
||||
if (is(Status.LOCKED,Status.OCCUPIED) && newState != state) return new Reply(415, t("{} locked by {}!",this,train()));
|
||||
if (address == 0) {
|
||||
state = newState;
|
||||
plan.place(this);
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import de.srsoftware.web4rail.moving.Train;
|
||||
import de.srsoftware.web4rail.tags.Fieldset;
|
||||
import de.srsoftware.web4rail.tags.Input;
|
||||
import de.srsoftware.web4rail.tags.Window;
|
||||
@@ -16,6 +17,7 @@ public abstract class TurnoutL extends Turnout {
|
||||
public Object click(boolean shift) throws IOException {
|
||||
Object o = super.click(shift);
|
||||
if (!shift) {
|
||||
Train train = train();
|
||||
if (isSet(train)) {
|
||||
plan.stream(t("{} is locked by {}!",this,train));
|
||||
} else state(state == State.STRAIGHT ? State.LEFT : State.STRAIGHT);
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import de.srsoftware.web4rail.moving.Train;
|
||||
import de.srsoftware.web4rail.tags.Fieldset;
|
||||
import de.srsoftware.web4rail.tags.Input;
|
||||
import de.srsoftware.web4rail.tags.Window;
|
||||
@@ -16,6 +17,7 @@ public abstract class TurnoutR extends Turnout {
|
||||
public Object click(boolean shift) throws IOException {
|
||||
Object o = super.click(shift);
|
||||
if (!shift) {
|
||||
Train train = train();
|
||||
if (isSet(train)) {
|
||||
plan.stream(t("{} is locked by {}!",this,train));
|
||||
} else state(state == State.STRAIGHT ? State.RIGHT : State.STRAIGHT);
|
||||
|
||||
Reference in New Issue
Block a user