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.4.8</version>
|
<version>1.4.9</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>
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ public interface Constants {
|
|||||||
public static final String ACTION_DROP = "drop";
|
public static final String ACTION_DROP = "drop";
|
||||||
public static final String ACTION_EMERGENCY = "emergency";
|
public static final String ACTION_EMERGENCY = "emergency";
|
||||||
public static final String ACTION_FASTER10 = "faster10";
|
public static final String ACTION_FASTER10 = "faster10";
|
||||||
|
public static final String ACTION_FREE = "free";
|
||||||
public static final String ACTION_MOVE = "move";
|
public static final String ACTION_MOVE = "move";
|
||||||
public static final String ACTION_OPEN = "open";
|
public static final String ACTION_OPEN = "open";
|
||||||
public static final String ACTION_POWER = "power";
|
public static final String ACTION_POWER = "power";
|
||||||
|
|||||||
@@ -203,6 +203,10 @@ public class Plan extends BaseClass{
|
|||||||
Tile tile = get(Id.from(params), false);
|
Tile tile = get(Id.from(params), false);
|
||||||
if (tile instanceof Bridge) return ((Bridge)tile).requestConnect();
|
if (tile instanceof Bridge) return ((Bridge)tile).requestConnect();
|
||||||
break;
|
break;
|
||||||
|
case ACTION_FREE:
|
||||||
|
Tile t = get(Id.from(params), false);
|
||||||
|
t.free(t.lockingTrain());
|
||||||
|
return t.properties();
|
||||||
case ACTION_MOVE:
|
case ACTION_MOVE:
|
||||||
return moveTile(params.get(DIRECTION),Id.from(params));
|
return moveTile(params.get(DIRECTION),Id.from(params));
|
||||||
case ACTION_PROPS:
|
case ACTION_PROPS:
|
||||||
|
|||||||
@@ -873,6 +873,7 @@ public class Route extends BaseClass {
|
|||||||
triggeredContacts.clear();
|
triggeredContacts.clear();
|
||||||
|
|
||||||
ActionList startActions = triggeredActions.get(ROUTE_START);
|
ActionList startActions = triggeredActions.get(ROUTE_START);
|
||||||
|
if (train.direction() != startDirection) train.turn();
|
||||||
|
|
||||||
if (isSet(startActions)) {
|
if (isSet(startActions)) {
|
||||||
context.route(this);
|
context.route(this);
|
||||||
|
|||||||
@@ -497,7 +497,7 @@ public class Train extends BaseClass implements Comparable<Train> {
|
|||||||
Integer waitTime = route.waitTime();
|
Integer waitTime = route.waitTime();
|
||||||
nextPreparedRoute = route.dropNextPreparedRoute();
|
nextPreparedRoute = route.dropNextPreparedRoute();
|
||||||
if (isSet(nextPreparedRoute)) LOG.debug("nextPreparedRoute is now {}",nextPreparedRoute);
|
if (isSet(nextPreparedRoute)) LOG.debug("nextPreparedRoute is now {}",nextPreparedRoute);
|
||||||
if ((!autopilot)|| isNull(nextPreparedRoute) || (isSet(waitTime) && waitTime > 0)) setSpeed(0);
|
if ((!autopilot) || isNull(nextPreparedRoute) || (isSet(waitTime) && waitTime > 0)) setSpeed(0);
|
||||||
route = null;
|
route = null;
|
||||||
endBlock.setTrain(this);
|
endBlock.setTrain(this);
|
||||||
currentBlock = endBlock;
|
currentBlock = endBlock;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import de.srsoftware.web4rail.Application;
|
import de.srsoftware.web4rail.Application;
|
||||||
import de.srsoftware.web4rail.BaseClass;
|
import de.srsoftware.web4rail.BaseClass;
|
||||||
@@ -30,7 +31,7 @@ public class RoutePrepper extends BaseClass implements Runnable{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return route+"(score: "+score+")";
|
return route.toString().replace(")", ", score: "+score+")");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,17 +56,17 @@ public class RoutePrepper extends BaseClass implements Runnable{
|
|||||||
boolean error = false;
|
boolean error = false;
|
||||||
|
|
||||||
Block startBlock = c.block();
|
Block startBlock = c.block();
|
||||||
if (isNull(startBlock) && (error=true)) LOG.warn("RoutePrepper.findRoute(…) called without a startBlock!");
|
if (isNull(startBlock) && (error=true)) LOG.warn("RoutePrepper.availableRoutes(…) called without a startBlock!");
|
||||||
|
|
||||||
Train train = c.train();
|
Train train = c.train();
|
||||||
if (isNull(train) && (error=true)) LOG.warn("RoutePrepper.findRoute(…) called without a startBlock!");
|
if (isNull(train) && (error=true)) LOG.warn("RoutePrepper.availableRoutes(…) called without a startBlock!");
|
||||||
|
|
||||||
if (error) return new TreeMap<>();
|
if (error) return new TreeMap<>();
|
||||||
|
|
||||||
Block destination = train.destination();
|
Block destination = train.destination();
|
||||||
|
|
||||||
Direction startDirection = c.direction();
|
Direction startDirection = c.direction();
|
||||||
LOG.debug("RoutePrepper.findRoute({},{},{}), dest = {}",startBlock,startDirection,train,destination);
|
LOG.debug("RoutePrepper.availableRoutes({},{},{}), dest = {}",startBlock,startDirection,train,destination);
|
||||||
|
|
||||||
TreeMap<Integer, LinkedList<Route>> candidates = routesFrom(c);
|
TreeMap<Integer, LinkedList<Route>> candidates = routesFrom(c);
|
||||||
|
|
||||||
@@ -76,12 +77,23 @@ public class RoutePrepper extends BaseClass implements Runnable{
|
|||||||
|
|
||||||
LOG.debug("{} is heading for {}, starting breadth-first search…",train,destination);
|
LOG.debug("{} is heading for {}, starting breadth-first search…",train,destination);
|
||||||
|
|
||||||
HashMap<Route,Candidate> predecessors = new HashMap<>();
|
HashMap<Route,Candidate> predecessors = new HashMap<>() {
|
||||||
|
public String toString() {
|
||||||
|
return entrySet().stream()
|
||||||
|
.sorted((e1,e2) -> e1.getValue().toString().compareTo(e2.getValue().toString()))
|
||||||
|
.map(entry -> entry.getValue()+" → "+entry.getKey())
|
||||||
|
.collect(Collectors.joining("\n"));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
candidates.entrySet().stream().flatMap(entry -> entry.getValue().stream()).forEach(route -> predecessors.put(route, null));
|
||||||
TreeMap<Integer,LinkedList<Route>> routesToDest = new TreeMap<>();
|
TreeMap<Integer,LinkedList<Route>> routesToDest = new TreeMap<>();
|
||||||
|
|
||||||
int level = 0;
|
int level = 0;
|
||||||
|
|
||||||
while (!candidates.isEmpty()) {
|
while (!candidates.isEmpty()) {
|
||||||
|
LOG.debug("Candidates for level {}:",level);
|
||||||
|
candidates.entrySet().stream().flatMap(entry -> entry.getValue().stream()).forEach(route -> LOG.debug(" - {}",route));
|
||||||
|
|
||||||
TreeMap<Integer, LinkedList<Route>> queue = new TreeMap<>();
|
TreeMap<Integer, LinkedList<Route>> queue = new TreeMap<>();
|
||||||
|
|
||||||
while (!candidates.isEmpty()) {
|
while (!candidates.isEmpty()) {
|
||||||
@@ -99,8 +111,10 @@ public class RoutePrepper extends BaseClass implements Runnable{
|
|||||||
// However it might be the last route in a long path.
|
// However it might be the last route in a long path.
|
||||||
// Thus, we need to get the first route in this path:
|
// Thus, we need to get the first route in this path:
|
||||||
while (predecessors.containsKey(candidate.route)) {
|
while (predecessors.containsKey(candidate.route)) {
|
||||||
candidate = predecessors.get(candidate.route);
|
Candidate predecessor = predecessors.get(candidate.route);
|
||||||
LOG.debug(" - predecessed by {}",candidate);
|
if (isNull(predecessor)) break;
|
||||||
|
LOG.debug(" - {} is predecessed by {}",candidate,predecessor);
|
||||||
|
candidate = predecessor;
|
||||||
score += candidate.score;
|
score += candidate.score;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,15 +125,18 @@ public class RoutePrepper extends BaseClass implements Runnable{
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.debug(" - {} not reaching {}, adding ongoing routes to queue:",candidate,destination);
|
LOG.debug(" - {} not reaching {}, adding ongoing routes to queue:",candidate,destination);
|
||||||
TreeMap<Integer, LinkedList<Route>> successors = routesFrom(c.clone().block(endBlock).direction(endDir));
|
TreeMap<Integer, LinkedList<Route>> successors = routesFrom(c.clone().block(endBlock).direction(endDir));
|
||||||
while (!successors.isEmpty()) {
|
while (!successors.isEmpty()) {
|
||||||
int score = successors.firstKey();
|
int score = successors.firstKey();
|
||||||
LinkedList<Route> best = successors.remove(score);
|
LinkedList<Route> best = successors.remove(score);
|
||||||
score -= 25; // Nachfolgeroute
|
score -= 25; // Nachfolgeroute
|
||||||
for (Route route : best) {
|
for (Route route : best) {
|
||||||
LOG.debug(" - queueing {} with score {}",route,score);
|
LOG.debug(" - queueing {} with score {}",route,score);
|
||||||
if (predecessors.containsKey(route)) continue; // Route wurde bereits besucht
|
if (predecessors.containsKey(route)) {
|
||||||
|
LOG.debug("this route already has a predecessor: {}",predecessors.get(route));
|
||||||
|
continue; // Route wurde bereits besucht
|
||||||
|
}
|
||||||
predecessors.put(route, candidate);
|
predecessors.put(route, candidate);
|
||||||
|
|
||||||
LinkedList<Route> list = queue.get(score);
|
LinkedList<Route> list = queue.get(score);
|
||||||
@@ -132,11 +149,11 @@ public class RoutePrepper extends BaseClass implements Runnable{
|
|||||||
if (!routesToDest.isEmpty()) return routesToDest;
|
if (!routesToDest.isEmpty()) return routesToDest;
|
||||||
LOG.debug("No routes to {} found with distance {}!",destination,level);
|
LOG.debug("No routes to {} found with distance {}!",destination,level);
|
||||||
level ++;
|
level ++;
|
||||||
candidates = queue;
|
candidates = queue;
|
||||||
}
|
}
|
||||||
LOG.debug("No more candidates for routes towards {}!",destination);
|
LOG.debug("No more candidates for routes towards {}!",destination);
|
||||||
|
|
||||||
return new TreeMap<>();
|
return routesToDest;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -244,19 +261,19 @@ public class RoutePrepper extends BaseClass implements Runnable{
|
|||||||
|
|
||||||
Direction startDirection = c.direction();
|
Direction startDirection = c.direction();
|
||||||
|
|
||||||
LOG.debug("RoutePrepper.routesFrom({},{},{}), dest = {}",startBlock,startDirection,train,destination);
|
LOG.debug(" RoutePrepper.routesFrom({},{},{}), dest = {}",startBlock,startDirection,train,destination);
|
||||||
|
|
||||||
TreeMap<Integer, LinkedList<Route>> routes = new TreeMap<>();
|
TreeMap<Integer, LinkedList<Route>> routes = new TreeMap<>();
|
||||||
|
|
||||||
for (Route route : startBlock.leavingRoutes()) {
|
for (Route route : startBlock.leavingRoutes()) {
|
||||||
LOG.debug(" - evaluating {}",route);
|
LOG.debug(" - evaluating {}",route);
|
||||||
|
|
||||||
int score = 0;
|
int score = 0;
|
||||||
|
|
||||||
if (!route.allowed(new Context(train).block(startBlock).direction(startDirection))) {
|
if (!route.allowed(new Context(train).block(startBlock).direction(startDirection))) {
|
||||||
LOG.debug(" - {} not allowed for {}", route, train);
|
LOG.debug(" - {} not allowed for {}", route, train);
|
||||||
if (route.endBlock() != destination) continue;
|
if (route.endBlock() != destination) continue;
|
||||||
LOG.debug(" …overridden by destination of train!", route, train);
|
LOG.debug(" …overridden by destination of train!", route, train);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (route.endBlock() == destination) score = 100_000;
|
if (route.endBlock() == destination) score = 100_000;
|
||||||
@@ -269,7 +286,7 @@ public class RoutePrepper extends BaseClass implements Runnable{
|
|||||||
|
|
||||||
LinkedList<Route> routesForScore = routes.get(score);
|
LinkedList<Route> routesForScore = routes.get(score);
|
||||||
if (isNull(routesForScore)) routes.put(score, routesForScore = new LinkedList<Route>());
|
if (isNull(routesForScore)) routes.put(score, routesForScore = new LinkedList<Route>());
|
||||||
LOG.debug(" → candidate!");
|
LOG.debug(" → candidate!");
|
||||||
routesForScore.add(route);
|
routesForScore.add(route);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ import java.util.TreeMap;
|
|||||||
|
|
||||||
import org.json.JSONArray;
|
import org.json.JSONArray;
|
||||||
import org.json.JSONObject;
|
import org.json.JSONObject;
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
import de.srsoftware.tools.Tag;
|
import de.srsoftware.tools.Tag;
|
||||||
import de.srsoftware.web4rail.Application;
|
import de.srsoftware.web4rail.Application;
|
||||||
|
|||||||
@@ -290,8 +290,7 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm,
|
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm, String... errors) {
|
||||||
String... errors) {
|
|
||||||
Fieldset fieldset = null;
|
Fieldset fieldset = null;
|
||||||
|
|
||||||
if (isSet(occupyingTrain)) {
|
if (isSet(occupyingTrain)) {
|
||||||
@@ -312,12 +311,13 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
|||||||
if (isSet(fieldset)) preForm.add(fieldset);
|
if (isSet(fieldset)) preForm.add(fieldset);
|
||||||
|
|
||||||
if (isTrack) {
|
if (isTrack) {
|
||||||
formInputs.add(t("Length"),
|
formInputs.add(t("Length"), new Input(LENGTH, length).numeric().addTo(new Tag("span")).content(NBSP + lengthUnit));
|
||||||
new Input(LENGTH, length).numeric().addTo(new Tag("span")).content(NBSP + lengthUnit));
|
|
||||||
Checkbox checkbox = new Checkbox(DISABLED, t("disabled"), disabled);
|
Checkbox checkbox = new Checkbox(DISABLED, t("disabled"), disabled);
|
||||||
if (disabled) checkbox.clazz("disabled");
|
if (disabled) checkbox.clazz("disabled");
|
||||||
formInputs.add(t("State"), checkbox);
|
formInputs.add(t("State"), checkbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isSet(lockingTrain())) formInputs.add(t("Locked by {}",lockingTrain()), button(t("free"), Map.of(REALM,REALM_PLAN,ACTION,ACTION_FREE)));
|
||||||
|
|
||||||
List<Direction> pd = possibleDirections();
|
List<Direction> pd = possibleDirections();
|
||||||
if (!pd.isEmpty()) {
|
if (!pd.isEmpty()) {
|
||||||
|
|||||||
Reference in New Issue
Block a user