- implemented load callback

- added waitTime field to context, wait time now determined in route.start
This commit is contained in:
Stephan Richter
2021-03-14 19:12:17 +01:00
parent d86b6dcbcc
commit 9c86955d8d
22 changed files with 253 additions and 266 deletions

View File

@@ -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.3.67</version> <version>1.3.68</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>

View File

@@ -68,6 +68,7 @@ public abstract class BaseClass implements Constants{
private Car car; private Car car;
private Contact contact; private Contact contact;
private Direction direction; private Direction direction;
private Integer waitTime;
public Context(BaseClass object) { public Context(BaseClass object) {
setMain(object); setMain(object);
@@ -102,6 +103,7 @@ public abstract class BaseClass implements Constants{
route = null; route = null;
tile = null; tile = null;
train = null; train = null;
waitTime = null;
} }
public Context clone() { public Context clone() {
@@ -115,6 +117,7 @@ public abstract class BaseClass implements Constants{
clone.route = route; clone.route = route;
clone.tile = tile; clone.tile = tile;
clone.train = train; clone.train = train;
clone.waitTime = waitTime;
return clone; return clone;
} }
@@ -187,6 +190,7 @@ public abstract class BaseClass implements Constants{
if (isSet(block)) sb.append(", "+t("Block: {}",block)); if (isSet(block)) sb.append(", "+t("Block: {}",block));
if (isSet(route)) sb.append(", "+t("Route: {}",route)); if (isSet(route)) sb.append(", "+t("Route: {}",route));
if (isSet(contact)) sb.append(", "+t("Contact: {}",contact)); if (isSet(contact)) sb.append(", "+t("Contact: {}",contact));
if (isSet(waitTime)) sb.append(", "+t("Wait time: {} ms",waitTime));
sb.append(")"); sb.append(")");
return sb.toString(); return sb.toString();
} }
@@ -200,6 +204,14 @@ public abstract class BaseClass implements Constants{
train = newTrain; train = newTrain;
return this; return this;
} }
public Integer waitTime() {
return waitTime;
}
public void waitTime(int ms) {
waitTime = ms;
}
} }
public class FormInput extends ArrayList<Map.Entry<String, Tag>>{ public class FormInput extends ArrayList<Map.Entry<String, Tag>>{

View File

@@ -0,0 +1,18 @@
package de.srsoftware.web4rail;
import java.util.LinkedList;
public abstract class LoadCallback {
private static LinkedList<LoadCallback> callbacks = new LinkedList<LoadCallback>();
public LoadCallback() {
callbacks.add(this);
}
public abstract void afterLoad();
public static void fire() {
for (LoadCallback callback : callbacks) callback.afterLoad();
}
}

View File

@@ -513,25 +513,29 @@ public class Plan extends BaseClass{
public static void load(String name) throws IOException { public static void load(String name) throws IOException {
plan = new Plan(); plan = new Plan();
plan.name = name; plan.name = name;
try {
Car.loadAll(name+".cars",plan);
} catch (Exception e) {
LOG.warn("Was not able to load cars!",e);
}
String content = new String(Files.readAllBytes(new File(name+".plan").toPath()),UTF8); String content = new String(Files.readAllBytes(new File(name+".plan").toPath()),UTF8);
JSONObject json = new JSONObject(content); JSONObject json = new JSONObject(content);
if (json.has(TILE)) json.getJSONArray(TILE).forEach(object -> Tile.load(object, plan));
if (json.has(LENGTH_UNIT)) lengthUnit = json.getString(LENGTH_UNIT); if (json.has(LENGTH_UNIT)) lengthUnit = json.getString(LENGTH_UNIT);
if (json.has(SPEED_UNIT)) speedUnit = json.getString(SPEED_UNIT); if (json.has(SPEED_UNIT)) speedUnit = json.getString(SPEED_UNIT);
if (json.has(FINAL_SPEED)) Train.defaultEndSpeed = json.getInt(FINAL_SPEED); if (json.has(FINAL_SPEED)) Train.defaultEndSpeed = json.getInt(FINAL_SPEED);
if (json.has(FREE_BEHIND_TRAIN)) Route.freeBehindTrain = json.getBoolean(FREE_BEHIND_TRAIN); if (json.has(FREE_BEHIND_TRAIN)) Route.freeBehindTrain = json.getBoolean(FREE_BEHIND_TRAIN);
try {
Car.loadAll(name+".cars",plan);
} catch (Exception e) {
LOG.warn("Was not able to load cars!",e);
}
try { try {
Train.loadAll(name+".trains",plan); Train.loadAll(name+".trains",plan);
} catch (Exception e) { } catch (Exception e) {
LOG.warn("Was not able to load trains!",e); LOG.warn("Was not able to load trains!",e);
} }
if (json.has(TILE)) json.getJSONArray(TILE).forEach(object -> Tile.load(object, plan));
try { try {
Route.loadAll(name+".routes",plan); Route.loadAll(name+".routes",plan);
} catch (Exception e) { } catch (Exception e) {
@@ -547,6 +551,7 @@ public class Plan extends BaseClass{
} catch (Exception e) { } catch (Exception e) {
LOG.warn("Was not able to establish connection to control unit!"); LOG.warn("Was not able to establish connection to control unit!");
} }
LoadCallback.fire();
} }
/** /**

View File

@@ -790,7 +790,7 @@ public class Route extends BaseClass {
public Route simplyfyName() { public Route simplyfyName() {
String[] parts = name().split("-"); String[] parts = name().split("-");
if (parts.length>1) name(parts[0]+" - "+parts[parts.length-1]); if (parts.length>1) name(parts[0].trim()+" - "+parts[parts.length-1].trim());
return this; return this;
} }
@@ -802,6 +802,8 @@ public class Route extends BaseClass {
if (isNull(train)) return false; // can't set route's train to null if (isNull(train)) return false; // can't set route's train to null
train.setRoute(this); // set new train train.setRoute(this); // set new train
triggeredContacts.clear();
ActionList startActions = triggeredActions.get(ROUTE_START); ActionList startActions = triggeredActions.get(ROUTE_START);
if (isSet(startActions)) { if (isSet(startActions)) {
@@ -810,7 +812,7 @@ public class Route extends BaseClass {
if (!startActions.fire(context,cause)) return false; // start actions failed if (!startActions.fire(context,cause)) return false; // start actions failed
} }
triggeredContacts.clear(); context.waitTime(endBlock.getWaitTime(train, endDirection).random());
return true; return true;
} }

View File

@@ -9,11 +9,11 @@ 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.LoadCallback;
import de.srsoftware.web4rail.moving.Train; import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tags.Checkbox; import de.srsoftware.web4rail.tags.Checkbox;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.Tile;
@@ -69,19 +69,13 @@ public class AddRemoveDestination extends Action {
public Action load(JSONObject json) { public Action load(JSONObject json) {
if (json.has(TURN)) turnAtDestination = json.getBoolean(TURN); if (json.has(TURN)) turnAtDestination = json.getBoolean(TURN);
if (json.has(SHUNTING)) shunting = json.getBoolean(SHUNTING); if (json.has(SHUNTING)) shunting = json.getBoolean(SHUNTING);
if (json.has(Train.DESTINATION)) { if (json.has(Train.DESTINATION)) new LoadCallback() {
Id blockId = new Id(json.getString(Train.DESTINATION));
destination = BaseClass.get(blockId);
if (isNull(destination)) {
new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
destination = BaseClass.get(blockId); destination = BaseClass.get(Id.from(json, Train.DESTINATION));
} }
}; };
}
}
return super.load(json); return super.load(json);
} }

View File

@@ -7,9 +7,9 @@ import java.util.Map;
import org.json.JSONObject; import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass; import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.LoadCallback;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.Tile;
@@ -39,18 +39,13 @@ public class DetermineTrainInBlock extends Action {
public Action load(JSONObject json) { public Action load(JSONObject json) {
super.load(json); super.load(json);
Id blockId = Id.from(json,BLOCK); Id blockId = Id.from(json,BLOCK);
if (isSet(blockId)) { if (isSet(blockId)) new LoadCallback() {
block = Block.get(blockId);
if (isNull(block)) {
new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
block = Block.get(blockId); block = Block.get(blockId);
} }
}; };
}
}
return this; return this;
} }

View File

@@ -8,10 +8,10 @@ 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.LoadCallback;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Radio; import de.srsoftware.web4rail.tags.Radio;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Shadow; import de.srsoftware.web4rail.tiles.Shadow;
import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.Tile;
@@ -43,24 +43,15 @@ public class DisableEnableBlock extends Action {
@Override @Override
public Action load(JSONObject json) { public Action load(JSONObject json) {
super.load(json); if (json.has(STATE)) disable = !json.getBoolean(STATE);
Id blockId = Id.from(json,BLOCK); if (json.has(BLOCK)) new LoadCallback() {
if (isSet(blockId)) {
block = Block.get(blockId);
if (isNull(block)) {
new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
block = Block.get(blockId); block = Block.get(Id.from(json,BLOCK));
} }
}; };
} return super.load(json);
}
if (json.has(STATE)) {
disable = !json.getBoolean(STATE);
}
return this;
} }
@Override @Override

View File

@@ -7,9 +7,9 @@ import java.util.Map;
import org.json.JSONObject; import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass; import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.LoadCallback;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Decoupler; import de.srsoftware.web4rail.tiles.Decoupler;
import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.Tile;
@@ -24,7 +24,7 @@ public class EngageDecoupler extends Action {
private Decoupler decoupler = null; private Decoupler decoupler = null;
@Override @Override
public boolean fire(Context context,Object cause) { public boolean fire(Context context, Object cause) {
if (isNull(decoupler)) return false; if (isNull(decoupler)) return false;
decoupler.engage(); decoupler.engage();
return true; return true;
@@ -41,26 +41,20 @@ public class EngageDecoupler extends Action {
@Override @Override
public Action load(JSONObject json) { public Action load(JSONObject json) {
super.load(json); if (json.has(DECOUPLER)) new LoadCallback() {
if (json.has(DECOUPLER)) {
String decouplerId = json.getString(DECOUPLER);
decoupler = BaseClass.get(new Id(decouplerId));
if (isNull(decoupler)) new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
decoupler = BaseClass.get(new Id(decouplerId)); decoupler = BaseClass.get(Id.from(json, DECOUPLER));
} }
}; };
} return super.load(json);
return this;
} }
@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("Decoupler")+": "+(isNull(decoupler) ? t("unset") : decoupler),button(t("Select from plan"),Map.of(ACTION,ACTION_UPDATE,ASSIGN,DECOUPLER))); formInputs.add(t("Decoupler") + ": " + (isNull(decoupler) ? t("unset") : decoupler), button(t("Select from plan"), Map.of(ACTION, ACTION_UPDATE, ASSIGN, DECOUPLER)));
return super.properties(preForm, formInputs, postForm,errors); return super.properties(preForm, formInputs, postForm, errors);
} }
@Override @Override
@@ -70,18 +64,18 @@ public class EngageDecoupler extends Action {
} }
public String toString() { public String toString() {
if (isNull(decoupler)) return "["+t("Click here to setup decoupler")+"]"; if (isNull(decoupler)) return "[" + t("Click here to setup decoupler") + "]";
return t("Engage {}",decoupler); return t("Engage {}", decoupler);
}; };
@Override @Override
protected Object update(HashMap<String, String> params) { protected Object update(HashMap<String, String> params) {
LOG.debug("update: {}",params); LOG.debug("update: {}", params);
if (params.containsKey(DECOUPLER)) { if (params.containsKey(DECOUPLER)) {
Tile tile = BaseClass.get(new Id(params.get(DECOUPLER))); Tile tile = BaseClass.get(new Id(params.get(DECOUPLER)));
if (tile instanceof Decoupler) { if (tile instanceof Decoupler) {
decoupler = (Decoupler) tile; decoupler = (Decoupler) tile;
} else return t("Clicked tile is not a {}!",t("decoupler")); } else return t("Clicked tile is not a {}!", t("decoupler"));
} }
return context().properties(); return context().properties();
} }

View File

@@ -1,7 +1,6 @@
package de.srsoftware.web4rail.actions; package de.srsoftware.web4rail.actions;
import de.srsoftware.web4rail.BaseClass; import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Range;
import de.srsoftware.web4rail.Route; import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.moving.Train; import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.Block;
@@ -25,10 +24,10 @@ public class PreserveRoute extends Action {
Block endBlock = route.endBlock(); Block endBlock = route.endBlock();
if (train.destination() == endBlock) return true; // do not reserve routes, when destination has been reached if (train.destination() == endBlock) return true; // do not reserve routes, when destination has been reached
Range waitTime = endBlock.getWaitTime(train,route.endDirection); Integer waitTime = context.waitTime();
if (waitTime.max > 0) { if (isSet(waitTime) && waitTime > 0) {
LOG.debug("Not preserving route, as train needs to stop for {} ms at {}!",waitTime,endBlock); LOG.debug("Not preserving route, as train needs to stop for {} ms at {}!",waitTime,endBlock);
return true; // train is expected to wait in next block. return false; // train is expected to wait in next block.
} }
train.reserveNext(); train.reserveNext();

View File

@@ -6,10 +6,10 @@ import java.util.List;
import org.json.JSONObject; import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass; import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.LoadCallback;
import de.srsoftware.web4rail.moving.Train; import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
public class SetContextTrain extends Action { public class SetContextTrain extends Action {
@@ -34,21 +34,13 @@ public class SetContextTrain extends Action {
@Override @Override
public Action load(JSONObject json) { public Action load(JSONObject json) {
super.load(json); if (json.has(REALM_TRAIN)) new LoadCallback() {
if (json.has(REALM_TRAIN)) {
Id trainId = Id.from(json,REALM_TRAIN);
if (isSet(trainId)) {
train = Train.get(trainId);
if (isNull(train)) new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
train = Train.get(trainId); train = Train.get(Id.from(json,REALM_TRAIN));
} }
}; };
} return super.load(json);
}
return this;
} }
@Override @Override

View File

@@ -7,10 +7,10 @@ import java.util.Map;
import org.json.JSONObject; import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass; import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.LoadCallback;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Label; import de.srsoftware.web4rail.tags.Label;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.TextDisplay; import de.srsoftware.web4rail.tiles.TextDisplay;
import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.Tile;
@@ -43,15 +43,12 @@ public class SetDisplayText extends TextAction{
@Override @Override
public Action load(JSONObject json) { public Action load(JSONObject json) {
if (json.has(DISPLAY)) { if (json.has(DISPLAY)) new LoadCallback() {
new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
display = (TextDisplay) plan.get(Id.from(json,DISPLAY), false); display = (TextDisplay) plan.get(Id.from(json,DISPLAY), false);
};
};
} }
};
return super.load(json); return super.load(json);
} }

View File

@@ -8,10 +8,10 @@ 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.LoadCallback;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Select; import de.srsoftware.web4rail.tags.Select;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Relay; import de.srsoftware.web4rail.tiles.Relay;
import de.srsoftware.web4rail.tiles.Switch; import de.srsoftware.web4rail.tiles.Switch;
import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.Tile;
@@ -51,31 +51,23 @@ public class SetRelayOrSwitch extends Action {
@Override @Override
public Action load(JSONObject json) { public Action load(JSONObject json) {
super.load(json);
if (json.has(RELAY)) {
String relayId = json.getString(RELAY);
relayOrSwitch = BaseClass.get(new Id(relayId));
if (isNull(relayOrSwitch)) new DelayedExecution(this) {
@Override
public void execute() {
relayOrSwitch = BaseClass.get(new Id(relayId));
};
};
}
if (json.has(SWITCH)) {
String relayId = json.getString(SWITCH);
relayOrSwitch = BaseClass.get(new Id(relayId));
if (isNull(relayOrSwitch)) new DelayedExecution(this) {
@Override
public void execute() {
relayOrSwitch = BaseClass.get(new Id(relayId));
}
};
}
if (json.has(STATE)) state = json.getBoolean(STATE); if (json.has(STATE)) state = json.getBoolean(STATE);
return this;
if (json.has(RELAY)) new LoadCallback() {
@Override
public void afterLoad() {
relayOrSwitch = BaseClass.get(Id.from(json, RELAY));
};
};
if (json.has(SWITCH)) new LoadCallback() {
@Override
public void afterLoad() {
relayOrSwitch = BaseClass.get(Id.from(json, SWITCH));
};
};
return super.load(json);
} }
@Override @Override

View File

@@ -8,10 +8,10 @@ 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.LoadCallback;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Select; import de.srsoftware.web4rail.tags.Select;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Turnout; import de.srsoftware.web4rail.tiles.Turnout;
import de.srsoftware.web4rail.tiles.Turnout.State; import de.srsoftware.web4rail.tiles.Turnout.State;
@@ -49,20 +49,15 @@ public class SetTurnout extends Action {
@Override @Override
public Action load(JSONObject json) { public Action load(JSONObject json) {
super.load(json); if (json.has(Turnout.STATE)) state = Turnout.State.valueOf(json.getString(Turnout.STATE));
Id turnoutId = json.has(TURNOUT) ? new Id(json.getString(TURNOUT)) : null; if (json.has(TURNOUT)) new LoadCallback() {
if (isSet(turnoutId)) {
turnout = BaseClass.get(turnoutId);
if (isNull(turnout)) new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
turnout = BaseClass.get(turnoutId); turnout = BaseClass.get(Id.from(json, TURNOUT));
} }
}; };
} return super.load(json);
if (json.has(Turnout.STATE)) state = Turnout.State.valueOf(json.getString(Turnout.STATE));
return this;
} }
@Override @Override

View File

@@ -8,6 +8,7 @@ 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.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;
@@ -82,19 +83,16 @@ public class WaitForContact extends ActionList {
@Override @Override
public Action load(JSONObject json) { public Action load(JSONObject json) {
if (json.has(CONTACT)) {
String cid = json.getString(CONTACT);
contact = BaseClass.get(new Id(cid));
if (isNull(contact)) new DelayedExecution(this) {
@Override
public void execute() {
contact = BaseClass.get(new Id(cid));
}
};
}
if (json.has(TIMEOUT)) timeout = json.getInt(TIMEOUT); if (json.has(TIMEOUT)) timeout = json.getInt(TIMEOUT);
if (json.has(TIMEOUT_ACTIONS)) timeoutActions.load(json.getJSONObject(TIMEOUT_ACTIONS)); if (json.has(TIMEOUT_ACTIONS)) timeoutActions.load(json.getJSONObject(TIMEOUT_ACTIONS));
if (json.has(CONTACT)) new LoadCallback() {
@Override
public void afterLoad() {
contact = BaseClass.get(Id.from(json, CONTACT));
}
};
return super.load(json); return super.load(json);
} }

View File

@@ -7,9 +7,9 @@ import java.util.Map;
import org.json.JSONObject; import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass; import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.LoadCallback;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.Tile;
@@ -34,20 +34,13 @@ public class BlockFree extends Condition {
} }
public Condition load(JSONObject json) { public Condition load(JSONObject json) {
super.load(json); if (json.has(BLOCK)) new LoadCallback() {
if (json.has(BLOCK)) {
Id bid = new Id(json.getString(BLOCK));
block(BaseClass.get(bid));
if (isNull(block)) {
new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
block(BaseClass.get(bid)); block(BaseClass.get(Id.from(json, BLOCK)));
} }
}; };
} return super.load(json);
}
return this;
} }
@Override @Override

View File

@@ -7,10 +7,10 @@ import java.util.Map;
import org.json.JSONObject; import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass; import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.LoadCallback;
import de.srsoftware.web4rail.Route; import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.Tile;
@@ -38,22 +38,15 @@ public class RouteEndBlock extends Condition{
} }
public Condition load(JSONObject json) { public Condition load(JSONObject json) {
super.load(json); new LoadCallback() {
Id bid = new Id(json.getString(BLOCK));
Block block = BaseClass.get(bid);
if (isSet(block)) {
block(block);
} else {
new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
block(BaseClass.get(bid)); block(BaseClass.get(Id.from(json, BLOCK)));
} }
}; };
}
return this; return super.load(json);
} }
@Override @Override

View File

@@ -8,10 +8,10 @@ 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.LoadCallback;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Radio; import de.srsoftware.web4rail.tags.Radio;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
import de.srsoftware.web4rail.tiles.Switch; import de.srsoftware.web4rail.tiles.Switch;
import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.Tile;
@@ -44,20 +44,13 @@ public class SwitchIsOn extends Condition {
} }
public Condition load(JSONObject json) { public Condition load(JSONObject json) {
super.load(json); if (json.has(SWITCH)) new LoadCallback() {
if (json.has(SWITCH)) {
swtch = BaseClass.get(new Id(json.getString(SWITCH)));
if (isNull(swtch)) {
new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
swtch = BaseClass.get(new Id(json.getString(SWITCH))); swtch = BaseClass.get(Id.from(json,SWITCH));
} }
}; };
} return super.load(json);
}
return this;
} }
@Override @Override

View File

@@ -23,6 +23,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.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;
@@ -514,18 +515,23 @@ public class Train extends BaseClass implements Comparable<Train> {
if (json.has(DIRECTION)) direction = Direction.valueOf(json.getString(DIRECTION)); if (json.has(DIRECTION)) direction = Direction.valueOf(json.getString(DIRECTION));
if (json.has(NAME)) name = json.getString(NAME); if (json.has(NAME)) name = json.getString(NAME);
if (json.has(TAGS)) json.getJSONArray(TAGS ).forEach(elem -> { tags.add(elem.toString()); }); if (json.has(TAGS)) json.getJSONArray(TAGS ).forEach(elem -> { tags.add(elem.toString()); });
if (json.has(TRACE)) json.getJSONArray(TRACE).forEach(elem -> {
Tile tile = plan.get(new Id(elem.toString()), false);
if (tile.setTrain(this)) trace.add(tile);
});
if (json.has(BLOCK)) {// do not move this up! during set, other fields will be referenced!
currentBlock = (Block) plan.get(new Id(json.getString(BLOCK)), false);
currentBlock.add(this, direction);
}
if (json.has(LOCOS)) { // for downward compatibility if (json.has(LOCOS)) { // for downward compatibility
for (Object id : json.getJSONArray(LOCOS)) add(BaseClass.get(new Id(""+id))); for (Object id : json.getJSONArray(LOCOS)) add(BaseClass.get(new Id(""+id)));
} }
for (Object id : json.getJSONArray(CARS)) add(BaseClass.get(new Id(""+id))); for (Object id : json.getJSONArray(CARS)) add(BaseClass.get(new Id(""+id)));
new LoadCallback() {
@Override
public void afterLoad() {
if (json.has(TRACE)) json.getJSONArray(TRACE).forEach(elem -> {
Tile tile = plan.get(new Id(elem.toString()), false);
if (tile.setTrain(Train.this)) trace.add(tile);
});
if (json.has(BLOCK)) {// do not move this up! during set, other fields will be referenced!
currentBlock = (Block) plan.get(Id.from(json, BLOCK), false);
if (isSet(currentBlock)) currentBlock.add(Train.this, direction);
}
}
};
super.load(json); super.load(json);
return this; return this;
} }
@@ -853,7 +859,7 @@ public class Train extends BaseClass implements Comparable<Train> {
public String start(boolean auto) { public String start(boolean auto) {
if (isNull(routeManager)) routeManager = new RouteManager(this); if (isNull(routeManager)) routeManager = new RouteManager(this);
routeManager.setAuto(auto); routeManager.setAuto(auto).start();
plan.stream(t("Started {}",this)); plan.stream(t("Started {}",this));
return null; return null;
} }

View File

@@ -31,9 +31,6 @@ public class RouteManager extends BaseClass implements Runnable {
public RouteManager(Train train) { public RouteManager(Train train) {
context = new Context(train); context = new Context(train);
state = State.STARTED; state = State.STARTED;
Thread thread = new Thread(this);
thread.setName(train.name());
thread.start();
} }
private static TreeMap<Integer,List<Route>> availableRoutes(Context context,HashSet<Route> visitedRoutes){ private static TreeMap<Integer,List<Route>> availableRoutes(Context context,HashSet<Route> visitedRoutes){
@@ -61,7 +58,7 @@ public class RouteManager extends BaseClass implements Runnable {
if (isSet(destination) && visitedRoutes.isEmpty()) LOG.debug("{}- Destination: {}",inset,destination); if (isSet(destination) && visitedRoutes.isEmpty()) LOG.debug("{}- Destination: {}",inset,destination);
for (Route routeCandidate : block.routes(startDirection)) { for (Route routeCandidate : block.leavingRoutes()) {
if (context.invalidated()) return availableRoutes; if (context.invalidated()) return availableRoutes;
if (visitedRoutes.contains(routeCandidate)) { if (visitedRoutes.contains(routeCandidate)) {
LOG.debug("{}→ Candidate {} would create loop, skipping",inset,routeCandidate.shortName()); LOG.debug("{}→ Candidate {} would create loop, skipping",inset,routeCandidate.shortName());
@@ -179,6 +176,7 @@ public class RouteManager extends BaseClass implements Runnable {
try { try {
do { do {
pause(); pause();
if (isSet(train.route())) continue;
if (context.invalidated()) return; if (context.invalidated()) return;
context.block(train.currentBlock()).direction(train.direction()); context.block(train.currentBlock()).direction(train.direction());
Route route = chooseRoute(context); Route route = chooseRoute(context);
@@ -205,8 +203,15 @@ public class RouteManager extends BaseClass implements Runnable {
} }
} }
public void setAuto(boolean auto) { public RouteManager setAuto(boolean auto) {
LOG.debug("{}abled autopilot of {}",auto?"En":"Dis"); LOG.debug("{}abled autopilot of {}",auto?"En":"Dis");
autopilot = auto; autopilot = auto;
return this;
}
public void start() {
Thread thread = new Thread(this);
thread.setName(context.train().name());
thread.start();
} }
} }

View File

@@ -20,6 +20,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.Direction; import de.srsoftware.web4rail.Plan.Direction;
import de.srsoftware.web4rail.Range; import de.srsoftware.web4rail.Range;
import de.srsoftware.web4rail.Route; import de.srsoftware.web4rail.Route;
@@ -99,7 +100,7 @@ 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 = "parked_trains"; private static final String TRAINS = "trains";
public String name = "Block"; public String name = "Block";
public boolean turnAllowed = false; public boolean turnAllowed = false;
@@ -202,15 +203,6 @@ public abstract class Block extends StretchableTile{
return t("Trigger contact to learn new contact"); return t("Trigger contact to learn new contact");
} }
@Override
public boolean isFreeFor(Context context) {
Train train = context.train();
if (is(Status.DISABLED)) return false;
if (trains.isEmpty()) return true;
if (trains.first() == train) return true;
return train.isShunting(); // block contains train(s), thus it is only free for shunting train
}
@Override @Override
public Object click(boolean shift) throws IOException { public Object click(boolean shift) throws IOException {
if (!trains.isEmpty() && !shift) return trains.first().properties(); if (!trains.isEmpty() && !shift) return trains.first().properties();
@@ -309,6 +301,15 @@ public abstract class Block extends StretchableTile{
return 1+internalContacts.indexOf(contact); return 1+internalContacts.indexOf(contact);
} }
@Override
public boolean isFreeFor(Context context) {
Train train = context.train();
if (is(Status.DISABLED)) return false;
if (trains.isEmpty()) return true;
if (trains.first() == train) return true;
return train.isShunting(); // block contains train(s), thus it is only free for shunting train
}
@Override @Override
public JSONObject json() { public JSONObject json() {
JSONObject json = super.json(); JSONObject json = super.json();
@@ -325,12 +326,17 @@ 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
if (!trains.isEmpty()) { if (!trains.isEmpty()) {
JSONArray ptids = new JSONArray(); JSONArray jTrains = new JSONArray();
for (Train parked : trains) { for (Train train : trains) {
if (isSet(parked)) ptids.put(parked.id().toString()); JSONObject to = new JSONObject();
to.put(ID, train.id());
Direction dir = trains.directionOf(train);
if (isSet(dir)) to.put(DIRECTION, dir.toString());
jTrains.put(to);
} }
json.put(PARKED_TRAINS, ptids); json.put(TRAINS, jTrains);
} }
return json; return json;
} }
@@ -339,6 +345,10 @@ public abstract class Block extends StretchableTile{
return trains.last(); return trains.last();
} }
public List<Route> leavingRoutes() {
return routes().stream().filter(route -> route.startBlock() == Block.this).collect(Collectors.toList());
}
/** /**
* If arguments are given, the first is taken as content, the second as tag type. * If arguments are given, the first is taken as content, the second as tag type.
@@ -372,24 +382,33 @@ public abstract class Block extends StretchableTile{
} catch (JSONException e) {} } catch (JSONException e) {}
} }
} }
new LoadCallback() {
@Override
public void afterLoad() {
if (json.has(TRAINS)) { if (json.has(TRAINS)) {
JSONArray jTrains = json.getJSONArray(TRAINS); JSONArray jTrains = json.getJSONArray(TRAINS);
for (Object o : jTrains) { for (Object o : jTrains) {
if (o instanceof JSONObject) { if (o instanceof JSONObject) {
JSONObject to = (JSONObject) o; JSONObject to = (JSONObject) o;
Train train = BaseClass.get(new Id(to.getString(ID))); Id tID = new Id(to.getString(ID));
Train train = BaseClass.get(tID);
Direction direction = to.has(DIRECTION) ? Direction.valueOf(to.getString(DIRECTION)) : null; Direction direction = to.has(DIRECTION) ? Direction.valueOf(to.getString(DIRECTION)) : null;
if (isSet(train)) trains.add(train, direction); if (isSet(train)) {
trains.add(train, direction);
train.set(Block.this);
} }
} }
} }
if (json.has(PARKED_TRAINS)) { // legacy } else if (json.has(PARKED_TRAINS)) { // legacy
JSONArray ptids = json.getJSONArray(PARKED_TRAINS); for (Object id : json.getJSONArray(PARKED_TRAINS)) {
for (Object id : ptids) {
Train train = BaseClass.get(new Id(id.toString())); Train train = BaseClass.get(new Id(id.toString()));
if (isSet(train)) trains.add(train,null); if (isSet(train)) trains.add(train,null);
} }
} }
}
};
return super.load(json); return super.load(json);
} }
@@ -485,10 +504,6 @@ public abstract class Block extends StretchableTile{
internalContacts.remove(blockContact); internalContacts.remove(blockContact);
} }
public List<Route> routes(Direction direction) {
return routes().stream().filter(route -> route.startBlock() == Block.this).collect(Collectors.toList());
}
public void set(Train train, Direction direction) { public void set(Train train, Direction direction) {
trains.set(train,direction); trains.set(train,direction);
} }

View File

@@ -9,10 +9,10 @@ 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.Connector; import de.srsoftware.web4rail.Connector;
import de.srsoftware.web4rail.LoadCallback;
import de.srsoftware.web4rail.moving.Train; import de.srsoftware.web4rail.moving.Train;
import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.DelayedExecution;
public abstract class Bridge extends Tile { public abstract class Bridge extends Tile {
private static final String COUNTERPART = "counterpart"; private static final String COUNTERPART = "counterpart";
@@ -56,14 +56,12 @@ public abstract class Bridge extends Tile {
@Override @Override
public Tile load(JSONObject json) { public Tile load(JSONObject json) {
if (json.has(COUNTERPART)) { if (json.has(COUNTERPART)) new LoadCallback() {
new DelayedExecution(this) {
@Override @Override
public void execute() { public void afterLoad() {
counterpart = (Bridge) plan.get(Id.from(json, COUNTERPART), false); counterpart = (Bridge) plan.get(Id.from(json, COUNTERPART), false);
} }
}; };
}
return super.load(json); return super.load(json);
} }