Implementierung des neuen Routen-Algorithmus weitgehend abgeschlossen.
Was noch fehlt ist der Brems-Prozessor; außerdem muss der neue Code getestet werden.
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.3.70</version>
|
<version>1.3.71</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>
|
||||||
|
|||||||
@@ -542,7 +542,7 @@ public abstract class BaseClass implements Constants{
|
|||||||
|
|
||||||
public void sleep(long ms) {
|
public void sleep(long ms) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(ms);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
* @author Stephan Richter, SRSoftware
|
* @author Stephan Richter, SRSoftware
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class Command {
|
public class Command extends BaseClass {
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(Command.class);
|
private static final Logger LOG = LoggerFactory.getLogger(Command.class);
|
||||||
private String command;
|
private String command;
|
||||||
@@ -143,11 +143,9 @@ public class Command {
|
|||||||
*/
|
*/
|
||||||
public Reply reply(int timeout) throws TimeoutException {
|
public Reply reply(int timeout) throws TimeoutException {
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
while (reply == null) try {
|
while (reply == null) {
|
||||||
if (counter++ > timeout) timeout();
|
if (counter++ > timeout) timeout();
|
||||||
Thread.sleep(10);
|
sleep(10);
|
||||||
} catch (InterruptedException e) {
|
|
||||||
LOG.warn("wait() interrupted!",e);
|
|
||||||
}
|
}
|
||||||
return reply;
|
return reply;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -300,7 +300,7 @@ public class Plan extends BaseClass{
|
|||||||
return win;
|
return win;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thread analyzer = new Thread() {
|
new Thread(Application.threadName("Plan.Analyzer")) {
|
||||||
public void run() {
|
public void run() {
|
||||||
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)) {
|
||||||
@@ -317,9 +317,7 @@ public class Plan extends BaseClass{
|
|||||||
|
|
||||||
stream(t("Found {} routes.",newRoutes.size()));
|
stream(t("Found {} routes.",newRoutes.size()));
|
||||||
}
|
}
|
||||||
};
|
}.start();
|
||||||
analyzer.setName(Application.threadName("Plan.Analyzer"));
|
|
||||||
analyzer.start();
|
|
||||||
|
|
||||||
return t("Analyzing plan...");
|
return t("Analyzing plan...");
|
||||||
}
|
}
|
||||||
@@ -652,7 +650,7 @@ public class Plan extends BaseClass{
|
|||||||
*/
|
*/
|
||||||
public Tile place(Tile tile) {
|
public Tile place(Tile tile) {
|
||||||
try {
|
try {
|
||||||
tile.parent(this);
|
// tile.parent(this);
|
||||||
tile.register();
|
tile.register();
|
||||||
stream("place "+tile.tag(null));
|
stream("place "+tile.tag(null));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import java.io.BufferedWriter;
|
|||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.FileWriter;
|
import java.io.FileWriter;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -36,6 +37,7 @@ import de.srsoftware.web4rail.tags.Fieldset;
|
|||||||
import de.srsoftware.web4rail.tags.Input;
|
import de.srsoftware.web4rail.tags.Input;
|
||||||
import de.srsoftware.web4rail.tags.Table;
|
import de.srsoftware.web4rail.tags.Table;
|
||||||
import de.srsoftware.web4rail.tags.Window;
|
import de.srsoftware.web4rail.tags.Window;
|
||||||
|
import de.srsoftware.web4rail.threads.BrakeProcess;
|
||||||
import de.srsoftware.web4rail.tiles.Block;
|
import de.srsoftware.web4rail.tiles.Block;
|
||||||
import de.srsoftware.web4rail.tiles.BlockContact;
|
import de.srsoftware.web4rail.tiles.BlockContact;
|
||||||
import de.srsoftware.web4rail.tiles.Contact;
|
import de.srsoftware.web4rail.tiles.Contact;
|
||||||
@@ -92,7 +94,7 @@ public class Route extends BaseClass {
|
|||||||
public Direction startDirection;
|
public Direction startDirection;
|
||||||
private HashSet<Contact> triggeredContacts = new HashSet<>();
|
private HashSet<Contact> triggeredContacts = new HashSet<>();
|
||||||
|
|
||||||
private Route nextRoute;
|
private Route nextPreparedRoute;
|
||||||
|
|
||||||
public Route() {
|
public Route() {
|
||||||
conditions = new ConditionList();
|
conditions = new ConditionList();
|
||||||
@@ -227,7 +229,9 @@ public class Route extends BaseClass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Integer brakeTime(String brakeId) {
|
public Integer brakeTime(String brakeId) {
|
||||||
return brakeTimes.get(brakeId);
|
Integer result = brakeTimes.get(brakeId);
|
||||||
|
Collection<Integer> values = brakeTimes.values();
|
||||||
|
return values.isEmpty() ? BrakeProcess.defaultTimeStep : values.stream().mapToInt(Integer::intValue).sum()/values.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void brakeTime(String brakeId, Integer newTimeStep) {
|
public void brakeTime(String brakeId, Integer newTimeStep) {
|
||||||
@@ -280,19 +284,19 @@ public class Route extends BaseClass {
|
|||||||
Contact nextToLastContact = contacts.get(contacts.size()-2);
|
Contact nextToLastContact = contacts.get(contacts.size()-2);
|
||||||
String trigger = nextToLastContact.trigger();
|
String trigger = nextToLastContact.trigger();
|
||||||
add(trigger,new BrakeStart(this));
|
add(trigger,new BrakeStart(this));
|
||||||
add(trigger,new PreserveRoute(this));
|
|
||||||
|
|
||||||
int count = 0;
|
int count = 0;
|
||||||
for (int i=0;i<contacts.size();i++) { // chose second contact, that is not a BlockContact
|
for (int i=0;i<contacts.size();i++) { // chose second contact, that is not a BlockContact
|
||||||
Contact contact = contacts.get(i);
|
Contact contact = contacts.get(i);
|
||||||
if (contact instanceof BlockContact) continue;
|
if (contact instanceof BlockContact) continue;
|
||||||
if (count++<1) continue;
|
if (count++==1) { // second contact, that is not a BlockContact:
|
||||||
|
for (Signal signal : signals) add(contact.trigger(),new SetSignal(this).set(signal).to(Signal.RED));
|
||||||
trigger = contact.trigger(); // second contact, that is not a BlockContact
|
|
||||||
for (Signal signal : signals) add(trigger,new SetSignal(this).set(signal).to(Signal.RED));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
add(trigger,new PreserveRoute(this));
|
||||||
|
|
||||||
|
}
|
||||||
if (!contacts.isEmpty()) add(contacts.lastElement().trigger(), new FinishRoute(this));
|
if (!contacts.isEmpty()) add(contacts.lastElement().trigger(), new FinishRoute(this));
|
||||||
for (Entry<Turnout, Turnout.State> entry : turnouts.entrySet()) {
|
for (Entry<Turnout, Turnout.State> entry : turnouts.entrySet()) {
|
||||||
Turnout turnout = entry.getKey();
|
Turnout turnout = entry.getKey();
|
||||||
@@ -370,6 +374,14 @@ public class Route extends BaseClass {
|
|||||||
for (String brakeId : brakeIds) brakeTimes.remove(brakeId);
|
for (String brakeId : brakeIds) brakeTimes.remove(brakeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Route dropNextPreparedRoute() {
|
||||||
|
try {
|
||||||
|
return nextPreparedRoute;
|
||||||
|
} finally {
|
||||||
|
nextPreparedRoute = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public Block endBlock() {
|
public Block endBlock() {
|
||||||
return endBlock;
|
return endBlock;
|
||||||
}
|
}
|
||||||
@@ -406,8 +418,8 @@ public class Route extends BaseClass {
|
|||||||
return sb.toString().trim();
|
return sb.toString().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Route getNextRoute() {
|
public Route getNextPreparedRoute() {
|
||||||
return nextRoute;
|
return nextPreparedRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Id id() {
|
public Id id() {
|
||||||
@@ -781,8 +793,8 @@ public class Route extends BaseClass {
|
|||||||
if (lastTile instanceof Turnout) addTurnout((Turnout) lastTile,state);
|
if (lastTile instanceof Turnout) addTurnout((Turnout) lastTile,state);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNextRoute(Route nextRoute) {
|
public void setNextPreparedRoute(Route route) {
|
||||||
this.nextRoute = nextRoute;
|
nextPreparedRoute = route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ public class PreserveRoute extends Action {
|
|||||||
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 false; // train is expected to wait in next block.
|
return false; // train is expected to wait in next block.
|
||||||
}
|
}
|
||||||
|
return isSet(route.getNextPreparedRoute()) || train.reserveRouteAfter(route);
|
||||||
return train.reserveRouteAfter(route);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,11 +29,7 @@ public class SetTurnout extends Action {
|
|||||||
if (isNull(turnout)) return false;
|
if (isNull(turnout)) return false;
|
||||||
if (!turnout.state(state).succeeded()) return false;
|
if (!turnout.state(state).succeeded()) return false;
|
||||||
if (turnout.address() == 0) return true;
|
if (turnout.address() == 0) return true;
|
||||||
try {
|
sleep(1000);
|
||||||
Thread.sleep(1000);
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ import de.srsoftware.web4rail.tags.Select;
|
|||||||
import de.srsoftware.web4rail.tags.Table;
|
import de.srsoftware.web4rail.tags.Table;
|
||||||
import de.srsoftware.web4rail.tags.Window;
|
import de.srsoftware.web4rail.tags.Window;
|
||||||
import de.srsoftware.web4rail.threads.RouteManager.Callback;
|
import de.srsoftware.web4rail.threads.RouteManager.Callback;
|
||||||
|
import de.srsoftware.web4rail.threads.BrakeProcess;
|
||||||
|
import de.srsoftware.web4rail.threads.DelayedExecution;
|
||||||
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.Contact;
|
import de.srsoftware.web4rail.tiles.Contact;
|
||||||
@@ -94,7 +96,9 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
|
|
||||||
private HashSet<Tile> stuckTrace = null;
|
private HashSet<Tile> stuckTrace = null;
|
||||||
|
|
||||||
private Route nextRoute;
|
private Route nextPreparedRoute;
|
||||||
|
|
||||||
|
private BrakeProcess brake;
|
||||||
|
|
||||||
public static Object action(HashMap<String, String> params, Plan plan) throws IOException {
|
public static Object action(HashMap<String, String> params, Plan plan) throws IOException {
|
||||||
String action = params.get(ACTION);
|
String action = params.get(ACTION);
|
||||||
@@ -404,10 +408,21 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
trace.clear();
|
trace.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private BrakeProcess endBrake() {
|
||||||
|
if (isNull(brake)) return null;
|
||||||
|
try {
|
||||||
|
return brake.end();
|
||||||
|
} finally {
|
||||||
|
brake = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void endRoute(Block endBlock, Direction endDirection) {
|
public void endRoute(Block endBlock, Direction endDirection) {
|
||||||
setSpeed(0);
|
BrakeProcess brake = endBrake();
|
||||||
nextRoute = route.getNextRoute();
|
if (isSet(brake)) brake.updateTime();
|
||||||
Integer waitTime = route.waitTime();
|
Integer waitTime = route.waitTime();
|
||||||
|
nextPreparedRoute = route.dropNextPreparedRoute();
|
||||||
|
if (isNull(nextPreparedRoute) || (isSet(waitTime) && waitTime > 0)) setSpeed(0);
|
||||||
route = null;
|
route = null;
|
||||||
direction = endDirection;
|
direction = endDirection;
|
||||||
endBlock.add(this, direction);
|
endBlock.add(this, direction);
|
||||||
@@ -415,8 +430,18 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
trace.add(endBlock);
|
trace.add(endBlock);
|
||||||
stuckTrace = null;
|
stuckTrace = null;
|
||||||
if (autopilot) {
|
if (autopilot) {
|
||||||
if (isSet(waitTime) && waitTime > 0) sleep(waitTime);
|
if (isNull(waitTime) || waitTime == 0) {
|
||||||
start(false);
|
start(false);
|
||||||
|
} else if (isSet(waitTime) && waitTime > 0) {
|
||||||
|
new DelayedExecution(waitTime,this) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
if (autopilot) Train.this.start(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
plan.stream(t("{} waiting {} secs",this,(int)(waitTime/1000)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -447,6 +472,11 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean hasNextPreparedRoute() {
|
||||||
|
return isSet(nextPreparedRoute) || (isSet(route) && isSet(route.getNextPreparedRoute()));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public Train heading(Direction dir) {
|
public Train heading(Direction dir) {
|
||||||
LOG.debug("{}.heading({})",this,dir);
|
LOG.debug("{}.heading({})",this,dir);
|
||||||
direction = dir;
|
direction = dir;
|
||||||
@@ -460,7 +490,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
|
|
||||||
public boolean isStoppable() {
|
public boolean isStoppable() {
|
||||||
if (speed > 0) return true;
|
if (speed > 0) return true;
|
||||||
if (isSet(routeManager) && routeManager.isSearching()) return true;
|
if (isSet(routeManager) && routeManager.isActive()) return true;
|
||||||
if (isSet(route)) return true;
|
if (isSet(route)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -689,6 +719,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
|
|
||||||
public String quitAutopilot() {
|
public String quitAutopilot() {
|
||||||
if (isSet(routeManager)) routeManager.quit();
|
if (isSet(routeManager)) routeManager.quit();
|
||||||
|
autopilot = false;
|
||||||
return t("Autopilot already was disabled!");
|
return t("Autopilot already was disabled!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -724,19 +755,19 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
return tags().iterator();
|
return tags().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean reserveRouteAfter(Route r) {
|
public boolean reserveRouteAfter(Route route) {
|
||||||
LOG.debug("reserveRouteAfter({})",r);
|
LOG.debug("reserveRouteAfter({})",route);
|
||||||
if (isNull(routeManager)) routeManager = new RouteManager();
|
if (isNull(routeManager)) routeManager = new RouteManager();
|
||||||
Context newContext = new Context(this).block(r.endBlock()).direction(r.endDirection);
|
Context newContext = new Context(this).block(route.endBlock()).direction(route.endDirection);
|
||||||
if (routeManager.isSearching()) return false;
|
if (routeManager.isSearching()) return false;
|
||||||
routeManager.setContext(newContext);
|
routeManager.setContext(newContext);
|
||||||
return (routeManager.setCallback(new Callback() {
|
routeManager.setCallback(new Callback() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void routePrepared(Route route) {
|
public void routePrepared(Route nextRoute) {
|
||||||
r.setNextRoute(route);
|
route.setNextPreparedRoute(nextRoute);
|
||||||
}
|
}
|
||||||
}));
|
});
|
||||||
|
return routeManager.prepareRoute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -869,9 +900,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
} else if (remaining.name.length()+car.name().length()<30){
|
} else if (remaining.name.length()+car.name().length()<30){
|
||||||
remaining.name += ", "+car.name();
|
remaining.name += ", "+car.name();
|
||||||
}
|
}
|
||||||
} else {
|
} else LOG.debug("Skipping {}",cars.get(i));
|
||||||
LOG.debug("Skipping {}",cars.get(i));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (remaining.cars.isEmpty()) return false;
|
if (remaining.cars.isEmpty()) return false;
|
||||||
remaining.direction = this.direction;
|
remaining.direction = this.direction;
|
||||||
@@ -885,8 +914,8 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
|
|
||||||
public String start(boolean auto) {
|
public String start(boolean auto) {
|
||||||
autopilot |= auto;
|
autopilot |= auto;
|
||||||
if (isSet(nextRoute) && nextRoute.start()) {
|
if (isSet(nextPreparedRoute) && nextPreparedRoute.start()) {
|
||||||
nextRoute = null;
|
nextPreparedRoute = null;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (isNull(routeManager)) routeManager = new RouteManager();
|
if (isNull(routeManager)) routeManager = new RouteManager();
|
||||||
@@ -899,7 +928,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (routeManager.isSearching()) { // es wird bereits eine Anschlussroute gesucht
|
if (routeManager.isActive()) { // es wird bereits eine Anschlussroute gesucht
|
||||||
// in diesem Fall muss bloß dass Callback des Route-Managers aktualisiert werden
|
// in diesem Fall muss bloß dass Callback des Route-Managers aktualisiert werden
|
||||||
routeManager.setCallback(callback);
|
routeManager.setCallback(callback);
|
||||||
} else { // routeManager nicht aktiv →> neuen Context setzen und starten
|
} else { // routeManager nicht aktiv →> neuen Context setzen und starten
|
||||||
@@ -916,9 +945,14 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
for (Train train : BaseClass.listElements(Train.class)) LOG.info(train.start(true));
|
for (Train train : BaseClass.listElements(Train.class)) LOG.info(train.start(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startBrake() {}
|
public void startBrake() {
|
||||||
|
LOG.debug("{}.startBrake()",this);
|
||||||
|
if (isSet(nextPreparedRoute)) return;
|
||||||
|
brake = new BrakeProcess(this);
|
||||||
|
}
|
||||||
|
|
||||||
public Window stopNow() {
|
public Window stopNow() {
|
||||||
|
endBrake();
|
||||||
setSpeed(0);
|
setSpeed(0);
|
||||||
quitAutopilot();
|
quitAutopilot();
|
||||||
if (isSet(route)) {
|
if (isSet(route)) {
|
||||||
@@ -994,8 +1028,6 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Context updateTrace(Context context) {
|
public Context updateTrace(Context context) {
|
||||||
// TOSO: neu implementieren!
|
|
||||||
// Beachten: Route aus Context, plan.freeBehindTrain
|
|
||||||
LOG.debug("updateTrace({})",context);
|
LOG.debug("updateTrace({})",context);
|
||||||
Tile from = context.tile();
|
Tile from = context.tile();
|
||||||
if (isNull(from)) from = context.contact();
|
if (isNull(from)) from = context.contact();
|
||||||
|
|||||||
@@ -0,0 +1,67 @@
|
|||||||
|
package de.srsoftware.web4rail.threads;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import de.srsoftware.web4rail.Application;
|
||||||
|
import de.srsoftware.web4rail.BaseClass;
|
||||||
|
import de.srsoftware.web4rail.moving.Train;
|
||||||
|
|
||||||
|
public class BrakeProcess extends BaseClass implements Runnable{
|
||||||
|
|
||||||
|
private static final Logger LOG = LoggerFactory.getLogger(BrakeProcess.class);
|
||||||
|
|
||||||
|
public static int defaultTimeStep = 500;
|
||||||
|
private Train train;
|
||||||
|
private int targetSpeed = Train.defaultEndSpeed;
|
||||||
|
boolean ended = false;
|
||||||
|
long distance = 0;
|
||||||
|
private int startSpeed;
|
||||||
|
private int lastSpeed;
|
||||||
|
private long lastTime;
|
||||||
|
|
||||||
|
public BrakeProcess(Train train) {
|
||||||
|
this.train = train;
|
||||||
|
new Thread(this, Application.threadName(this)).start();
|
||||||
|
}
|
||||||
|
|
||||||
|
public BrakeProcess end() {
|
||||||
|
LOG.debug("{}.end()",this);
|
||||||
|
ended = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
Integer delay = train.route().brakeTime(train.brakeId());
|
||||||
|
startSpeed = train.speed;
|
||||||
|
lastTime = timestamp();
|
||||||
|
while (!train.hasNextPreparedRoute()) {
|
||||||
|
sleep(delay);
|
||||||
|
lastSpeed = train.speed;
|
||||||
|
updateDistance();
|
||||||
|
if (lastSpeed > targetSpeed) lastSpeed -= 10;
|
||||||
|
if (lastSpeed < targetSpeed && (ended = true)) lastSpeed = targetSpeed;
|
||||||
|
if (ended) break;
|
||||||
|
if (lastSpeed != train.speed) train.setSpeed(lastSpeed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDistance() {
|
||||||
|
long newTime = timestamp();
|
||||||
|
distance += (newTime-lastTime)*lastSpeed;
|
||||||
|
lastTime = newTime;
|
||||||
|
LOG.debug("measured distance: {} units",distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName()+"("+train+")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateTime() {
|
||||||
|
updateDistance();
|
||||||
|
LOG.debug("updateTime(): start speed was {} {}.",startSpeed,BaseClass.speedUnit);
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -300,7 +300,7 @@ public class ControlUnit extends Thread implements Constants{
|
|||||||
private void startInfoThread() {
|
private void startInfoThread() {
|
||||||
infoSocket = commandSocket; // handshake läuft immer über commandSocket und commandScanner
|
infoSocket = commandSocket; // handshake läuft immer über commandSocket und commandScanner
|
||||||
infoScanner = commandScanner;
|
infoScanner = commandScanner;
|
||||||
Thread infoThread = new Thread() {
|
new Thread(Application.threadName("CU.InfoThread")) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -318,14 +318,12 @@ public class ControlUnit extends Thread implements Constants{
|
|||||||
case FEEDBACK:
|
case FEEDBACK:
|
||||||
int addr = Integer.parseInt(parts[5]);
|
int addr = Integer.parseInt(parts[5]);
|
||||||
boolean active = !parts[6].equals("0");
|
boolean active = !parts[6].equals("0");
|
||||||
Thread thread = new Thread() {
|
new Thread(Application.threadName("CU.FeedBack("+addr+")")) {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
plan.sensor(addr,active);
|
plan.sensor(addr,active);
|
||||||
}
|
}
|
||||||
};
|
}.start();
|
||||||
thread.setName(Application.threadName("CU.FeedBack("+addr+")"));
|
|
||||||
thread.start();
|
|
||||||
case ACESSORY:
|
case ACESSORY:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -351,9 +349,7 @@ public class ControlUnit extends Thread implements Constants{
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return "CU.InfoThread";
|
return "CU.InfoThread";
|
||||||
}
|
}
|
||||||
};
|
}.start();
|
||||||
infoThread.setName(Application.threadName("CU.InfoThread"));
|
|
||||||
infoThread.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -10,9 +10,8 @@ public abstract class DelayedExecution extends Thread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public DelayedExecution(int delay,Object cause) {
|
public DelayedExecution(int delay,Object cause) {
|
||||||
|
super(Application.threadName(cause));
|
||||||
this.delay = delay;
|
this.delay = delay;
|
||||||
|
|
||||||
setName(Application.threadName(cause));
|
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.util.Vector;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import de.srsoftware.web4rail.Application;
|
||||||
import de.srsoftware.web4rail.BaseClass;
|
import de.srsoftware.web4rail.BaseClass;
|
||||||
import de.srsoftware.web4rail.Plan.Direction;
|
import de.srsoftware.web4rail.Plan.Direction;
|
||||||
import de.srsoftware.web4rail.Route;
|
import de.srsoftware.web4rail.Route;
|
||||||
@@ -18,17 +19,21 @@ import de.srsoftware.web4rail.tiles.Tile;
|
|||||||
|
|
||||||
public class RouteManager extends BaseClass {
|
public class RouteManager extends BaseClass {
|
||||||
|
|
||||||
|
private enum State{
|
||||||
|
IDLE,SEARCHING,PREPARING
|
||||||
|
}
|
||||||
|
|
||||||
public static abstract class Callback {
|
public static abstract class Callback {
|
||||||
public abstract void routePrepared(Route route);
|
public abstract void routePrepared(Route route);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RouteManager.class);
|
private static final Logger LOG = LoggerFactory.getLogger(RouteManager.class);
|
||||||
private Context ctx;
|
private Context ctx;
|
||||||
|
private State state;
|
||||||
private Callback callback;
|
private Callback callback;
|
||||||
private boolean searching;
|
|
||||||
|
|
||||||
public RouteManager() {
|
public RouteManager() {
|
||||||
searching = false;
|
state =State.IDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TreeMap<Integer, List<Route>> availableRoutes(Context context, HashSet<Route> visitedRoutes) {
|
private static TreeMap<Integer, List<Route>> availableRoutes(Context context, HashSet<Route> visitedRoutes) {
|
||||||
@@ -153,55 +158,63 @@ public class RouteManager extends BaseClass {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return state != State.IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSearching() {
|
||||||
|
return state == State.SEARCHING;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean prepareRoute() {
|
||||||
|
try {
|
||||||
|
if (isNull(ctx) || ctx.invalidated()) return false;
|
||||||
|
state = State.SEARCHING;
|
||||||
|
Route route = chooseRoute(ctx);
|
||||||
|
if (isNull(route)) return false;
|
||||||
|
ctx.route(route);
|
||||||
|
if (!route.reserveFor(ctx)) {
|
||||||
|
route.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
state = State.PREPARING;
|
||||||
|
if (!route.prepareAndLock()) {
|
||||||
|
route.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (isNull(route) || isNull(callback)) return false;
|
||||||
|
callback.routePrepared(route);
|
||||||
|
return true;
|
||||||
|
} finally {
|
||||||
|
state = State.IDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void quit() {
|
public void quit() {
|
||||||
LOG.debug("{}.quit", this);
|
LOG.debug("{}.quit", this);
|
||||||
callback = null;
|
callback = null;
|
||||||
if (isSet(ctx)) ctx.invalidate();
|
if (isSet(ctx)) ctx.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Route prepareRoute(Context context) {
|
|
||||||
if (isNull(context) || context.invalidated()) return null;
|
|
||||||
Route route = chooseRoute(context);
|
|
||||||
if (isNull(route)) return null;
|
|
||||||
context.route(route);
|
|
||||||
if (!route.reserveFor(context)) {
|
|
||||||
route.reset();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (!route.prepareAndLock()) {
|
|
||||||
route.reset();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return route;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setContext(Context context) {
|
public void setContext(Context context) {
|
||||||
ctx = context;
|
ctx = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean setCallback(Callback callback) {
|
public void setCallback(Callback callback) {
|
||||||
if (ctx.invalidated()) return false;
|
if (!ctx.invalidated()) this.callback = callback;
|
||||||
this.callback = callback;
|
|
||||||
if (searching) return false; // search already running, do not start again!
|
|
||||||
searching = true;
|
|
||||||
Route route = prepareRoute(ctx);
|
|
||||||
searching = false;
|
|
||||||
if (isNull(route) || isNull(callback)) return false;
|
|
||||||
callback.routePrepared(route);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSearching() {
|
|
||||||
return searching;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start(Callback callback) {
|
public void start(Callback callback) {
|
||||||
Thread thread = new Thread() {
|
|
||||||
public void run() {
|
|
||||||
setCallback(callback);
|
setCallback(callback);
|
||||||
|
new Thread(Application.threadName(this)) {
|
||||||
|
public void run() {
|
||||||
|
prepareRoute();
|
||||||
};
|
};
|
||||||
};
|
}.start();
|
||||||
thread.setName(getClass().getSimpleName() + "(" + ctx.train() + ")");
|
}
|
||||||
thread.start();
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getClass().getSimpleName() + "(" + ctx.train() + ")";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ public abstract class Block extends StretchableTile{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return trains.toString();
|
return trains.stream().map(t -> t+"→"+directionOf(t)).reduce((s1,s2) -> s1+", "+s2).orElse(t("empty"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static final String ALLOW_TURN = "allowTurn";
|
private static final String ALLOW_TURN = "allowTurn";
|
||||||
@@ -192,6 +192,7 @@ public abstract class Block extends StretchableTile{
|
|||||||
private Vector<WaitTime> waitTimes = new Vector<WaitTime>();
|
private Vector<WaitTime> waitTimes = new Vector<WaitTime>();
|
||||||
|
|
||||||
public void add(Train train,Direction direction) {
|
public void add(Train train,Direction direction) {
|
||||||
|
if (isNull(train)) return;
|
||||||
train.register();
|
train.register();
|
||||||
trains.add(train,direction);
|
trains.add(train,direction);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ public class Contact extends Tile{
|
|||||||
boolean aborted = false;
|
boolean aborted = false;
|
||||||
|
|
||||||
public OffTimer() {
|
public OffTimer() {
|
||||||
setName(Application.threadName("OffTimer("+Contact.this+")"));
|
super(Application.threadName("OffTimer("+Contact.this+")"));
|
||||||
start();
|
start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +112,12 @@ public class Contact extends Tile{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object click(boolean shift) throws IOException {
|
public Object click(boolean shift) throws IOException {
|
||||||
if (!shift) trigger(200);
|
if (!shift) new Thread(Application.threadName(this)) {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
trigger(200);
|
||||||
|
}
|
||||||
|
}.start();
|
||||||
return super.click(shift);
|
return super.click(shift);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ public class Switch extends Tile{
|
|||||||
public void state(boolean newState) {
|
public void state(boolean newState) {
|
||||||
state = newState;
|
state = newState;
|
||||||
|
|
||||||
Thread thread = new Thread() {
|
new Thread(Application.threadName(this)) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
@@ -173,9 +173,7 @@ public class Switch extends Tile{
|
|||||||
actionsOn.fire(context,Switch.this);
|
actionsOn.fire(context,Switch.this);
|
||||||
} else actionsOff.fire(context,Switch.this);
|
} else actionsOff.fire(context,Switch.this);
|
||||||
}
|
}
|
||||||
};
|
}.start();
|
||||||
thread.setName(Application.threadName(this));
|
|
||||||
thread.start();
|
|
||||||
stream();
|
stream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -161,6 +161,7 @@ public abstract class Turnout extends Tile implements Device{
|
|||||||
public Reply state(State newState) {
|
public Reply state(State newState) {
|
||||||
if (is(Status.LOCKED,Status.OCCUPIED) && newState != state) return new Reply(415, t("{} locked by {}!",this,train()));
|
if (is(Status.LOCKED,Status.OCCUPIED) && newState != state) return new Reply(415, t("{} locked by {}!",this,train()));
|
||||||
if (address == 0) {
|
if (address == 0) {
|
||||||
|
sleep(300);
|
||||||
state = newState;
|
state = newState;
|
||||||
plan.place(this);
|
plan.place(this);
|
||||||
return new Reply(200,"OK");
|
return new Reply(200,"OK");
|
||||||
|
|||||||
Reference in New Issue
Block a user