diff --git a/pom.xml b/pom.xml index 0603c2f..b374879 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.srsoftware web4rail - 0.11.3 + 0.11.4 Web4Rail jar Java Model Railway Control diff --git a/src/main/java/de/srsoftware/web4rail/BaseClass.java b/src/main/java/de/srsoftware/web4rail/BaseClass.java index e5e424b..70c11c2 100644 --- a/src/main/java/de/srsoftware/web4rail/BaseClass.java +++ b/src/main/java/de/srsoftware/web4rail/BaseClass.java @@ -2,12 +2,15 @@ package de.srsoftware.web4rail; import java.util.HashMap; import java.util.Map; +import java.util.Random; import org.json.JSONObject; import de.srsoftware.tools.Tag; -public class BaseClass implements Constants{ +public abstract class BaseClass implements Constants{ + + public static final Random random = new Random(); public static Tag link(String tagClass,Map params,Object caption) { String json = new JSONObject(params).toString().replace("\"", "'"); diff --git a/src/main/java/de/srsoftware/web4rail/Range.java b/src/main/java/de/srsoftware/web4rail/Range.java index 2d31f59..9f7539c 100644 --- a/src/main/java/de/srsoftware/web4rail/Range.java +++ b/src/main/java/de/srsoftware/web4rail/Range.java @@ -1,7 +1,6 @@ package de.srsoftware.web4rail; import java.util.Map; -import java.util.Random; import org.json.JSONObject; @@ -9,8 +8,7 @@ import org.json.JSONObject; * Class for integer ranges (min…max) * @author Stephan Richter */ -public class Range { - private static final Random random = new Random(); +public class Range extends BaseClass{ private static final String MAX = "max"; private static final String MIN = "min"; diff --git a/src/main/java/de/srsoftware/web4rail/actions/Action.java b/src/main/java/de/srsoftware/web4rail/actions/Action.java index 667650f..62373b0 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/Action.java +++ b/src/main/java/de/srsoftware/web4rail/actions/Action.java @@ -20,6 +20,7 @@ import de.srsoftware.web4rail.Window; import de.srsoftware.web4rail.moving.Train; import de.srsoftware.web4rail.tags.Label; import de.srsoftware.web4rail.tags.Select; +import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.Contact; /** @@ -38,25 +39,48 @@ public abstract class Action extends BaseClass { public Contact contact = null; public Route route = null; public Train train = null; + public Block block = null; public Context(Contact c) { contact = c; - plan = contact.plan(); - route = contact.route(); - if (route == null) return; - train = route.train; + setPlan(contact.plan()); + setRoute(contact.route()); } - + public Context(Train train) { - this.train = train; - if (isSet(train)) plan = train.locos().get(0).plan(); + setTrain(train); } - + public Context(Route route) { + setRoute(route); + } + + private void setRoute(Route route) { this.route = route; - if (isSet(route)) plan = route.path().firstElement().plan(); - train = route.train; + if (isSet(route)) setTrain(route.train); + + } + + private void setTrain(Train train) { + this.train = train; + if (isSet(train)) { + if (isNull(route)) route = train.route; + setBlock(train.currentBlock()); + } + + } + + private void setBlock(Block block) { + this.block = block; + } + + private void setPlan(Plan plan) { + this.plan = plan; } + + + + @Override public String toString() { diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java index ce37280..bee5f4b 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Train.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java @@ -12,8 +12,8 @@ import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Random; import java.util.SortedSet; +import java.util.TreeMap; import java.util.TreeSet; import java.util.Vector; @@ -76,7 +76,7 @@ public class Train extends BaseClass implements Comparable { private HashSet tags = new HashSet(); - private Block block,destination = null; + private Block currentBlock,destination = null; LinkedList trace = new LinkedList(); private class Autopilot extends Thread{ @@ -171,28 +171,55 @@ public class Train extends BaseClass implements Comparable { } showTrace(); } - - private Route chooseRoute(Context context) { - HashSet routes = block.routes(); - Vector availableRoutes = new Vector(); + + private static Route chooseRoute(Context context) { + TreeMap> availableRoutes = availableRoutes(context); + if (availableRoutes.isEmpty()) return null; + Entry> entry = availableRoutes.firstEntry(); + List preferredRoutes = entry.getValue(); + Route selectetRoute = preferredRoutes.get(random.nextInt(preferredRoutes.size())); + LOG.debug("Chose \"{}\" with priority {}.",selectetRoute,entry.getKey()); + + return selectetRoute; + } + + private static TreeMap> availableRoutes(Context context){ + TreeMap> availableRoutes = new TreeMap>(); + + boolean error = false; + if (isNull(context.block)) { + LOG.warn("{}.availableRoutes called without context.block!",Train.class.getSimpleName()); + error = true; + } + if (isNull(context.train)) { + LOG.warn("{}.availableRoutes called without context.train!",Train.class.getSimpleName()); + error = true; + } + if (error) return availableRoutes; + + Collection routes = context.block.routes(); + for (Route rt : routes) { - if (rt == route) continue; // andere Route als zuvor wählen - if (rt.path().firstElement() != block) continue; // keine Route wählen, die nicht vom aktuellen Block des Zuges startet - if (isSet(direction) && rt.startDirection != direction) { // Route ist entgegen der Startrichtung des Zuges - if (!pushPull || !block.turnAllowed) { // Zug ist kein Wendezug oder Block erlaubt kein Wenden - continue; - } + if (rt.path().firstElement() != context.block) continue; // routen, die nicht vom aktuellen Block starten sind bubu + int priority = 0; + if (rt == context.route) 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(context.train.direction) && rt.startDirection != context.train.direction) { // Route startet entgegen der aktuellen Fahrtrichtung des Zuges + if (!context.train.pushPull) continue; // Zug kann nicht wenden + if (!context.block.turnAllowed) continue; // Wenden im Block nicht gestattet + priority -= 5; } - if (!rt.isFreeFor(this)) { // keine belegten Routen wählen -// LOG.debug("{} is not free!",rt); - continue; + if (!rt.isFreeFor(context.train)) continue; // Route ist nicht frei + if (!rt.allowed(context)) continue; // Zug darf auf Grund einer nicht erfüllten Bedingung nicht auf die Route + + List routeSet = availableRoutes.get(priority); + if (isNull(routeSet)) { + routeSet = new Vector(); + availableRoutes.put(priority, routeSet); } - if (!rt.allowed(context)) continue; - availableRoutes.add(rt); + routeSet.add(rt); } - Random rand = new Random(); - if (availableRoutes.isEmpty()) return null; - return availableRoutes.get(rand.nextInt(availableRoutes.size())); + + return availableRoutes; } @Override @@ -303,7 +330,7 @@ public class Train extends BaseClass implements Comparable { public Train heading(Direction dir) { direction = dir; - if (isSet(block)) plan.place(block); + if (isSet(currentBlock)) plan.place(currentBlock); return this; } @@ -316,7 +343,7 @@ public class Train extends BaseClass implements Comparable { json.put(ID, id); json.put(PUSH_PULL, pushPull); - if (isSet(block)) json.put(BLOCK, block.id()); + if (isSet(currentBlock)) json.put(BLOCK, currentBlock.id()); if (isSet(name))json.put(NAME, name); if (isSet(route)) json.put(ROUTE, route.id()); if (isSet(direction)) json.put(DIRECTION, direction); @@ -374,7 +401,7 @@ public class Train extends BaseClass implements Comparable { if (json.has(NAME)) name = json.getString(NAME); if (json.has(TAGS)) json.getJSONArray(TAGS ).forEach(elem -> { tags.add(elem.toString()); }); if (json.has(TRACE)) json.getJSONArray(TRACE).forEach(elem -> { trace.add(plan.get(elem.toString(), false).set(this)); }); - if (json.has(BLOCK)) block = (Block) plan.get(json.getString(BLOCK), false).set(this); // do not move this up! during set, other fields will be referenced! + if (json.has(BLOCK)) currentBlock = (Block) plan.get(json.getString(BLOCK), false).set(this); // do not move this up! during set, other fields will be referenced! for (Object id : json.getJSONArray(CARS)) add(Car.get(id)); for (Object id : json.getJSONArray(LOCOS)) add((Locomotive) Car.get(id)); return this; @@ -494,8 +521,8 @@ public class Train extends BaseClass implements Comparable { } dest.addTo(propList); - if (isSet(block)) { - link("li",Map.of(REALM,REALM_PLAN,ID,block.id(),ACTION,ACTION_CLICK),t("Current location: {}",block)).addTo(propList); + if (isSet(currentBlock)) { + link("li",Map.of(REALM,REALM_PLAN,ID,currentBlock.id(),ACTION,ACTION_CLICK),t("Current location: {}",currentBlock)).addTo(propList); Tag actions = new Tag("li").clazz().content(t("Actions:")+NBSP); props.put(ACTION, ACTION_START); new Button(t("start"),props).addTo(actions); @@ -556,8 +583,8 @@ public class Train extends BaseClass implements Comparable { } public void set(Block newBlock) { - block = newBlock; - if (isSet(block)) block.set(this); + currentBlock = newBlock; + if (isSet(currentBlock)) currentBlock.set(this); } private String setDestination(HashMap params) { @@ -594,13 +621,12 @@ public class Train extends BaseClass implements Comparable { } public String start() throws IOException { - if (isNull(block)) return t("{} not in a block",this); + if (isNull(currentBlock)) return t("{} not in a block",this); Context context = isSet(route) ? new Context( route ) : new Context( this); - if (isSet(context.route)) context.route.reset(); // reset route previously chosen route = chooseRoute(context); - if (isNull(route)) return t("No free routes from {}",block); + if (isNull(route)) return t("No free routes from {}",currentBlock); if (!route.lock()) return t("Was not able to lock {}",route); if (direction != route.startDirection) turn(); @@ -648,7 +674,7 @@ public class Train extends BaseClass implements Comparable { direction = direction.inverse(); for (Locomotive loco : locos) loco.turn(); reverseTrace(); - if (isSet(block)) plan.place(block); + if (isSet(currentBlock)) plan.place(currentBlock); } return t("{} turned.",this); } @@ -676,4 +702,8 @@ public class Train extends BaseClass implements Comparable { public void setWaitTime(Range waitTime) { if (autopilot != null) autopilot.waitTime = waitTime.random(); } + + public Block currentBlock() { + return currentBlock; + } } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java index cdda81f..f1cc716 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java @@ -44,7 +44,7 @@ import de.srsoftware.web4rail.tags.Radio; */ public abstract class Tile extends BaseClass{ protected static Logger LOG = LoggerFactory.getLogger(Tile.class); - private static int DEFAUT_LENGTH = 5; + private static int DEFAUT_LENGTH = 100; // 10cm private static final String LENGTH = "length"; private static final String LOCKED = "locked";