dunno what to write, this is a non-clean state...
This commit is contained in:
@@ -91,6 +91,8 @@ public class Route extends BaseClass {
|
|||||||
private Block startBlock = null;
|
private Block startBlock = null;
|
||||||
public Direction startDirection;
|
public Direction startDirection;
|
||||||
private HashSet<Contact> triggeredContacts = new HashSet<>();
|
private HashSet<Contact> triggeredContacts = new HashSet<>();
|
||||||
|
|
||||||
|
private Route nextRoute;
|
||||||
|
|
||||||
public Route() {
|
public Route() {
|
||||||
conditions = new ConditionList();
|
conditions = new ConditionList();
|
||||||
@@ -404,6 +406,10 @@ public class Route extends BaseClass {
|
|||||||
return sb.toString().trim();
|
return sb.toString().trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Route getNextRoute() {
|
||||||
|
return nextRoute;
|
||||||
|
}
|
||||||
|
|
||||||
public Id id() {
|
public Id id() {
|
||||||
if (isNull(id)) id = new Id(""+(generateName().hashCode()));
|
if (isNull(id)) id = new Id(""+(generateName().hashCode()));
|
||||||
return id;
|
return id;
|
||||||
@@ -775,6 +781,11 @@ 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) {
|
||||||
|
this.nextRoute = nextRoute;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean setSignals(String state) {
|
public boolean setSignals(String state) {
|
||||||
LOG.debug("{}.setSignals({})",this,state);
|
LOG.debug("{}.setSignals({})",this,state);
|
||||||
for (Signal signal : signals) {
|
for (Signal signal : signals) {
|
||||||
@@ -862,4 +873,8 @@ public class Route extends BaseClass {
|
|||||||
super.update(params);
|
super.update(params);
|
||||||
return properties();
|
return properties();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer waitTime() {
|
||||||
|
return isNull(context) ? null : context.waitTime();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ public class PreserveRoute extends Action {
|
|||||||
return false; // train is expected to wait in next block.
|
return false; // train is expected to wait in next block.
|
||||||
}
|
}
|
||||||
|
|
||||||
train.reserveRouteAfter(route);
|
return route.prepareNext(train);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ 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;
|
import de.srsoftware.web4rail.threads.RouteManager;
|
||||||
|
import de.srsoftware.web4rail.threads.RouteManager.Callback;
|
||||||
import de.srsoftware.web4rail.tiles.Block;
|
import de.srsoftware.web4rail.tiles.Block;
|
||||||
import de.srsoftware.web4rail.tiles.Contact;
|
import de.srsoftware.web4rail.tiles.Contact;
|
||||||
import de.srsoftware.web4rail.tiles.Tile;
|
import de.srsoftware.web4rail.tiles.Tile;
|
||||||
@@ -61,7 +62,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
private Route route;
|
private Route route;
|
||||||
|
|
||||||
private Direction direction;
|
private Direction direction;
|
||||||
|
private boolean autopilot;
|
||||||
private static final String PUSH_PULL = "pushPull";
|
private static final String PUSH_PULL = "pushPull";
|
||||||
public boolean pushPull = false;
|
public boolean pushPull = false;
|
||||||
|
|
||||||
@@ -93,6 +94,8 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
|
|
||||||
private HashSet<Tile> stuckTrace = null;
|
private HashSet<Tile> stuckTrace = null;
|
||||||
|
|
||||||
|
private Route nextRoute;
|
||||||
|
|
||||||
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);
|
||||||
if (isNull(action)) return t("No action passed to Train.action!");
|
if (isNull(action)) return t("No action passed to Train.action!");
|
||||||
@@ -403,12 +406,18 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
|
|
||||||
public void endRoute(Block endBlock, Direction endDirection) {
|
public void endRoute(Block endBlock, Direction endDirection) {
|
||||||
setSpeed(0);
|
setSpeed(0);
|
||||||
|
nextRoute = route.getNextRoute();
|
||||||
|
Integer waitTime = route.waitTime();
|
||||||
route = null;
|
route = null;
|
||||||
direction = endDirection;
|
direction = endDirection;
|
||||||
endBlock.add(this, direction);
|
endBlock.add(this, direction);
|
||||||
currentBlock = endBlock;
|
currentBlock = endBlock;
|
||||||
trace.add(endBlock);
|
trace.add(endBlock);
|
||||||
stuckTrace = null;
|
stuckTrace = null;
|
||||||
|
if (autopilot) {
|
||||||
|
if (isSet(waitTime) && waitTime > 0) sleep(waitTime);
|
||||||
|
start(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tag faster(int steps) {
|
private Tag faster(int steps) {
|
||||||
@@ -715,10 +724,6 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
return tags().iterator();
|
return tags().iterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reserveRouteAfter(Route r) {
|
|
||||||
LOG.debug("reserveRouteAfter({})",r);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This turns the train as if it went through a loop. Example:
|
* This turns the train as if it went through a loop. Example:
|
||||||
* before: CabCar→ MiddleCar→ Loco→
|
* before: CabCar→ MiddleCar→ Loco→
|
||||||
@@ -864,9 +869,20 @@ 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);
|
autopilot |= auto;
|
||||||
routeManager.setAuto(auto).start();
|
if (isSet(nextRoute) && nextRoute.start()) {
|
||||||
plan.stream(t("Started {}",this));
|
nextRoute = null;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (isNull(routeManager)) routeManager = new RouteManager();
|
||||||
|
routeManager.setContext(new Context(this).block(currentBlock).direction(direction));
|
||||||
|
routeManager.start(new Callback() {
|
||||||
|
@Override
|
||||||
|
public void routePrepared(Route route) {
|
||||||
|
route.start();
|
||||||
|
plan.stream(t("Started {}",Train.this));
|
||||||
|
}
|
||||||
|
});
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -999,6 +1015,6 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean usesAutopilot() {
|
public boolean usesAutopilot() {
|
||||||
return isSet(routeManager) && routeManager.autoEnabled();
|
return autopilot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,202 +16,193 @@ import de.srsoftware.web4rail.moving.Train;
|
|||||||
import de.srsoftware.web4rail.tiles.Block;
|
import de.srsoftware.web4rail.tiles.Block;
|
||||||
import de.srsoftware.web4rail.tiles.Tile;
|
import de.srsoftware.web4rail.tiles.Tile;
|
||||||
|
|
||||||
public class RouteManager extends BaseClass implements Runnable {
|
public class RouteManager extends BaseClass {
|
||||||
|
|
||||||
enum State {
|
|
||||||
ENDED,IDLE,STARTED;
|
|
||||||
}
|
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(RouteManager.class);
|
|
||||||
private static final int DEFAULT_PAUSE_TIME = 250; // ms
|
|
||||||
private State state = State.IDLE;
|
|
||||||
private boolean autopilot;
|
|
||||||
private Context context;
|
|
||||||
private int time = 0;
|
|
||||||
|
|
||||||
public RouteManager(Train train) {
|
public static abstract class Callback {
|
||||||
context = new Context(train);
|
public abstract void routePrepared(Route route);
|
||||||
state = State.STARTED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static TreeMap<Integer,List<Route>> availableRoutes(Context context,HashSet<Route> visitedRoutes){
|
private static final Logger LOG = LoggerFactory.getLogger(RouteManager.class);
|
||||||
|
private Context ctx;
|
||||||
|
private Callback callback;
|
||||||
|
private boolean active;
|
||||||
|
|
||||||
|
public RouteManager() {
|
||||||
|
active = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static TreeMap<Integer, List<Route>> availableRoutes(Context context, HashSet<Route> visitedRoutes) {
|
||||||
String inset = "";
|
String inset = "";
|
||||||
for (int i=0; i<visitedRoutes.size(); i++) inset+=" ";
|
for (int i = 0; i < visitedRoutes.size(); i++) inset += " ";
|
||||||
LOG.debug("{}{}.availableRoutes({})",inset,RouteManager.class.getSimpleName(),context);
|
LOG.debug("{}{}.availableRoutes({})", inset, RouteManager.class.getSimpleName(), context);
|
||||||
|
|
||||||
Block block = context.block();
|
Block block = context.block();
|
||||||
Train train = context.train();
|
Train train = context.train();
|
||||||
Direction startDirection = context.direction();
|
Direction startDirection = context.direction();
|
||||||
Route currentRoute = context.route();
|
Route currentRoute = context.route();
|
||||||
TreeMap<Integer,List<Route>> availableRoutes = new TreeMap<Integer, List<Route>>();
|
TreeMap<Integer, List<Route>> availableRoutes = new TreeMap<Integer, List<Route>>();
|
||||||
|
|
||||||
boolean error = false;
|
boolean error = false;
|
||||||
if (isNull(block) && (error = true)) LOG.warn("{} → {}.availableRoutes called without context.block!",inset,Train.class.getSimpleName());
|
if (isNull(block) && (error = true))
|
||||||
if (isNull(train) && (error = true)) LOG.warn("{}→ {}.availableRoutes called without context.train!", inset,Train.class.getSimpleName());
|
LOG.warn("{} → {}.availableRoutes called without context.block!", inset, Train.class.getSimpleName());
|
||||||
|
if (isNull(train) && (error = true))
|
||||||
|
LOG.warn("{}→ {}.availableRoutes called without context.train!", inset, Train.class.getSimpleName());
|
||||||
if (error) return availableRoutes;
|
if (error) return availableRoutes;
|
||||||
|
|
||||||
Block destination = train.destination();
|
Block destination = train.destination();
|
||||||
if (isSet(startDirection)) {
|
if (isSet(startDirection)) {
|
||||||
LOG.debug("{}- Looking for {}-bound routes from {}",inset,startDirection,block);
|
LOG.debug("{}- Looking for {}-bound routes from {}", inset, startDirection, block);
|
||||||
} else {
|
} else {
|
||||||
LOG.debug("{}- Looking for all routes from {}",inset,block);
|
LOG.debug("{}- Looking for all routes from {}", inset, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isSet(destination) && visitedRoutes.isEmpty()) LOG.debug("{}- Destination: {}",inset,destination);
|
if (isSet(destination) && visitedRoutes.isEmpty()) LOG.debug("{}- Destination: {}", inset, destination);
|
||||||
|
|
||||||
for (Route routeCandidate : block.leavingRoutes()) {
|
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());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
HashSet<Tile> stuckTrace = train.stuckTrace(); // if train has been stopped in between two blocks lastly: only allow routes that do not conflict with current train position
|
HashSet<Tile> stuckTrace = train.stuckTrace(); // if train has been stopped in between two blocks lastly:
|
||||||
|
// only allow routes that do not conflict with current train
|
||||||
|
// position
|
||||||
if (isSet(stuckTrace) && !routeCandidate.path().containsAll(stuckTrace)) {
|
if (isSet(stuckTrace) && !routeCandidate.path().containsAll(stuckTrace)) {
|
||||||
LOG.debug("Stuck train occupies tiles ({}) outside of {} – not allowed.",stuckTrace,routeCandidate);
|
LOG.debug("Stuck train occupies tiles ({}) outside of {} – not allowed.", stuckTrace, routeCandidate);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!routeCandidate.allowed(context)) {
|
if (!routeCandidate.allowed(context)) {
|
||||||
if (routeCandidate.endBlock() != destination) { // allowance may be overridden by destination
|
if (routeCandidate.endBlock() != destination) { // allowance may be overridden by destination
|
||||||
LOG.debug("{} not allowed for {}",routeCandidate,context);
|
LOG.debug("{} not allowed for {}", routeCandidate, context);
|
||||||
continue; // Zug darf auf Grund einer nicht erfüllten Bedingung nicht auf die Route
|
continue; // Zug darf auf Grund einer nicht erfüllten Bedingung nicht auf die Route
|
||||||
}
|
}
|
||||||
LOG.debug("{} not allowed for {} – overridden by selected destination",routeCandidate,context);
|
LOG.debug("{} not allowed for {} – overridden by selected destination", routeCandidate, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
int priority = 0;
|
int priority = 0;
|
||||||
if (isSet(startDirection) && routeCandidate.startDirection != startDirection) { // Route startet entgegen der aktuellen Fahrtrichtung des Zuges
|
if (isSet(startDirection) && routeCandidate.startDirection != startDirection) { // Route startet entgegen
|
||||||
|
// der aktuellen
|
||||||
|
// Fahrtrichtung des Zuges
|
||||||
if (!train.pushPull) continue; // Zug kann nicht wenden
|
if (!train.pushPull) continue; // Zug kann nicht wenden
|
||||||
if (!block.turnAllowed) continue; // Wenden im Block nicht gestattet
|
if (!block.turnAllowed) continue; // Wenden im Block nicht gestattet
|
||||||
priority -= 5;
|
priority -= 5;
|
||||||
}
|
}
|
||||||
if (routeCandidate == currentRoute) priority-=10; // möglichst andere Route als zuvor wählen // TODO: den Routen einen "last-used" Zeitstempel hinzufügen, und diesen mit in die Priorisierung einbeziehen
|
if (routeCandidate == currentRoute) priority -= 10; // möglichst andere Route als zuvor wählen // TODO: den
|
||||||
|
// Routen einen "last-used" Zeitstempel hinzufügen, und
|
||||||
|
// diesen mit in die Priorisierung einbeziehen
|
||||||
|
|
||||||
if (isSet(destination)) {
|
if (isSet(destination)) {
|
||||||
if (routeCandidate.endBlock() == destination) { // route goes directly to destination
|
if (routeCandidate.endBlock() == destination) { // route goes directly to destination
|
||||||
LOG.debug("{}→ Candidate {} directly leads to {}",inset,routeCandidate.shortName(),destination);
|
LOG.debug("{}→ Candidate {} directly leads to {}", inset, routeCandidate.shortName(), destination);
|
||||||
priority = 1_000_000;
|
priority = 1_000_000;
|
||||||
} else {
|
} else {
|
||||||
LOG.debug("{}- Candidate: {}",inset,routeCandidate.shortName());
|
LOG.debug("{}- Candidate: {}", inset, routeCandidate.shortName());
|
||||||
Context forwardContext = new Context(train).block(routeCandidate.endBlock()).route(null).direction(routeCandidate.endDirection);
|
Context forwardContext = new Context(train).block(routeCandidate.endBlock()).route(null)
|
||||||
|
.direction(routeCandidate.endDirection);
|
||||||
visitedRoutes.add(routeCandidate);
|
visitedRoutes.add(routeCandidate);
|
||||||
TreeMap<Integer, List<Route>> forwardRoutes = availableRoutes(forwardContext,visitedRoutes);
|
TreeMap<Integer, List<Route>> forwardRoutes = availableRoutes(forwardContext, visitedRoutes);
|
||||||
visitedRoutes.remove(routeCandidate);
|
visitedRoutes.remove(routeCandidate);
|
||||||
if (forwardRoutes.isEmpty()) continue; // the candidate does not lead to a block, from which routes to the destination exist
|
if (forwardRoutes.isEmpty()) continue; // the candidate does not lead to a block, from which routes
|
||||||
|
// to the destination exist
|
||||||
Entry<Integer, List<Route>> entry = forwardRoutes.lastEntry();
|
Entry<Integer, List<Route>> entry = forwardRoutes.lastEntry();
|
||||||
LOG.debug("{}→ The following routes have connections to {}:",inset,destination);
|
LOG.debug("{}→ The following routes have connections to {}:", inset, destination);
|
||||||
for (Route rt: entry.getValue()) LOG.debug("{} - {}",inset,rt.shortName());
|
for (Route rt : entry.getValue()) LOG.debug("{} - {}", inset, rt.shortName());
|
||||||
priority += entry.getKey()-10;
|
priority += entry.getKey() - 10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Route> routeSet = availableRoutes.get(priority);
|
List<Route> routeSet = availableRoutes.get(priority);
|
||||||
if (isNull(routeSet)) {
|
if (isNull(routeSet)) {
|
||||||
routeSet = new Vector<Route>();
|
routeSet = new Vector<Route>();
|
||||||
availableRoutes.put(priority, routeSet);
|
availableRoutes.put(priority, routeSet);
|
||||||
}
|
}
|
||||||
routeSet.add(routeCandidate);
|
routeSet.add(routeCandidate);
|
||||||
if (routeCandidate.endBlock() == destination) break; // direct connection to destination discovered, quit search
|
if (routeCandidate.endBlock() == destination) break; // direct connection to destination discovered, quit
|
||||||
|
// search
|
||||||
}
|
}
|
||||||
if (!availableRoutes.isEmpty()) LOG.debug("{}→ Routes from {}: {}",inset,block,availableRoutes.isEmpty()?"none":"");
|
if (!availableRoutes.isEmpty())
|
||||||
|
LOG.debug("{}→ Routes from {}: {}", inset, block, availableRoutes.isEmpty() ? "none" : "");
|
||||||
for (Entry<Integer, List<Route>> entry : availableRoutes.entrySet()) {
|
for (Entry<Integer, List<Route>> entry : availableRoutes.entrySet()) {
|
||||||
LOG.debug("{} - Priority {}:",inset,entry.getKey());
|
LOG.debug("{} - Priority {}:", inset, entry.getKey());
|
||||||
for (Route r : entry.getValue()) LOG.debug("{} - {}",inset,r.shortName());
|
for (Route r : entry.getValue()) LOG.debug("{} - {}", inset, r.shortName());
|
||||||
}
|
}
|
||||||
return availableRoutes;
|
return availableRoutes;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean autoEnabled() {
|
|
||||||
return autopilot && isActive();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Route chooseRoute(Context context) {
|
public static Route chooseRoute(Context context) {
|
||||||
LOG.debug("{}.chooseRoute({})",RouteManager.class.getSimpleName(),context);
|
LOG.debug("{}.chooseRoute({})", RouteManager.class.getSimpleName(), context);
|
||||||
TreeMap<Integer, List<Route>> availableRoutes = availableRoutes(context,new HashSet<Route>());
|
TreeMap<Integer, List<Route>> availableRoutes = availableRoutes(context, new HashSet<Route>());
|
||||||
while (!availableRoutes.isEmpty()) {
|
while (!availableRoutes.isEmpty()) {
|
||||||
if (context.invalidated()) break;
|
if (context.invalidated()) break;
|
||||||
LOG.debug("availableRoutes: {}",availableRoutes);
|
LOG.debug("availableRoutes: {}", availableRoutes);
|
||||||
Entry<Integer, List<Route>> entry = availableRoutes.lastEntry();
|
Entry<Integer, List<Route>> entry = availableRoutes.lastEntry();
|
||||||
List<Route> preferredRoutes = entry.getValue();
|
List<Route> preferredRoutes = entry.getValue();
|
||||||
LOG.debug("preferredRoutes: {}",preferredRoutes);
|
LOG.debug("preferredRoutes: {}", preferredRoutes);
|
||||||
Route selectedRoute = preferredRoutes.get(random.nextInt(preferredRoutes.size()));
|
Route selectedRoute = preferredRoutes.get(random.nextInt(preferredRoutes.size()));
|
||||||
if (selectedRoute.isFreeFor(context)) {
|
if (selectedRoute.isFreeFor(context)) {
|
||||||
LOG.debug("Chose \"{}\" with priority {}.",selectedRoute,entry.getKey());
|
LOG.debug("Chose \"{}\" with priority {}.", selectedRoute, entry.getKey());
|
||||||
return selectedRoute;
|
return selectedRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug("Selected route \"{}\" is not free for {}",selectedRoute,context);
|
LOG.debug("Selected route \"{}\" is not free for {}", selectedRoute, context);
|
||||||
preferredRoutes.remove(selectedRoute);
|
preferredRoutes.remove(selectedRoute);
|
||||||
if (preferredRoutes.isEmpty()) availableRoutes.remove(availableRoutes.lastKey());
|
if (preferredRoutes.isEmpty()) availableRoutes.remove(availableRoutes.lastKey());
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isActive() {
|
|
||||||
switch (state) {
|
|
||||||
case ENDED:
|
|
||||||
return false;
|
|
||||||
case IDLE:
|
|
||||||
return false;
|
|
||||||
default:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void pause(){
|
|
||||||
if (time == 0) {
|
|
||||||
time = DEFAULT_PAUSE_TIME;
|
|
||||||
} else sleep(time);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void quit() {
|
public void quit() {
|
||||||
LOG.debug("{}.quit",this);
|
LOG.debug("{}.quit", this);
|
||||||
autopilot = false;
|
callback = null;
|
||||||
context.invalidate();
|
if (isSet(ctx)) ctx.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public Route prepareRoute(Context context) {
|
||||||
public void run() {
|
|
||||||
Train train = context.train();
|
|
||||||
try {
|
try {
|
||||||
do {
|
if (isNull(context) || context.invalidated()) return null;
|
||||||
pause();
|
Route route = chooseRoute(context);
|
||||||
if (isSet(train.route())) continue;
|
if (isNull(route)) return null;
|
||||||
if (context.invalidated()) return;
|
context.route(route);
|
||||||
context.block(train.currentBlock()).direction(train.direction());
|
if (!route.reserveFor(context)) {
|
||||||
Route route = chooseRoute(context);
|
route.reset();
|
||||||
if (isNull(route)) continue;
|
return null;
|
||||||
context.route(route);
|
}
|
||||||
if (!route.reserveFor(context)) {
|
if (!route.prepareAndLock()) {
|
||||||
route.reset();
|
route.reset();
|
||||||
continue;
|
return null;
|
||||||
}
|
}
|
||||||
if (!route.prepareAndLock()) {
|
|
||||||
route.reset();
|
return route;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
// Route reserved, prepared and locked:
|
|
||||||
if (!route.start()) {
|
|
||||||
route.reset();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
} while (autopilot);
|
|
||||||
} finally {
|
} finally {
|
||||||
// do not invalidate context here: may be used in delayed actions called from (successful) start
|
active = false;
|
||||||
state = State.ENDED;
|
|
||||||
train.removeChild(this);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public RouteManager setAuto(boolean auto) {
|
public void setContext(Context context) {
|
||||||
LOG.debug("{}abled autopilot of {}",auto?"En":"Dis");
|
ctx = context;
|
||||||
autopilot = auto;
|
|
||||||
return this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void setCallback(Callback callback) {
|
||||||
Thread thread = new Thread(this);
|
if (ctx.invalidated()) return;
|
||||||
thread.setName(context.train().name());
|
if (isNull(this.callback)) {
|
||||||
|
Route route = prepareRoute(ctx);
|
||||||
|
if (isSet(route) && isSet(callback)) callback.routePrepared(route);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isActive() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void start(Callback callback) {
|
||||||
|
Thread thread = new Thread() {
|
||||||
|
public void run() {
|
||||||
|
setCallback(callback);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
thread.setName(getClass().getSimpleName() + "(" + ctx.train() + ")");
|
||||||
thread.start();
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user