Browse Source

working on autorouting and turnout code

lookup-tables
Stephan Richter 5 years ago
parent
commit
f5dbb0916a
  1. 8
      resources/css/style.css
  2. 18
      resources/js/plan.js
  3. 4
      src/main/java/de/srsoftware/web4rail/Application.java
  4. 4
      src/main/java/de/srsoftware/web4rail/Plan.java
  5. 3
      src/main/java/de/srsoftware/web4rail/Route.java
  6. 48
      src/main/java/de/srsoftware/web4rail/moving/Train.java
  7. 10
      src/main/java/de/srsoftware/web4rail/tiles/Tile.java
  8. 35
      src/main/java/de/srsoftware/web4rail/tiles/Turnout.java
  9. 20
      src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java
  10. 11
      src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java

8
resources/css/style.css

@ -175,9 +175,9 @@ h2{ @@ -175,9 +175,9 @@ h2{
width: 15px;
height: 15px;
background: lime;
position: absolute;
position: fixed;
top: 10px;
right: 10px;
left: 10px;
display: none;
}
@ -206,3 +206,7 @@ fieldset{ @@ -206,3 +206,7 @@ fieldset{
border: 1px solid black;
border-radius: 5px;
}
.error{
background: red;
}

18
resources/js/plan.js

@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
const ADD = 'add';
const MOVE = 'move';
const SQUARE = 30;
const BODY = 'body';
const CU = 'cu';
const DIV = 'DIV';
const SVG = 'svg';
const MOVE = 'move';
const OPAC = 100;
const PLAN = '#plan';
const POST = 'POST';
const PROPS = 'props';
const CU = 'cu';
const OPAC = 100;
const SQUARE = 30;
const SVG = 'svg';
var selected = null;
var mode = null;
var messageTimer = null;
@ -157,6 +157,7 @@ function request(data){ @@ -157,6 +157,7 @@ function request(data){
data : data,
success: function(resp){
if (data.realm != 'car' && data.realm != 'loco') closeWindows();
if (resp.startsWith('<html')) return;
if (resp.startsWith('<svg')){
$(PLAN).append($(resp));
} else if (resp.startsWith('<')) {
@ -187,12 +188,17 @@ function runAction(ev){ @@ -187,12 +188,17 @@ function runAction(ev){
function stream(ev){
var data = ev.data;
//console.log("received: ",data);
console.log("received: ",data);
if (data.startsWith('<svg')) {
$(PLAN).append($(data));
return false;
}
if (data.startsWith("heartbeat")) return heartbeat(data);
if (data.startsWith("place ")) return place(data.substring(6));
if (data.startsWith("remove")) return remove(data.substring(7));
if (data.startsWith("addclass")) return addClass(data.substring(9));
if (data.startsWith("dropclass")) return dropClass(data.substring(10));
addMessage(data);
}
function swapTiling(ev){

4
src/main/java/de/srsoftware/web4rail/Application.java

@ -71,8 +71,8 @@ public class Application implements Constants{ @@ -71,8 +71,8 @@ public class Application implements Constants{
return plan.action(params);
case REALM_ROUTE:
return plan.routeAction(params);
case REALM_TRAIN:
return Train.action(params);
case REALM_TRAIN:
return Train.action(params,plan);
}
return t("Unknown realm: {}",params.get(REALM));

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

@ -250,7 +250,7 @@ public class Plan implements Constants{ @@ -250,7 +250,7 @@ public class Plan implements Constants{
LOG.warn("Was not able to load cars!",e);
}
try {
Train.loadAll(filename+".trains");
Train.loadAll(filename+".trains",plan);
} catch (Exception e) {
LOG.warn("Was not able to load trains!",e);
}
@ -437,7 +437,7 @@ public class Plan implements Constants{ @@ -437,7 +437,7 @@ public class Plan implements Constants{
public synchronized void stream(String data) {
data = data.replaceAll("\n", "").replaceAll("\r", "");
//LOG.debug("streaming: {}",data);
//if (!data.startsWith("heartbeat")) LOG.debug("streaming: {}",data);
Vector<OutputStreamWriter> badClients = null;
for (Entry<OutputStreamWriter, Integer> entry : clients.entrySet()) {
OutputStreamWriter client = entry.getKey();

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

@ -308,7 +308,8 @@ public class Route implements Constants{ @@ -308,7 +308,8 @@ public class Route implements Constants{
for (Entry<Turnout, State> entry : turnouts.entrySet()) {// try to switch all turnouts of this route
CompletableFuture<Reply> reply = entry.getKey().state(entry.getValue()); // switching a turnout is an asynchronous process, so it returns a CompletableFuture here
promise = promise == null ? reply : promise.thenCombine(reply, (a,b) -> a);
}
}
if (promise == null) promise = CompletableFuture.completedFuture(null);
promise.exceptionally(ex -> {
for (Tile tile : locked) try {
tile.unlock();

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

@ -12,7 +12,6 @@ import java.util.HashSet; @@ -12,7 +12,6 @@ import java.util.HashSet;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Vector;
import java.util.concurrent.CompletableFuture;
import org.json.JSONObject;
import org.slf4j.Logger;
@ -22,6 +21,7 @@ import de.keawe.tools.translations.Translation; @@ -22,6 +21,7 @@ import de.keawe.tools.translations.Translation;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.Constants;
import de.srsoftware.web4rail.Plan;
import de.srsoftware.web4rail.Plan.Direction;
import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.Window;
@ -98,6 +98,8 @@ public class Train implements Constants { @@ -98,6 +98,8 @@ public class Train implements Constants {
public int speed = 0;
private Autopilot autopilot = null;
private Plan plan;
public Train(Locomotive loco) {
this(loco,null);
@ -110,15 +112,15 @@ public class Train implements Constants { @@ -110,15 +112,15 @@ public class Train implements Constants {
trains.put(id, this);
}
public static Object action(HashMap<String, String> params) throws IOException {
public static Object action(HashMap<String, String> params, Plan plan) throws IOException {
String action = params.get(ACTION);
if (action == null) return t("No action passed to Train.action!");
if (!params.containsKey(Train.ID)) {
switch (action) {
case ACTION_PROPS:
return manager();
case ACTION_ADD:
return create(params);
case ACTION_ADD:
return create(params,plan);
}
return t("No train id passed!");
}
@ -140,10 +142,10 @@ public class Train implements Constants { @@ -140,10 +142,10 @@ public class Train implements Constants {
return t("Unknown action: {}",params.get(ACTION));
}
private static Object create(HashMap<String, String> params) {
private static Object create(HashMap<String, String> params, Plan plan) {
Locomotive loco = (Locomotive) Locomotive.get(params.get(Train.LOCO_ID));
if (loco == null) return t("unknown locomotive: {}",params.get(ID));
Train train = new Train(loco);
Train train = new Train(loco).plan(plan);
if (params.containsKey(NAME)) train.name(params.get(NAME));
return train;
}
@ -215,7 +217,7 @@ public class Train implements Constants { @@ -215,7 +217,7 @@ public class Train implements Constants {
return trains.values();
}
public static void loadAll(String filename) throws IOException {
public static void loadAll(String filename, Plan plan) throws IOException {
BufferedReader file = new BufferedReader(new FileReader(filename));
String line = file.readLine();
while (line != null) {
@ -224,18 +226,19 @@ public class Train implements Constants { @@ -224,18 +226,19 @@ public class Train implements Constants {
long id = json.getLong(ID);
Train train = new Train(null,id);
train.load(json);
train.load(json).plan(plan);
line = file.readLine();
}
file.close();
}
private void load(JSONObject json) {
private Train load(JSONObject json) {
pushPull = json.getBoolean(PUSH_PULL);
if (json.has(NAME)) name = json.getString(NAME);
for (Object id : json.getJSONArray(CARS)) add(Car.get((String)id));
for (Object id : json.getJSONArray(LOCOS)) add((Locomotive) Car.get((String)id));
return this;
}
public static Object manager() {
@ -277,7 +280,12 @@ public class Train implements Constants { @@ -277,7 +280,12 @@ public class Train implements Constants {
}
return result;
}
private Train plan(Plan plan) {
this.plan = plan;
return this;
}
public Tag props() {
Window window = new Window("train-properties",t("Properties of {}",getClass().getSimpleName()));
@ -310,6 +318,9 @@ public class Train implements Constants { @@ -310,6 +318,9 @@ public class Train implements Constants {
actions.addTo(list);
}
if (route != null) {
new Tag("li").content(t("Current route: {}",route)).addTo(list);
}
if (direction != null) new Tag("li").content(t("Direction: heading {}",direction)).addTo(list);
@ -332,8 +343,8 @@ public class Train implements Constants { @@ -332,8 +343,8 @@ public class Train implements Constants {
this.speed = v;
}
public CompletableFuture<String> start() throws IOException {
if (block == null) return CompletableFuture.failedFuture(new RuntimeException(t("{} not in a block",this)));
public String start() throws IOException {
if (block == null) return t("{} not in a block",this);
if (route != null) route.unlock().setSignals(Signal.STOP);
HashSet<Route> routes = block.routes();
Vector<Route> availableRoutes = new Vector<Route>();
@ -352,9 +363,10 @@ public class Train implements Constants { @@ -352,9 +363,10 @@ public class Train implements Constants {
availableRoutes.add(rt);
}
Random rand = new Random();
if (availableRoutes.isEmpty()) return CompletableFuture.failedFuture(new RuntimeException(t("No free routes from {}",block)));
if (availableRoutes.isEmpty()) return t("No free routes from {}",block);
route = availableRoutes.get(rand.nextInt(availableRoutes.size()));
return route.lock(this).thenApply(reply -> {
route.lock(this).thenApply(reply -> {
try {
route.setSignals(null);
if (direction != route.startDirection) turn();
@ -363,7 +375,13 @@ public class Train implements Constants { @@ -363,7 +375,13 @@ public class Train implements Constants {
} catch (Exception e) {
throw new RuntimeException(e);
}
});
}).thenAccept(message -> plan.stream(message))
.exceptionally(ex -> {
plan.stream(ex.getMessage());
throw new RuntimeException(ex);
});
return t("Trying to start {}",this);
}
private Object stop() {

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

@ -274,7 +274,7 @@ public abstract class Tile implements Constants{ @@ -274,7 +274,7 @@ public abstract class Tile implements Constants{
.id((x!=-1 && y!=-1)?(id()):(getClass().getSimpleName()))
.clazz(classes())
.size(100,100)
.attr("name", getClass().getSimpleName())
.attr("name", getClass().getSimpleName())
.attr("viewbox", "0 0 "+width+" "+height);
if (x>-1) style="left: "+(30*x)+"px; top: "+(30*y)+"px;";
if (len()>1) style+=" width: "+(30*len())+"px;";
@ -322,10 +322,16 @@ public abstract class Tile implements Constants{ @@ -322,10 +322,16 @@ public abstract class Tile implements Constants{
.content("?")
.addTo(svg);
}
String title = title();
if (title!=null) new Tag("title").content(title()).addTo(svg);
return svg;
}
public String title() {
return null;
}
@Override
public String toString() {
return t("{}({},{})",getClass().getSimpleName(),x,y) ;

35
src/main/java/de/srsoftware/web4rail/tiles/Turnout.java

@ -24,9 +24,10 @@ public abstract class Turnout extends Tile implements Device{ @@ -24,9 +24,10 @@ public abstract class Turnout extends Tile implements Device{
private Protocol protocol = Protocol.DCC128;
protected int address = 0;
protected int portA = 0, portB = 0;
protected int portA = 0, portB = 1;
protected int delay = 400;
protected boolean initialized;
protected boolean initialized = false;
protected boolean error = false;
public enum State{
LEFT,STRAIGHT,RIGHT,UNDEF;
@ -36,11 +37,21 @@ public abstract class Turnout extends Tile implements Device{ @@ -36,11 +37,21 @@ public abstract class Turnout extends Tile implements Device{
@Override
public Object click() throws IOException {
LOG.debug("Turnout.click()");
LOG.debug(getClass().getSimpleName()+".click()");
init();
return super.click();
}
public void error(Reply reply) {
this.error = true;
try {
plan.stream(tag(null).toString());
} catch (IOException e) {
LOG.error("Was not able to stream: ",e);
}
throw new RuntimeException(reply.message());
}
protected void init() {
if (!initialized) {
plan.queue("INIT {} GA "+address+" "+proto());
@ -52,7 +63,7 @@ public abstract class Turnout extends Tile implements Device{ @@ -52,7 +63,7 @@ public abstract class Turnout extends Tile implements Device{
public JSONObject json() {
JSONObject json = super.json();
if (portA != 0) json.put(PORT_A, portA);
if (portB != 0) json.put(PORT_B, portB);
if (portB != 1) json.put(PORT_B, portB);
if (address != 0) json.put(ADDRESS, address);
json.put(PROTOCOL, protocol);
return json;
@ -101,14 +112,28 @@ public abstract class Turnout extends Tile implements Device{ @@ -101,14 +112,28 @@ public abstract class Turnout extends Tile implements Device{
}
public abstract CompletableFuture<Reply> state(State newState) throws IOException;
public void success() {
this.error = false;
try {
plan.stream(tag(null).toString());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Override
public Tag tag(Map<String, Object> replacements) throws IOException {
Tag tag = super.tag(replacements);
tag.clazz(tag.get("class")+(" "+state).toLowerCase());
tag.clazz(tag.get("class")+(" "+state).toLowerCase()+(error?" error":""));
return tag;
}
@Override
public String title() {
return getClass().getSimpleName()+t("(Address: {}, Ports {} and {})",address,portA,portB);
}
public void toggle() {
state = State.STRAIGHT;
}

20
src/main/java/de/srsoftware/web4rail/tiles/TurnoutL.java

@ -16,7 +16,6 @@ public class TurnoutL extends Turnout { @@ -16,7 +16,6 @@ public class TurnoutL extends Turnout {
@Override
public Object click() throws IOException {
LOG.debug("TurnoutL.click()");
Object o = super.click();
if (route != null) {
plan.stream(t("{} is locked by {}!",this,route));
@ -45,13 +44,6 @@ public class TurnoutL extends Turnout { @@ -45,13 +44,6 @@ public class TurnoutL extends Turnout {
return form;
}
@Override
public Tile update(HashMap<String, String> params) throws IOException {
if (params.containsKey(STRAIGHT)) portA = Integer.parseInt(params.get(STRAIGHT));
if (params.containsKey(LEFT)) portB = Integer.parseInt(params.get(LEFT));
return super.update(params);
}
@Override
public CompletableFuture<Reply> state(State newState) throws IOException {
init();
@ -68,10 +60,18 @@ public class TurnoutL extends Turnout { @@ -68,10 +60,18 @@ public class TurnoutL extends Turnout {
throw new IllegalStateException();
}
return result.thenApply(reply -> {
LOG.debug("{} received {}",TurnoutL.this,reply);
if (!reply.is(200)) throw new RuntimeException(reply.message());
LOG.debug("{} received {}",getClass().getSimpleName(),reply);
if (!reply.is(200)) error(reply);
state = newState;
success();
return reply;
});
}
@Override
public Tile update(HashMap<String, String> params) throws IOException {
if (params.containsKey(STRAIGHT)) portA = Integer.parseInt(params.get(STRAIGHT));
if (params.containsKey(LEFT)) portB = Integer.parseInt(params.get(LEFT));
return super.update(params);
}
}

11
src/main/java/de/srsoftware/web4rail/tiles/TurnoutR.java

@ -16,7 +16,6 @@ public class TurnoutR extends Turnout { @@ -16,7 +16,6 @@ public class TurnoutR extends Turnout {
@Override
public Object click() throws IOException {
LOG.debug("Turnoutr.click()");
Object o = super.click();
if (route != null) {
plan.stream(t("{} is locked by {}!",this,route));
@ -34,8 +33,8 @@ public class TurnoutR extends Turnout { @@ -34,8 +33,8 @@ public class TurnoutR extends Turnout {
break;
}
}
new Input(STRAIGHT, portA).addTo(new Label(t("Straight port"))).addTo(fieldset);
new Input(RIGHT, portB).addTo(new Label(t("Right port"))).addTo(fieldset);
new Input(STRAIGHT, portA).numeric().addTo(new Label(t("Straight port"))).addTo(fieldset);
new Input(RIGHT, portB).numeric().addTo(new Label(t("Right port"))).addTo(fieldset);
return form;
}
@ -62,8 +61,10 @@ public class TurnoutR extends Turnout { @@ -62,8 +61,10 @@ public class TurnoutR extends Turnout {
throw new IllegalStateException();
}
return result.thenApply(reply -> {
LOG.debug("{} received {}",reply);
if (reply.is(200)) state = newState;
LOG.debug("{} received {}",getClass().getSimpleName(),reply);
if (!reply.is(200)) error(reply);
state = newState;
success();
return reply;
});
}

Loading…
Cancel
Save