bugfixes
This commit is contained in:
2
pom.xml
2
pom.xml
@@ -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.2.26</version>
|
<version>1.2.27</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>
|
||||||
|
|||||||
@@ -87,17 +87,30 @@ public abstract class BaseClass implements Constants{
|
|||||||
return car;
|
return car;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
action = null;
|
||||||
|
block = null;
|
||||||
|
car = null;
|
||||||
|
condition = null;
|
||||||
|
contact = null;
|
||||||
|
direction = null;
|
||||||
|
main = null;
|
||||||
|
route = null;
|
||||||
|
tile = null;
|
||||||
|
train = null;
|
||||||
|
}
|
||||||
|
|
||||||
public Context clone() {
|
public Context clone() {
|
||||||
Context clone = new Context(main);
|
Context clone = new Context(main);
|
||||||
clone.tile = tile;
|
|
||||||
clone.block = block;
|
|
||||||
clone.train = train;
|
|
||||||
clone.route = route;
|
|
||||||
clone.action = action;
|
clone.action = action;
|
||||||
clone.condition = condition;
|
clone.block = block;
|
||||||
clone.car = car;
|
clone.car = car;
|
||||||
|
clone.condition = condition;
|
||||||
clone.contact = contact;
|
clone.contact = contact;
|
||||||
clone.direction = direction;
|
clone.direction = direction;
|
||||||
|
clone.route = route;
|
||||||
|
clone.tile = tile;
|
||||||
|
clone.train = train;
|
||||||
return clone;
|
return clone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +122,11 @@ public abstract class BaseClass implements Constants{
|
|||||||
return contact;
|
return contact;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void contact(Contact newContact) {
|
||||||
|
contact = newContact;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Direction direction() {
|
public Direction direction() {
|
||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
@@ -117,6 +135,11 @@ public abstract class BaseClass implements Constants{
|
|||||||
direction = newDirection;
|
direction = newDirection;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean invalidated() {
|
||||||
|
return isNull(main);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Route route() {
|
public Route route() {
|
||||||
return route;
|
return route;
|
||||||
@@ -376,11 +399,11 @@ public abstract class BaseClass implements Constants{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public String realm() {
|
public String realm() {
|
||||||
if (this instanceof Tile) return REALM_PLAN;
|
|
||||||
if (this instanceof Contact) return REALM_CONTACT;
|
if (this instanceof Contact) return REALM_CONTACT;
|
||||||
|
if (this instanceof Tile) return REALM_PLAN;
|
||||||
|
|
||||||
if (this instanceof Car) return REALM_CAR;
|
|
||||||
if (this instanceof Locomotive) return REALM_LOCO;
|
if (this instanceof Locomotive) return REALM_LOCO;
|
||||||
|
if (this instanceof Car) return REALM_CAR;
|
||||||
|
|
||||||
if (this instanceof Action) return REALM_ACTIONS;
|
if (this instanceof Action) return REALM_ACTIONS;
|
||||||
if (this instanceof Condition) return REALM_CONDITION;
|
if (this instanceof Condition) return REALM_CONDITION;
|
||||||
|
|||||||
@@ -251,9 +251,6 @@ public class Plan extends BaseClass{
|
|||||||
List<Route> oldRoutes = BaseClass.listElements(Route.class);
|
List<Route> oldRoutes = BaseClass.listElements(Route.class);
|
||||||
Vector<Route> newRoutes = new Vector<Route>();
|
Vector<Route> newRoutes = new Vector<Route>();
|
||||||
for (Block block : BaseClass.listElements(Block.class)) {
|
for (Block block : BaseClass.listElements(Block.class)) {
|
||||||
if (block.name.equals("Huhu")) {
|
|
||||||
System.err.println("Here we go!");
|
|
||||||
}
|
|
||||||
for (Connector con : block.startPoints()) {
|
for (Connector con : block.startPoints()) {
|
||||||
newRoutes.addAll(follow(new Route().begin(block,con.from.inverse()),con));
|
newRoutes.addAll(follow(new Route().begin(block,con.from.inverse()),con));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ import de.srsoftware.web4rail.tiles.Turnout;
|
|||||||
* @author Stephan Richter, SRSoftware
|
* @author Stephan Richter, SRSoftware
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Route extends BaseClass implements Comparable<Route>{
|
public class Route extends BaseClass {
|
||||||
|
|
||||||
public enum State {
|
public enum State {
|
||||||
FREE, LOCKED, PREPARED, STARTED;
|
FREE, LOCKED, PREPARED, STARTED;
|
||||||
@@ -106,7 +106,6 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
public void finish() {
|
public void finish() {
|
||||||
long timestamp2 = new Date().getTime();
|
long timestamp2 = new Date().getTime();
|
||||||
//int remainingSpeed = train.speed;
|
//int remainingSpeed = train.speed;
|
||||||
train.setSpeed(0);
|
|
||||||
if (aborted) return;
|
if (aborted) return;
|
||||||
long runtime = timestamp2 - timestamp;
|
long runtime = timestamp2 - timestamp;
|
||||||
int quotient = startSpeed - ENDSPEED;
|
int quotient = startSpeed - ENDSPEED;
|
||||||
@@ -144,6 +143,7 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
private HashMap<String,Integer> brakeTimes = new HashMap<String, Integer>();
|
private HashMap<String,Integer> brakeTimes = new HashMap<String, Integer>();
|
||||||
private ConditionList conditions;
|
private ConditionList conditions;
|
||||||
private Vector<Contact> contacts;
|
private Vector<Contact> contacts;
|
||||||
|
private Context context; // this context is passed to actions
|
||||||
private boolean disabled = false;
|
private boolean disabled = false;
|
||||||
private Block endBlock = null;
|
private Block endBlock = null;
|
||||||
public Direction endDirection;
|
public Direction endDirection;
|
||||||
@@ -222,6 +222,46 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
conditions.add(condition);
|
conditions.add(condition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addPropertiesFrom(Route existingRoute) {
|
||||||
|
LOG.debug("addPropertiesFrom({})",existingRoute);
|
||||||
|
disabled = existingRoute.disabled;
|
||||||
|
|
||||||
|
for (Condition condition : existingRoute.conditions) { // bestehende Bedingungen der neuen zuweisen
|
||||||
|
condition.parent(this);
|
||||||
|
conditions.add(condition);
|
||||||
|
}
|
||||||
|
conditions.forEach(condition -> existingRoute.conditions.removeChild(condition));
|
||||||
|
|
||||||
|
for (Entry<String, ActionList> entry : triggeredActions.entrySet()) {
|
||||||
|
String trigger = entry.getKey();
|
||||||
|
ActionList existingActionList = existingRoute.triggeredActions.get(trigger);
|
||||||
|
if (isSet(existingActionList)) {
|
||||||
|
LOG.debug("found action list for {} on existing route {}: {}",trigger,existingRoute,existingActionList);
|
||||||
|
existingActionList.forEach(action -> LOG.debug("OLD Action: {}",action));
|
||||||
|
entry.getValue().merge(existingActionList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
brakeTimes = new HashMap<String, Integer>(existingRoute.brakeTimes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addSignal(Signal signal) {
|
||||||
|
signals.add(signal);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addTurnout(Turnout t, Turnout.State s) {
|
||||||
|
turnouts.put(t, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* checks, whether the route may be used in a given context
|
||||||
|
* @param context
|
||||||
|
* @return false, if any of the associated conditions is not fulfilled
|
||||||
|
*/
|
||||||
|
public boolean allowed(Context context) {
|
||||||
|
if (disabled) return false;
|
||||||
|
return conditions.fulfilledBy(context);
|
||||||
|
}
|
||||||
|
|
||||||
private Fieldset basicProperties() {
|
private Fieldset basicProperties() {
|
||||||
Fieldset fieldset = new Fieldset(t("Route properties"));
|
Fieldset fieldset = new Fieldset(t("Route properties"));
|
||||||
|
|
||||||
@@ -253,7 +293,86 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
new Tag("p").content(t("1) Duration between 5 {} steps during brake process.",speedUnit)).addTo(fieldset);
|
new Tag("p").content(t("1) Duration between 5 {} steps during brake process.",speedUnit)).addTo(fieldset);
|
||||||
return fieldset;
|
return fieldset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Route begin(Block block,Direction to) {
|
||||||
|
// add those fields to clone, too!
|
||||||
|
contacts = new Vector<Contact>();
|
||||||
|
signals = new Vector<Signal>();
|
||||||
|
path = new Vector<Tile>();
|
||||||
|
turnouts = new HashMap<>();
|
||||||
|
startBlock = block;
|
||||||
|
startDirection = to;
|
||||||
|
path.add(block);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void brakeCancel() {
|
||||||
|
if (isSet(brakeProcessor)) brakeProcessor.abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void brakeStart() {
|
||||||
|
if (isNull(train)) return;
|
||||||
|
brakeProcessor = new BrakeProcessor(this,train);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void brakeStop() {
|
||||||
|
train.setSpeed(0);
|
||||||
|
if (isSet(brakeProcessor)) brakeProcessor.finish();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Route clone() {
|
||||||
|
Route clone = new Route();
|
||||||
|
clone.startBlock = startBlock;
|
||||||
|
clone.startDirection = startDirection;
|
||||||
|
clone.endBlock = endBlock;
|
||||||
|
clone.endDirection = endDirection;
|
||||||
|
clone.contacts = new Vector<Contact>(contacts);
|
||||||
|
clone.signals = new Vector<Signal>(signals);
|
||||||
|
clone.turnouts = new HashMap<>(turnouts);
|
||||||
|
clone.path = new Vector<>(path);
|
||||||
|
clone.brakeTimes = new HashMap<String, Integer>(brakeTimes);
|
||||||
|
return clone;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Route complete() {
|
||||||
|
if (contacts.size()>1) { // mindestens 2 Kontakte: erster Kontakt aktiviert Block, vorletzter Kontakt leitet Bremsung ein
|
||||||
|
Contact nextToLastContact = contacts.get(contacts.size()-2);
|
||||||
|
String trigger = nextToLastContact.trigger();
|
||||||
|
add(trigger,new BrakeStart(this));
|
||||||
|
add(trigger,new PreserveRoute(this));
|
||||||
|
for (Signal signal : signals) add(trigger,new SetSignal(this).set(signal).to(Signal.STOP));
|
||||||
|
}
|
||||||
|
if (!contacts.isEmpty()) {
|
||||||
|
Contact lastContact = contacts.lastElement();
|
||||||
|
add(lastContact.trigger(), new BrakeStop(this));
|
||||||
|
add(lastContact.trigger(), new FinishRoute(this));
|
||||||
|
}
|
||||||
|
for (Signal signal : signals) add(ROUTE_SETUP,new SetSignal(this).set(signal).to(Signal.GO));
|
||||||
|
add(ROUTE_START,new SetSpeed(this).to(999));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kontakt der Route aktivieren
|
||||||
|
* @param contact
|
||||||
|
* @param trainHead
|
||||||
|
*/
|
||||||
|
public void contact(Contact contact) {
|
||||||
|
if (triggeredContacts.contains(contact)) return; // don't trigger contact a second time
|
||||||
|
triggeredContacts.add(contact);
|
||||||
|
LOG.debug("{} on {} activated {}.",train,this,contact);
|
||||||
|
traceTrainFrom(contact);
|
||||||
|
ActionList actions = triggeredActions.get(contact.trigger());
|
||||||
|
LOG.debug("Contact has id {} / trigger {} and is assigned with {}",contact.id(),contact.trigger(),actions);
|
||||||
|
if (isNull(actions)) return;
|
||||||
|
context.contact(contact);
|
||||||
|
actions.fire(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Vector<Contact> contacts() {
|
||||||
|
return new Vector<>(contacts);
|
||||||
|
}
|
||||||
|
|
||||||
private Fieldset contactsAndActions() {
|
private Fieldset contactsAndActions() {
|
||||||
Fieldset win = new Fieldset(t("Actions and contacts"));
|
Fieldset win = new Fieldset(t("Actions and contacts"));
|
||||||
Tag list = new Tag("ol");
|
Tag list = new Tag("ol");
|
||||||
@@ -287,152 +406,12 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
return win;
|
return win;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addPropertiesFrom(Route existingRoute) {
|
|
||||||
LOG.debug("addPropertiesFrom({})",existingRoute);
|
|
||||||
disabled = existingRoute.disabled;
|
|
||||||
|
|
||||||
for (Condition condition : existingRoute.conditions) { // bestehende Bedingungen der neuen zuweisen
|
|
||||||
condition.parent(this);
|
|
||||||
conditions.add(condition);
|
|
||||||
}
|
|
||||||
conditions.forEach(condition -> existingRoute.conditions.removeChild(condition));
|
|
||||||
|
|
||||||
for (Entry<String, ActionList> entry : triggeredActions.entrySet()) {
|
|
||||||
String trigger = entry.getKey();
|
|
||||||
ActionList existingActionList = existingRoute.triggeredActions.get(trigger);
|
|
||||||
if (isSet(existingActionList)) {
|
|
||||||
LOG.debug("found action list for {} on existing route {}: {}",trigger,existingRoute,existingActionList);
|
|
||||||
ActionList newActionList = entry.getValue();
|
|
||||||
newActionList.addActionsFrom(existingActionList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
brakeTimes = new HashMap<String, Integer>(existingRoute.brakeTimes);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addSignal(Signal signal) {
|
|
||||||
signals.add(signal);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addTurnout(Turnout t, Turnout.State s) {
|
|
||||||
turnouts.put(t, s);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Fieldset turnouts() {
|
|
||||||
Fieldset win = new Fieldset(t("Turnouts"));
|
|
||||||
Tag list = new Tag("ul");
|
|
||||||
for (Entry<Turnout, Turnout.State> entry : turnouts.entrySet()) {
|
|
||||||
Turnout turnout = entry.getKey();
|
|
||||||
Plan.addLink(turnout, turnout+": "+t(entry.getValue().toString()), list);
|
|
||||||
}
|
|
||||||
list.addTo(win);
|
|
||||||
return win;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* checks, whether the route may be used in a given context
|
|
||||||
* @param context
|
|
||||||
* @return false, if any of the associated conditions is not fulfilled
|
|
||||||
*/
|
|
||||||
public boolean allowed(Context context) {
|
|
||||||
if (disabled) return false;
|
|
||||||
return conditions.fulfilledBy(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Route begin(Block block,Direction to) {
|
|
||||||
// add those fields to clone, too!
|
|
||||||
contacts = new Vector<Contact>();
|
|
||||||
signals = new Vector<Signal>();
|
|
||||||
path = new Vector<Tile>();
|
|
||||||
turnouts = new HashMap<>();
|
|
||||||
startBlock = block;
|
|
||||||
startDirection = to;
|
|
||||||
path.add(block);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void brakeCancel() {
|
|
||||||
if (isSet(brakeProcessor)) brakeProcessor.abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void brakeStart() {
|
|
||||||
if (isNull(train)) return;
|
|
||||||
brakeProcessor = new BrakeProcessor(this,train);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void brakeStop() {
|
|
||||||
if (isSet(brakeProcessor)) brakeProcessor.finish();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Route clone() {
|
|
||||||
Route clone = new Route();
|
|
||||||
clone.startBlock = startBlock;
|
|
||||||
clone.startDirection = startDirection;
|
|
||||||
clone.endBlock = endBlock;
|
|
||||||
clone.endDirection = endDirection;
|
|
||||||
clone.contacts = new Vector<Contact>(contacts);
|
|
||||||
clone.signals = new Vector<Signal>(signals);
|
|
||||||
clone.turnouts = new HashMap<>(turnouts);
|
|
||||||
clone.path = new Vector<>(path);
|
|
||||||
clone.brakeTimes = new HashMap<String, Integer>(brakeTimes);
|
|
||||||
return clone;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int compareTo(Route other) {
|
|
||||||
return name().compareTo(other.name());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Route complete() {
|
|
||||||
if (contacts.size()>1) { // mindestens 2 Kontakte: erster Kontakt aktiviert Block, vorletzter Kontakt leitet Bremsung ein
|
|
||||||
Contact nextToLastContact = contacts.get(contacts.size()-2);
|
|
||||||
String trigger = nextToLastContact.trigger();
|
|
||||||
add(trigger,new BrakeStart(this));
|
|
||||||
add(trigger,new PreserveRoute(this));
|
|
||||||
for (Signal signal : signals) add(trigger,new SetSignal(this).set(signal).to(Signal.STOP));
|
|
||||||
}
|
|
||||||
if (!contacts.isEmpty()) {
|
|
||||||
Contact lastContact = contacts.lastElement();
|
|
||||||
add(lastContact.trigger(), new BrakeStop(this));
|
|
||||||
add(lastContact.trigger(), new FinishRoute(this));
|
|
||||||
}
|
|
||||||
for (Signal signal : signals) add(ROUTE_SETUP,new SetSignal(this).set(signal).to(Signal.GO));
|
|
||||||
add(ROUTE_START,new SetSpeed(this).to(999));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Kontakt der Route aktivieren
|
|
||||||
* @param contact
|
|
||||||
* @param trainHead
|
|
||||||
*/
|
|
||||||
public void contact(Contact contact) {
|
|
||||||
if (triggeredContacts.contains(contact)) return; // don't trigger contact a second time
|
|
||||||
triggeredContacts.add(contact);
|
|
||||||
LOG.debug("{} on {} activated {}.",train,this,contact);
|
|
||||||
traceTrainFrom(contact);
|
|
||||||
ActionList actions = triggeredActions.get(contact.trigger());
|
|
||||||
if (isNull(actions)) return;
|
|
||||||
Context context = new Context(contact).route(this).train(train);
|
|
||||||
actions.fire(context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Vector<Contact> contacts() {
|
|
||||||
return new Vector<>(contacts);
|
|
||||||
}
|
|
||||||
|
|
||||||
public String context() {
|
|
||||||
return REALM_ROUTE+":"+id();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isDisabled() {
|
|
||||||
return disabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Block endBlock() {
|
public Block endBlock() {
|
||||||
return endBlock;
|
return endBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish() {
|
public void finish() {
|
||||||
|
context.clear(); // prevent delayed actions from firing after route has finished
|
||||||
setSignals(Signal.STOP);
|
setSignals(Signal.STOP);
|
||||||
for (Tile tile : path) tile.setRoute(null);
|
for (Tile tile : path) tile.setRoute(null);
|
||||||
Tile lastTile = path.lastElement();
|
Tile lastTile = path.lastElement();
|
||||||
@@ -455,7 +434,7 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
triggeredContacts.clear();
|
triggeredContacts.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean fireSetupActions(Context context) {
|
public boolean fireSetupActions() {
|
||||||
ActionList setupActions = triggeredActions.get(ROUTE_SETUP);
|
ActionList setupActions = triggeredActions.get(ROUTE_SETUP);
|
||||||
if (isSet(setupActions) && !setupActions.fire(context)) return false;
|
if (isSet(setupActions) && !setupActions.fire(context)) return false;
|
||||||
state = State.PREPARED;
|
state = State.PREPARED;
|
||||||
@@ -481,6 +460,10 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
if (isNull(id)) id = new Id(""+(generateName().hashCode()));
|
if (isNull(id)) id = new Id(""+(generateName().hashCode()));
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isDisabled() {
|
||||||
|
return disabled;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isFreeFor(Train newTrain) {
|
public boolean isFreeFor(Train newTrain) {
|
||||||
for (int i=1; i<path.size(); i++) {
|
for (int i=1; i<path.size(); i++) {
|
||||||
@@ -761,9 +744,6 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
LOG.debug("Removing route ({}) {}",id(),this);
|
LOG.debug("Removing route ({}) {}",id(),this);
|
||||||
if (isSet(train)) train.removeChild(this);
|
if (isSet(train)) train.removeChild(this);
|
||||||
for (Tile tile : path) {
|
for (Tile tile : path) {
|
||||||
if (tile.id().equals(Tile.id(4, 6))) {
|
|
||||||
System.err.println(tile);
|
|
||||||
}
|
|
||||||
tile.removeChild(this);
|
tile.removeChild(this);
|
||||||
}
|
}
|
||||||
conditions.remove();
|
conditions.remove();
|
||||||
@@ -823,6 +803,12 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
file.write("]}");
|
file.write("]}");
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Context set(Context newContext) {
|
||||||
|
context = newContext;
|
||||||
|
context.route(this);
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
|
||||||
public void setLast(Turnout.State state) {
|
public void setLast(Turnout.State state) {
|
||||||
if (isNull(state) || state == Turnout.State.UNDEF) return;
|
if (isNull(state) || state == Turnout.State.UNDEF) return;
|
||||||
@@ -865,7 +851,7 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
if (newTrain != train) return false; // can't alter route's train
|
if (newTrain != train) return false; // can't alter route's train
|
||||||
} else train = newTrain; // set new train
|
} else train = newTrain; // set new train
|
||||||
ActionList startActions = triggeredActions.get(ROUTE_START);
|
ActionList startActions = triggeredActions.get(ROUTE_START);
|
||||||
if (isSet(startActions) && !startActions.fire(new Context(this).train(train))) return false; // start actions failed
|
if (isSet(startActions) && !startActions.fire(context)) return false; // start actions failed
|
||||||
state = State.STARTED;
|
state = State.STARTED;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -896,6 +882,17 @@ public class Route extends BaseClass implements Comparable<Route>{
|
|||||||
return train;
|
return train;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Fieldset turnouts() {
|
||||||
|
Fieldset win = new Fieldset(t("Turnouts"));
|
||||||
|
Tag list = new Tag("ul");
|
||||||
|
for (Entry<Turnout, Turnout.State> entry : turnouts.entrySet()) {
|
||||||
|
Turnout turnout = entry.getKey();
|
||||||
|
Plan.addLink(turnout, turnout+": "+t(entry.getValue().toString()), list);
|
||||||
|
}
|
||||||
|
list.addTo(win);
|
||||||
|
return win;
|
||||||
|
}
|
||||||
|
|
||||||
public Route unlock() throws IOException {
|
public Route unlock() throws IOException {
|
||||||
// TODO
|
// TODO
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ public abstract class Action extends BaseClass {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean equals(Action other) {
|
public boolean corresponsTo(Action other) {
|
||||||
return this.toString().equals(other.toString());
|
return this.toString().equals(other.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,30 +58,6 @@ public class ActionList extends Action implements Iterable<Action>{
|
|||||||
return new Tag("span").content(t("Unknown action type: {}",type)).addTo(actionTypeForm());
|
return new Tag("span").content(t("Unknown action type: {}",type)).addTo(actionTypeForm());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addActionsFrom(ActionList other) {
|
|
||||||
for (Action otherAction : other.actions) {
|
|
||||||
//LOG.debug("old action ({}): {}",otherAction.getClass().getSimpleName(),otherAction);
|
|
||||||
boolean exists = false;
|
|
||||||
int len = actions.size();
|
|
||||||
for (int i=0; i<len; i++) {
|
|
||||||
Action thisAction = actions.get(i);
|
|
||||||
LOG.debug("→ {} ?",thisAction);
|
|
||||||
if (thisAction.equals(otherAction)) {
|
|
||||||
LOG.debug("Action already existing!");
|
|
||||||
exists = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exists) {
|
|
||||||
LOG.debug("action not added.");
|
|
||||||
} else { // bestehemde Aktion der neuen Liste zuweisen
|
|
||||||
this.add(otherAction);
|
|
||||||
LOG.debug("action added.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
actions.forEach(action -> other.removeChild(action)); // zugewiesene Aktionen von alter Liste löschen
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
while (!actions.isEmpty()) actions.firstElement().remove();
|
while (!actions.isEmpty()) actions.firstElement().remove();
|
||||||
}
|
}
|
||||||
@@ -91,6 +67,10 @@ public class ActionList extends Action implements Iterable<Action>{
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean fire(Context context) {
|
public boolean fire(Context context) {
|
||||||
|
if (context.invalidated()) {
|
||||||
|
LOG.debug("Context has been invalidated, aborting {}",this);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!isEmpty()) LOG.debug(t("Firing {}"),actions);
|
if (!isEmpty()) LOG.debug(t("Firing {}"),actions);
|
||||||
for (Action action : actions) {
|
for (Action action : actions) {
|
||||||
if (!action.fire(context)) return false;
|
if (!action.fire(context)) return false;
|
||||||
@@ -151,6 +131,20 @@ public class ActionList extends Action implements Iterable<Action>{
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void merge(ActionList oldActions) {
|
||||||
|
for (Action oldAction : oldActions.actions) {
|
||||||
|
for (Action newAction : actions) {
|
||||||
|
if (oldAction.corresponsTo(newAction)) {
|
||||||
|
actions.remove(newAction);
|
||||||
|
LOG.debug("new action {} replaced by {}",newAction,oldAction);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
add(oldAction);
|
||||||
|
}
|
||||||
|
oldActions.actions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean moveUp(Action action) {
|
public boolean moveUp(Action action) {
|
||||||
if (isNull(action)) return false;
|
if (isNull(action)) return false;
|
||||||
if (actions.firstElement() == action && parent() instanceof ActionList) {
|
if (actions.firstElement() == action && parent() instanceof ActionList) {
|
||||||
|
|||||||
@@ -19,13 +19,14 @@ public class PreserveRoute extends Action {
|
|||||||
if (isNull(train)) return false;
|
if (isNull(train)) return false;
|
||||||
if (isNull(route)) return false;
|
if (isNull(route)) return false;
|
||||||
|
|
||||||
Range waitTime = route.endBlock().getWaitTime(train,route.endDirection);
|
|
||||||
|
|
||||||
// These are NOT errors:
|
// These are NOT errors:
|
||||||
if (!train.usesAutopilot()) return true;
|
if (!train.usesAutopilot()) return true;
|
||||||
if (waitTime.max > 0) return true; // train is expected to wait in next block.
|
|
||||||
if (train.destination() == route.endBlock()) return true;
|
if (train.destination() == route.endBlock()) return true;
|
||||||
|
|
||||||
|
Range waitTime = route.endBlock().getWaitTime(train,route.endDirection);
|
||||||
|
if (waitTime.max > 0) return true; // train is expected to wait in next block.
|
||||||
|
|
||||||
train.reserveNext();
|
train.reserveNext();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,10 +75,10 @@ public class SetRelay extends Action {
|
|||||||
@Override
|
@Override
|
||||||
protected Object update(HashMap<String, String> params) {
|
protected Object update(HashMap<String, String> params) {
|
||||||
LOG.debug("update: {}",params);
|
LOG.debug("update: {}",params);
|
||||||
Id relayId = new Id(params.get(RELAY));
|
Id relayId = new Id(params.get(Relay.class.getSimpleName()));
|
||||||
relay = Relay.get(relayId);
|
relay = Relay.get(relayId);
|
||||||
String st = params.get(Relay.STATE);
|
String st = params.get(Relay.STATE);
|
||||||
if (isSet(st)) state = st.equals("true");
|
if (isSet(st)) state = st.equals("true");
|
||||||
return properties();
|
return context().properties();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ public class SetSpeed extends Action{
|
|||||||
public static final String MAX_SPEED = "max_speed";
|
public static final String MAX_SPEED = "max_speed";
|
||||||
private int speed = 0;
|
private int speed = 0;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean corresponsTo(Action other) {
|
||||||
|
return other instanceof SetSpeed;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean fire(Context context) {
|
public boolean fire(Context context) {
|
||||||
if (isNull(context.train())) return false;
|
if (isNull(context.train())) return false;
|
||||||
@@ -66,10 +71,7 @@ public class SetSpeed extends Action{
|
|||||||
try {
|
try {
|
||||||
int s = Integer.parseInt(ms);
|
int s = Integer.parseInt(ms);
|
||||||
if (s<0) error = t("Speed must not be less than zero!");
|
if (s<0) error = t("Speed must not be less than zero!");
|
||||||
if (error == null) {
|
if (isNull(error)) speed = s;
|
||||||
this.speed = s;
|
|
||||||
return t("Action updated!");
|
|
||||||
}
|
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
error = t("Not a valid number!");
|
error = t("Not a valid number!");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -523,7 +523,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dest.addTo(propList);
|
dest.addTo(propList);
|
||||||
if (isSet(route)) link("li", route).addTo(propList);
|
if (isSet(route)) route.link("li", route).addTo(propList);
|
||||||
int ms = maxSpeed();
|
int ms = maxSpeed();
|
||||||
if (ms < Integer.MAX_VALUE) new Tag("li").content(t("Max. Speed")+": "+maxSpeed()+NBSP+speedUnit).addTo(propList);
|
if (ms < Integer.MAX_VALUE) new Tag("li").content(t("Max. Speed")+": "+maxSpeed()+NBSP+speedUnit).addTo(propList);
|
||||||
|
|
||||||
@@ -583,10 +583,10 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
Context context = new Context(this).route(route).block(route.endBlock()).direction(route.endDirection);
|
Context context = new Context(this).route(route).block(route.endBlock()).direction(route.endDirection);
|
||||||
Route nextRoute = PathFinder.chooseRoute(context);
|
Route nextRoute = PathFinder.chooseRoute(context);
|
||||||
if (isNull(nextRoute)) return;
|
if (isNull(nextRoute)) return;
|
||||||
|
nextRoute.set(context);
|
||||||
boolean error = !nextRoute.lockIgnoring(route);
|
boolean error = !nextRoute.lockIgnoring(route);
|
||||||
error = error || !nextRoute.setTurnouts();
|
error = error || !nextRoute.setTurnouts();
|
||||||
error = error || !nextRoute.fireSetupActions(context);
|
error = error || !nextRoute.fireSetupActions();
|
||||||
|
|
||||||
if (error) {
|
if (error) {
|
||||||
nextRoute.reset(); // may unlock tiles belonging to the current route.
|
nextRoute.reset(); // may unlock tiles belonging to the current route.
|
||||||
@@ -686,23 +686,26 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
return properties();
|
return properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String start() throws IOException {
|
public Object start() throws IOException {
|
||||||
if (isNull(currentBlock)) return t("{} not in a block",this);
|
if (isNull(currentBlock)) return t("{} not in a block",this);
|
||||||
if (maxSpeed() == 0) return t("Train has maximum speed of 0 {}, cannot go!",speedUnit);
|
if (maxSpeed() == 0) return t("Train has maximum speed of 0 {}, cannot go!",speedUnit);
|
||||||
if (isSet(route)) route.reset(); // reset route previously chosen
|
if (isSet(route)) route.reset(); // reset route previously chosen
|
||||||
|
|
||||||
Context context = new Context(this).block(currentBlock).direction(direction);
|
|
||||||
String error = null;
|
String error = null;
|
||||||
if (isSet(nextRoute)) {
|
if (isSet(nextRoute)) {
|
||||||
route = nextRoute;
|
route = nextRoute;
|
||||||
if (!route.lock()) return t("Was not able to lock {}",route);
|
if (!route.lock()) return t("Was not able to lock {}",route);
|
||||||
nextRoute = null;
|
nextRoute = null;
|
||||||
|
route.set(new Context(this).block(currentBlock).direction(direction));
|
||||||
} else {
|
} else {
|
||||||
|
Context context = new Context(this).block(currentBlock).direction(direction);
|
||||||
route = PathFinder.chooseRoute(context);
|
route = PathFinder.chooseRoute(context);
|
||||||
if (isNull(route)) return t("No free routes from {}",currentBlock);
|
if (isNull(route)) return t("No free routes from {}",currentBlock);
|
||||||
if (!route.lock()) return t("Was not able to lock {}",route);
|
if (!route.lock()) return t("Was not able to lock {}",route);
|
||||||
if (!route.setTurnouts()) error = t("Was not able to set all turnouts!");
|
if (!route.setTurnouts()) error = t("Was not able to set all turnouts!");
|
||||||
if (isNull(error) && !route.fireSetupActions(context.route(route))) error = t("Was not able to fire all setup actions of route!");
|
context.train(this);
|
||||||
|
route.set(context);
|
||||||
|
if (isNull(error) && !route.fireSetupActions()) error = t("Was not able to fire all setup actions of route!");
|
||||||
}
|
}
|
||||||
if (direction != route.startDirection) turn();
|
if (direction != route.startDirection) turn();
|
||||||
|
|
||||||
@@ -713,7 +716,9 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
startSimulation();
|
startSimulation();
|
||||||
return t("Started {}",this);
|
Window win = properties();
|
||||||
|
new Tag("p").content(t("Started {}",this)).addTo(win);
|
||||||
|
return win;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void startAll() {
|
public static void startAll() {
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ public class Relay extends Tile implements Device{
|
|||||||
new Tag("option").attr("value","0").content(t("unset")).addTo(select);
|
new Tag("option").attr("value","0").content(t("unset")).addTo(select);
|
||||||
for (Relay relay : BaseClass.listElements(Relay.class)) {
|
for (Relay relay : BaseClass.listElements(Relay.class)) {
|
||||||
if (exclude.contains(relay)) continue;
|
if (exclude.contains(relay)) continue;
|
||||||
Tag opt = select.addOption(relay.id, relay);
|
Tag opt = select.addOption(relay.id(), relay);
|
||||||
if (relay == preselected) opt.attr("selected", "selected");
|
if (relay == preselected) opt.attr("selected", "selected");
|
||||||
}
|
}
|
||||||
return select;
|
return select;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public abstract class Tile extends BaseClass implements Comparable<Tile>{
|
|||||||
private int length = DEFAUT_LENGTH;
|
private int length = DEFAUT_LENGTH;
|
||||||
protected Direction oneWay = null;
|
protected Direction oneWay = null;
|
||||||
protected Route route = null;
|
protected Route route = null;
|
||||||
private TreeSet<Route> routes = new TreeSet<>();
|
private TreeSet<Route> routes = new TreeSet<>((r1,r2)->r1.toString().compareTo(r2.toString()));
|
||||||
protected Train train = null;
|
protected Train train = null;
|
||||||
public Integer x = null;
|
public Integer x = null;
|
||||||
public Integer y = null;
|
public Integer y = null;
|
||||||
@@ -169,10 +169,11 @@ 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
|
||||||
super.load(json);
|
super.load(json);
|
||||||
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)) disabled = json.getBoolean(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));
|
||||||
|
|||||||
Reference in New Issue
Block a user