Browse Source

re-implemented trace update code

lookup-tables
Stephan Richter 4 years ago
parent
commit
c4e57d2b8a
  1. 2
      pom.xml
  2. 6
      src/main/java/de/srsoftware/web4rail/BaseClass.java
  3. 2
      src/main/java/de/srsoftware/web4rail/Plan.java
  4. 27
      src/main/java/de/srsoftware/web4rail/Route.java
  5. 93
      src/main/java/de/srsoftware/web4rail/moving/Train.java
  6. 15
      src/main/java/de/srsoftware/web4rail/tiles/Block.java
  7. 7
      src/main/java/de/srsoftware/web4rail/tiles/Tile.java

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.3.65</version> <version>1.3.66</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>

6
src/main/java/de/srsoftware/web4rail/BaseClass.java

@ -4,6 +4,7 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.AbstractMap; import java.util.AbstractMap;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
@ -521,6 +522,11 @@ public abstract class BaseClass implements Constants{
registry = new HashMap<BaseClass.Id, BaseClass>(); registry = new HashMap<BaseClass.Id, BaseClass>();
customFieldNames = new HashMap<Class<? extends BaseClass>, Set<String>>(); customFieldNames = new HashMap<Class<? extends BaseClass>, Set<String>>();
} }
public static <T,L extends List<T>> L reverse(L list){
Collections.reverse(list);
return list;
}
public void sleep(long ms) { public void sleep(long ms) {
try { try {

2
src/main/java/de/srsoftware/web4rail/Plan.java

@ -356,7 +356,7 @@ public class Plan extends BaseClass{
new Input(ACTION,ACTION_UPDATE).hideIn(form); new Input(ACTION,ACTION_UPDATE).hideIn(form);
new Input(LENGTH_UNIT, lengthUnit).addTo(new Label(t("Length unit")+COL)).addTo(form); new Input(LENGTH_UNIT, lengthUnit).addTo(new Label(t("Length unit")+COL)).addTo(form);
new Input(SPEED_UNIT, speedUnit).addTo(new Label(t("Speed unit")+COL)).addTo(form); new Input(SPEED_UNIT, speedUnit).addTo(new Label(t("Speed unit")+COL)).addTo(form);
new Input(FINAL_SPEED, Train.defaultEndSpeed).addTo(new Label(t("Lower speed limit")+COL)).attr("title", t("Final speed after breaking, before halting")).addTo(form); // TODO new Input(FINAL_SPEED, Train.defaultEndSpeed).addTo(new Label(t("Lower speed limit")+COL)).attr("title", t("Final speed after breaking, before halting")).addTo(form);
new Checkbox(FREE_BEHIND_TRAIN, t("Free tiles behind train"), Route.freeBehindTrain).attr("title", t("If checked, tiles behind the train are freed according to the length of the train and the tiles. If it is unchecked, tiles will not get free before route is finished.")).addTo(form); new Checkbox(FREE_BEHIND_TRAIN, t("Free tiles behind train"), Route.freeBehindTrain).attr("title", t("If checked, tiles behind the train are freed according to the length of the train and the tiles. If it is unchecked, tiles will not get free before route is finished.")).addTo(form);
new Button(t("Save"), form).addTo(form); new Button(t("Save"), form).addTo(form);
form.addTo(fieldset); form.addTo(fieldset);

27
src/main/java/de/srsoftware/web4rail/Route.java

@ -322,7 +322,9 @@ public class Route extends BaseClass {
LOG.debug("Contact has id {} / trigger {} and is assigned with {}",contact.id(),contact.trigger(),isNull(actions)?t("nothing"):actions); LOG.debug("Contact has id {} / trigger {} and is assigned with {}",contact.id(),contact.trigger(),isNull(actions)?t("nothing"):actions);
if (isNull(actions)) return context; if (isNull(actions)) return context;
actions.fire(context,"Route.Contact("+contact.addr()+")"); actions.fire(context,"Route.Contact("+contact.addr()+")");
return context; Context previousContext = context;
if (context.invalidated()) context = null; // route has been freed in between.
return previousContext;
} }
public Vector<Contact> contacts() { public Vector<Contact> contacts() {
@ -380,13 +382,10 @@ public class Route extends BaseClass {
private void free() { private void free() {
context.invalidate(); context.invalidate();
Train train = context.train(); Train train = context.train();
for (int i=path.size(); i>0; i--) { Vector<Tile> reversedPath = reverse(path());
Tile tile = path.get(i-1); for (Tile tile : reversedPath) {
if (isSet(train) && !train.onTrace(tile)) { if (isSet(train) && !train.onTrace(tile)) tile.free(train);
tile.free(train);
}
} }
context = null;
} }
private String generateName() { private String generateName() {
@ -504,7 +503,7 @@ public class Route extends BaseClass {
if (json.has(ACTIONS)) { if (json.has(ACTIONS)) {
loadActions(json.getJSONObject(ACTIONS)); loadActions(json.getJSONObject(ACTIONS));
} }
if (json.has("action_lists")) { // TODO: this is legacy! if (json.has("action_lists")) { // Legacy
JSONArray jarr = json.getJSONArray("action_lists"); JSONArray jarr = json.getJSONArray("action_lists");
for (Object o : jarr) { for (Object o : jarr) {
if (o instanceof JSONObject) { if (o instanceof JSONObject) {
@ -525,7 +524,7 @@ public class Route extends BaseClass {
} }
} }
} }
if (json.has("conditions")) { // TODO: this is legacy! if (json.has("conditions")) { // Legacy
JSONArray jConditions = json.getJSONArray("conditions"); JSONArray jConditions = json.getJSONArray("conditions");
for (Object o : jConditions) { for (Object o : jConditions) {
if (o instanceof JSONObject) { if (o instanceof JSONObject) {
@ -540,7 +539,7 @@ public class Route extends BaseClass {
} }
} }
if (json.has(CONDITION_LIST)) conditions.load(json.getJSONObject(CONDITION_LIST)).parent(this); if (json.has(CONDITION_LIST)) conditions.load(json.getJSONObject(CONDITION_LIST)).parent(this);
if (json.has(SETUP_ACTIONS)) { // TODO: this is legacy! if (json.has(SETUP_ACTIONS)) { // Legacy
Object so = json.get(SETUP_ACTIONS); Object so = json.get(SETUP_ACTIONS);
if (so instanceof JSONObject) { if (so instanceof JSONObject) {
JSONObject jo = (JSONObject) so; JSONObject jo = (JSONObject) so;
@ -565,7 +564,7 @@ public class Route extends BaseClass {
triggeredActions.put(ROUTE_SETUP, setupActions); triggeredActions.put(ROUTE_SETUP, setupActions);
} }
} }
if (json.has(START_ACTIONS)) { // TODO: this is legacy! if (json.has(START_ACTIONS)) { // Legacy
Object so = json.get(START_ACTIONS); Object so = json.get(START_ACTIONS);
if (so instanceof JSONObject) { if (so instanceof JSONObject) {
JSONObject jo = (JSONObject) so; JSONObject jo = (JSONObject) so;
@ -645,9 +644,7 @@ public class Route extends BaseClass {
} }
public Vector<Tile> path() { public Vector<Tile> path() {
Vector<Tile> result = new Vector<Tile>(); return isSet(path) ? new Vector<>(path) : new Vector<>();
if (isSet(path)) result.addAll(path);
return result;
} }
public boolean prepareAndLock() { public boolean prepareAndLock() {
@ -660,7 +657,7 @@ public class Route extends BaseClass {
} }
for (Tile tile : path) { for (Tile tile : path) {
if (context.invalidated() || !tile.lockFor(context)) { if (context.invalidated() || !tile.lockFor(context,false)) {
LOG.debug("Was not able to allocate route for {}.",context); LOG.debug("Was not able to allocate route for {}.",context);
return false; return false;
} }

93
src/main/java/de/srsoftware/web4rail/moving/Train.java

@ -10,7 +10,6 @@ import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.HashSet; import java.util.HashSet;
import java.util.Iterator; import java.util.Iterator;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.SortedSet; import java.util.SortedSet;
@ -38,7 +37,6 @@ import de.srsoftware.web4rail.tags.Table;
import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.threads.RouteManager; import de.srsoftware.web4rail.threads.RouteManager;
import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.Block;
import de.srsoftware.web4rail.tiles.BlockContact;
import de.srsoftware.web4rail.tiles.Contact; import de.srsoftware.web4rail.tiles.Contact;
import de.srsoftware.web4rail.tiles.Tile; import de.srsoftware.web4rail.tiles.Tile;
@ -84,7 +82,7 @@ public class Train extends BaseClass implements Comparable<Train> {
private boolean f1,f2,f3,f4; private boolean f1,f2,f3,f4;
private Block currentBlock,destination = null; private Block currentBlock,destination = null;
LinkedList<Tile> trace = new LinkedList<Tile>(); HashSet<Tile> trace = new HashSet<Tile>();
private Vector<Block> lastBlocks = new Vector<Block>(); private Vector<Block> lastBlocks = new Vector<Block>();
public int speed = 0; public int speed = 0;
@ -300,9 +298,7 @@ public class Train extends BaseClass implements Comparable<Train> {
public Context contact(Contact contact) { public Context contact(Contact contact) {
if (isNull(route)) return new Context(contact).train(this); if (isNull(route)) return new Context(contact).train(this);
Context context = route.contact(contact); return updateTrace(route.contact(contact));
traceFrom(context);
return context;
} }
@ -398,11 +394,17 @@ public class Train extends BaseClass implements Comparable<Train> {
public void dropTrace() { public void dropTrace() {
while (!trace.isEmpty()) trace.removeFirst().free(this); trace.forEach(tile -> tile.free(this));
trace.clear();
} }
public void endRoute(Block newBlock, Direction newDirection) { public void endRoute(Block endBlock, Direction endDirection) {
setSpeed(0);
route = null;
direction = endDirection;
endBlock.add(this, direction);
currentBlock = endBlock;
trace.add(endBlock);
} }
private Tag faster(int steps) { private Tag faster(int steps) {
@ -713,22 +715,14 @@ public class Train extends BaseClass implements Comparable<Train> {
public Train reverse() { public Train reverse() {
LOG.debug("train.reverse();"); LOG.debug("train.reverse();");
if (isSet(direction)) { if (isSet(direction)) direction = direction.inverse();
direction = direction.inverse(); if (isSet(currentBlock)) {
reverseTrace(); currentBlock.set(this,direction);
plan.place(currentBlock);
} }
if (isSet(currentBlock)) plan.place(currentBlock);
return this; return this;
} }
private void reverseTrace() {
LinkedList<Tile> reversed = new LinkedList<Tile>();
LOG.debug("Trace: {}",trace);
while (!trace.isEmpty()) reversed.addFirst(trace.removeFirst());
trace = reversed;
LOG.debug("reversed: {}",trace);
}
public Route route() { public Route route() {
return route; return route;
} }
@ -903,15 +897,6 @@ public class Train extends BaseClass implements Comparable<Train> {
return name(); return name();
} }
public void traceFrom(Context context) {
// TOSO: neu implementieren!
// Beachten: Route aus Context, plan.freeBehindTrain
}
public Tile traceHead() {
return trace == null || trace.isEmpty() ? null : trace.getFirst();
}
/** /**
* this inverts the direction the train is heading to. Example: * this inverts the direction the train is heading to. Example:
* before: CabCar MiddleCar Loco * before: CabCar MiddleCar Loco
@ -922,7 +907,7 @@ public class Train extends BaseClass implements Comparable<Train> {
LOG.debug("{}.turn()",this); LOG.debug("{}.turn()",this);
setSpeed(0); setSpeed(0);
for (Car car : cars) car.turn(); for (Car car : cars) car.turn();
Collections.reverse(cars); reverse(cars);
return reverse(); return reverse();
} }
@ -941,6 +926,52 @@ public class Train extends BaseClass implements Comparable<Train> {
} }
return properties(); return properties();
} }
public Context updateTrace(Context context) {
// TOSO: neu implementieren!
// Beachten: Route aus Context, plan.freeBehindTrain
LOG.debug("updateTrace({})",context);
Tile from = context.tile();
if (isNull(from)) from = context.contact();
if (isNull(from)) {
LOG.debug("no starting point for trace given in {}",context);
return context;
}
trace.add(from);
Route route = context.route();
LOG.debug("Route: {}",route);
if (isNull(route)) return context;
Vector<Tile> reversedPath = reverse(route.path());
HashSet<Tile> newTrace = new HashSet<Tile>();
Integer remainingLength = null;
for (Tile tile : reversedPath) {
if (isNull(remainingLength) && onTrace(tile)) remainingLength = length();
if (remainingLength == null) { // ahead of train
LOG.debug("{} is ahead of train and will not be touched.",tile);
trace.remove(tile); // old trace will be cleared afterwards. but this tile shall not be cleared, so remove it from old trace
} else if (remainingLength > 0) { // within train
LOG.debug("{} is occupied by train and will be marked as \"occupied\"",tile);
remainingLength -= tile.length();
newTrace.add(tile);
trace.remove(tile); // old trace will be cleared afterwards. but this tile shall not be cleared, so remove it from old trace
tile.setTrain(this);
LOG.debug("remaining length: {}",remainingLength);
} else { // behind train
if (Route.freeBehindTrain) {
LOG.debug("{} is behind train and will be freed in the next step",tile);
trace.add(tile); // old trace will be cleared afterwards
} else {
LOG.debug("{} is behind train and will be reset to \"locked\" state",tile);
tile.lockFor(context,true);
trace.remove(tile); // old trace will be cleared afterwards. but this tile shall not be cleared, so remove it from old trace
}
}
}
for (Tile tile : trace) tile.free(this);
trace = newTrace;
return context;
}
public boolean usesAutopilot() { public boolean usesAutopilot() {
return isSet(routeManager) && routeManager.autoEnabled(); return isSet(routeManager) && routeManager.autoEnabled();

15
src/main/java/de/srsoftware/web4rail/tiles/Block.java

@ -80,6 +80,11 @@ public abstract class Block extends StretchableTile{
return trains.remove(b); return trains.remove(b);
} }
public void set(Train train, Direction newDirection) {
dirs.put(train, newDirection);
}
@Override @Override
public String toString() { public String toString() {
return trains.toString(); return trains.toString();
@ -388,7 +393,7 @@ public abstract class Block extends StretchableTile{
} }
@Override @Override
public boolean lockFor(Context context) { public boolean lockFor(Context context, boolean downgrade) {
Train newTrain = context.train(); Train newTrain = context.train();
Route route = context.route(); Route route = context.route();
LOG.debug("{}.lock({})",this,newTrain); LOG.debug("{}.lock({})",this,newTrain);
@ -398,6 +403,8 @@ public abstract class Block extends StretchableTile{
switch (status) { switch (status) {
case DISABLED: case DISABLED:
return false; return false;
case OCCUPIED:
if (!downgrade) break;
case FREE: case FREE:
case RESERVED: case RESERVED:
status = Status.LOCKED; status = Status.LOCKED;
@ -406,7 +413,6 @@ public abstract class Block extends StretchableTile{
add(newTrain,dir); add(newTrain,dir);
plan.place(this); plan.place(this);
break; break;
case OCCUPIED:
case LOCKED: case LOCKED:
break; // do not downgrade break; // do not downgrade
} }
@ -482,6 +488,11 @@ public abstract class Block extends StretchableTile{
return routes().stream().filter(route -> route.startBlock() == Block.this).collect(Collectors.toList()); return routes().stream().filter(route -> route.startBlock() == Block.this).collect(Collectors.toList());
} }
public void set(Train train, Direction direction) {
trains.set(train,direction);
}
public abstract List<Connector> startPoints(); public abstract List<Connector> startPoints();
@Override @Override

7
src/main/java/de/srsoftware/web4rail/tiles/Tile.java

@ -478,7 +478,7 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
plan.place(this); plan.place(this);
} }
public boolean lockFor(Context context) { public boolean lockFor(Context context,boolean downgrade) {
Train newTrain = context.train(); Train newTrain = context.train();
LOG.debug("{}.lockFor({})",this,newTrain); LOG.debug("{}.lockFor({})",this,newTrain);
if (isNull(newTrain)) return false; if (isNull(newTrain)) return false;
@ -486,14 +486,15 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
switch (status) { switch (status) {
case DISABLED: case DISABLED:
return false; return false;
case OCCUPIED:
if (!downgrade) break;
case FREE: case FREE:
case RESERVED: case RESERVED:
status = Status.LOCKED; status = Status.LOCKED;
plan.place(this); plan.place(this);
break; break;
case OCCUPIED:
case LOCKED: case LOCKED:
break; // do not downgrade break; // already locked
} }
return true; return true;
} }

Loading…
Cancel
Save