From 5b4ccf058b3698617d6b2a35af1188a904f4a4bc Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Thu, 26 Nov 2020 20:37:53 +0100 Subject: [PATCH] implemented scaled velocity --- pom.xml | 2 +- resources/js/plan.js | 2 +- .../translations/Application.de.translation | 8 +-- .../de/srsoftware/web4rail/BaseClass.java | 1 + .../de/srsoftware/web4rail/Constants.java | 2 + .../de/srsoftware/web4rail/ControlUnit.java | 2 +- .../java/de/srsoftware/web4rail/Plan.java | 67 +++++++++++++++++-- .../java/de/srsoftware/web4rail/Protocol.java | 21 +++--- .../srsoftware/web4rail/actions/SetSpeed.java | 18 ++--- .../de/srsoftware/web4rail/moving/Car.java | 18 +++-- .../web4rail/moving/Locomotive.java | 28 ++++---- .../de/srsoftware/web4rail/moving/Train.java | 44 ++++++++---- .../de/srsoftware/web4rail/tiles/Tile.java | 16 ++--- 13 files changed, 157 insertions(+), 72 deletions(-) diff --git a/pom.xml b/pom.xml index 0f71868..9376109 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.srsoftware web4rail - 1.0.16 + 1.0.17 Web4Rail jar Java Model Railway Control diff --git a/resources/js/plan.js b/resources/js/plan.js index dcd9665..de9e411 100644 --- a/resources/js/plan.js +++ b/resources/js/plan.js @@ -118,7 +118,7 @@ function heartbeat(data){ } function keypress(ev){ - if (ev.code === 'Enter') request({realm:"cu",action:"emergency"}); + if (ev.code === 'Escape') request({realm:"cu",action:"emergency"}); } function moveTile(x,y){ diff --git a/resources/translations/Application.de.translation b/resources/translations/Application.de.translation index ec8aefa..853917c 100644 --- a/resources/translations/Application.de.translation +++ b/resources/translations/Application.de.translation @@ -45,7 +45,7 @@ Command to send to control unit\: : Kommando, welches zur Zentrale gesendet werd Create action : Aktion erzeugen Current location : Aufenthaltsort Current location\: {} : Aufenthaltsort: {} -Current velocity\: {} km/h : Aktuelle Geschwindigkeit: {} km/h +Current velocity\: {} {} : Aktuelle Geschwindigkeit: {} {} Delay : Verzögerung DelayedAction : verzögerte Aktion delete : entfernen @@ -76,7 +76,7 @@ if ({})\: : falls ({}): inverted : invertiert known cars : bekannte Waggons known locomotives : bekannte Lokomotiven -knwon trains : bekannte Züge +known trains : bekannte Züge learn : lernen LEFT : links Left port\: : Port für links @@ -134,8 +134,8 @@ SetRelay : Relais schalten SetSignal : Signal stellen SetSignalsToStop : Signale auf Halt stellen SetSpeed : Geschwindigkeit ändern -Set {} to {} km/h : {} auf {} km/h gesetzt -Set speed to {} km/h : Geschwindigkeit auf {} km/h setzen +Set {} to {} {} : {} auf {} {} gesetzt +Set speed to {} {} : Geschwindigkeit auf {} {} setzen Set {} to {} : {} auf {} setzen SetPower : Strom schalten Set speed to : Geschwindigkeit setzen diff --git a/src/main/java/de/srsoftware/web4rail/BaseClass.java b/src/main/java/de/srsoftware/web4rail/BaseClass.java index 9c4b1d8..e69f77e 100644 --- a/src/main/java/de/srsoftware/web4rail/BaseClass.java +++ b/src/main/java/de/srsoftware/web4rail/BaseClass.java @@ -12,6 +12,7 @@ import de.srsoftware.web4rail.tags.Button; public abstract class BaseClass implements Constants{ protected static Plan plan; // the track layout in use public static final Random random = new Random(); + public static String speedUnit = DEFAULT_SPEED_UNIT; public static Button contextButton(String context,String text) { String[] parts = context.split(":"); diff --git a/src/main/java/de/srsoftware/web4rail/Constants.java b/src/main/java/de/srsoftware/web4rail/Constants.java index 9501a71..38197a5 100644 --- a/src/main/java/de/srsoftware/web4rail/Constants.java +++ b/src/main/java/de/srsoftware/web4rail/Constants.java @@ -47,9 +47,11 @@ public interface Constants { public static final String REALM_PLAN = "plan"; public static final String REALM_TRAIN = "train"; + public static final String BLOCK = "block"; public static final String CONTACT = "contact"; public static final String CONTEXT = "context"; + public static final String DEFAULT_SPEED_UNIT = "km/h"; public static final String DISABLED = "disabled"; public static final String GITHUB_URL = "https://github.com/srsoftware-de/Web4Rail"; public static final String ID = "id"; diff --git a/src/main/java/de/srsoftware/web4rail/ControlUnit.java b/src/main/java/de/srsoftware/web4rail/ControlUnit.java index 8e07b25..3e4f9bd 100644 --- a/src/main/java/de/srsoftware/web4rail/ControlUnit.java +++ b/src/main/java/de/srsoftware/web4rail/ControlUnit.java @@ -114,7 +114,7 @@ public class ControlUnit extends Thread implements Constants{ * @throws IOException */ public void load(String filename) throws IOException { - BufferedReader file = new BufferedReader(new FileReader(filename)); + BufferedReader file = new BufferedReader(new FileReader(filename, UTF8)); JSONObject json = new JSONObject(file.readLine()); file.close(); if (json.has(PORT)) port = json.getInt(PORT); diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java index b6f8c5e..d45b653 100644 --- a/src/main/java/de/srsoftware/web4rail/Plan.java +++ b/src/main/java/de/srsoftware/web4rail/Plan.java @@ -1,8 +1,12 @@ package de.srsoftware.web4rail; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.io.OutputStreamWriter; import java.lang.reflect.InvocationTargetException; +import java.nio.file.Files; import java.security.InvalidParameterException; import java.util.Collection; import java.util.Date; @@ -16,6 +20,8 @@ import java.util.Stack; import java.util.TreeSet; import java.util.Vector; +import org.json.JSONArray; +import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,7 +30,11 @@ import de.srsoftware.tools.Tag; import de.srsoftware.web4rail.actions.Action; import de.srsoftware.web4rail.moving.Car; import de.srsoftware.web4rail.moving.Train; +import de.srsoftware.web4rail.tags.Button; import de.srsoftware.web4rail.tags.Div; +import de.srsoftware.web4rail.tags.Form; +import de.srsoftware.web4rail.tags.Input; +import de.srsoftware.web4rail.tags.Label; import de.srsoftware.web4rail.tiles.Block; import de.srsoftware.web4rail.tiles.BlockH; import de.srsoftware.web4rail.tiles.BlockV; @@ -120,6 +130,7 @@ public class Plan extends BaseClass{ private static final String Y = "y"; private static final HashMap clients = new HashMap(); private static final String FULLSCREEN = "fullscreen"; + private static final String SPEED_UNIT = "speed_unit"; public HashMap tiles = new HashMap(); // The list of tiles of this plan, i.e. the Track layout private HashSet blocks = new HashSet(); // the list of tiles, that are blocks @@ -157,13 +168,15 @@ public class Plan extends BaseClass{ case ACTION_CLICK: return click(get(params.get(ID),true)); case ACTION_MOVE: - return moveTile(params.get(DIRECTION),params.get(ID)); + return moveTile(params.get(DIRECTION),params.get(ID)); + case ACTION_PROPS: + return properties(params); case ACTION_SAVE: return saveTo(DEFAULT_NAME); case ACTION_TIMES: return updateTimes(params); case ACTION_UPDATE: - return update(get(params.get(ID),true),params); + return update(params); } return t("Unknown action: {}",params.get(ACTION)); } @@ -401,7 +414,13 @@ public class Plan extends BaseClass{ } catch (Exception e) { LOG.warn("Was not able to load cars!",e); } - Tile.loadAll(filename+".plan",plan); + + String content = new String(Files.readAllBytes(new File(filename+".plan").toPath()),UTF8); + JSONObject json = new JSONObject(content); + JSONArray jTiles = json.getJSONArray(TILE); + jTiles.forEach(object -> Tile.load(object, plan)); + speedUnit = json.getString(SPEED_UNIT); + try { Train.loadAll(filename+".trains",plan); } catch (Exception e) { @@ -568,8 +587,20 @@ public class Plan extends BaseClass{ new Div(ACTION_ANALYZE).clazz(REALM_PLAN).content(t("Analyze")).addTo(actions); new Div(ACTION_QR).clazz(REALM_PLAN).content(t("QR-Code")).addTo(actions); new Div(FULLSCREEN).clazz(REALM_PLAN).content(t("Fullscreen")).addTo(actions); + new Div(ACTION_PROPS).clazz(REALM_PLAN).content(t("Properties")).addTo(actions); return actions.addTo(actionMenu); } + + private Window properties(HashMap params) { + Window win = new Window("plan-properties", t("Properties")); + Form form = new Form("plan-properties-form"); + new Input(REALM,REALM_PLAN).hideIn(form); + new Input(ACTION,ACTION_UPDATE).hideIn(form); + new Input(SPEED_UNIT, speedUnit).addTo(new Label(t("Speed unit")+":"+NBSP)).addTo(form); + new Button(t("Save"), form).addTo(form); + form.addTo(win); + return win; + } /** * adds a command to the control unit's command queue @@ -649,14 +680,32 @@ public class Plan extends BaseClass{ */ private String saveTo(String name) throws IOException { if (name == null || name.isEmpty()) throw new NullPointerException("Name must not be empty!"); - Car.saveAll(name+".cars"); + Car.saveAll(name+".cars"); Tile.saveAll(tiles,name+".plan"); Train.saveAll(name+".trains"); // refers to cars, blocks Route.saveAll(routes.values(),name+".routes"); // refers to tiles controlUnit.save(name+".cu"); + + BufferedWriter file = new BufferedWriter(new FileWriter(name+".plan")); + file.write(json().toString()); + file.close(); + return t("Plan saved as \"{}\".",name); } + private Object json() { + JSONArray jTiles = new JSONArray(); + tiles.values().stream() + .filter(tile -> isSet(tile)) + .filter(tile -> !(tile instanceof Shadow)) + .map(tile -> tile.json()) + .forEach(jTiles::put); + + return new JSONObject() + .put(TILE, jTiles) + .put(SPEED_UNIT, speedUnit); + } + /** * adds a tile to the plan at a specific position * @param x @@ -836,8 +885,14 @@ public class Plan extends BaseClass{ * @return * @throws IOException */ - private Tile update(Tile tile, HashMap params) throws IOException { - return tile == null ? null : tile.update(params); + private Object update(HashMap params) throws IOException { + Tile tile = get(params.get(ID),true); + if (isSet(tile)) return tile.update(params); + + if (params.containsKey(SPEED_UNIT)) speedUnit = params.get(SPEED_UNIT); + + return t("Plan updated."); + } private Object updateTimes(HashMap params) throws IOException { diff --git a/src/main/java/de/srsoftware/web4rail/Protocol.java b/src/main/java/de/srsoftware/web4rail/Protocol.java index a7f934b..e9f1833 100644 --- a/src/main/java/de/srsoftware/web4rail/Protocol.java +++ b/src/main/java/de/srsoftware/web4rail/Protocol.java @@ -1,12 +1,17 @@ package de.srsoftware.web4rail; public enum Protocol{ - DCC14, - DCC27, - DCC28, - DCC128, - MOTO, - FLEISCH, - SELECTRIX, - ZIMO; + DCC14(14), + DCC27(27), + DCC28(28), + DCC128(128), + MOTO(14), + FLEISCH(15), + SELECTRIX(31); + + public int steps; + + Protocol(int steps) { + this.steps = steps; + } } diff --git a/src/main/java/de/srsoftware/web4rail/actions/SetSpeed.java b/src/main/java/de/srsoftware/web4rail/actions/SetSpeed.java index f3c11cb..28002a6 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/SetSpeed.java +++ b/src/main/java/de/srsoftware/web4rail/actions/SetSpeed.java @@ -14,26 +14,26 @@ import de.srsoftware.web4rail.tags.Label; public class SetSpeed extends Action{ public static final String MAX_SPEED = "max_speed"; - private int maxSpeed = 0; + private int speed = 0; @Override public boolean fire(Context context) { if (isNull(context.train)) return false; - context.train.setSpeed(maxSpeed); + context.train.setSpeed(speed); return true; } @Override public JSONObject json() { JSONObject json = super.json(); - json.put(MAX_SPEED, maxSpeed); + json.put(MAX_SPEED, speed); return json; } @Override public Action load(JSONObject json) { super.load(json); - maxSpeed = json.getInt(MAX_SPEED); + speed = json.getInt(MAX_SPEED); return this; } @@ -46,7 +46,7 @@ public class SetSpeed extends Action{ new Input(ACTION,ACTION_UPDATE).hideIn(form); new Input(CONTEXT,params.get(CONTEXT)).hideIn(form); Label label = new Label(t("Set speed to")+NBSP); - new Input(MAX_SPEED, maxSpeed).numeric().addTo(label).content(NBSP+t("km/h")); + new Input(MAX_SPEED, speed).numeric().addTo(label).content(NBSP+speedUnit); label.addTo(form); new Button(t("Apply"),form).addTo(form).addTo(win); return win; @@ -54,11 +54,11 @@ public class SetSpeed extends Action{ @Override public String toString() { - return t("Set speed to {} km/h",maxSpeed); + return t("Set speed to {} {}",speed,speedUnit); } - public SetSpeed to(int kmh) { - maxSpeed = kmh; + public SetSpeed to(int newSpeed) { + speed = newSpeed; return this; } @@ -74,7 +74,7 @@ public class SetSpeed extends Action{ int s = Integer.parseInt(ms); if (s<0) error = t("Speed must not be less than zero!"); if (error == null) { - this.maxSpeed = s; + this.speed = s; return t("Action updated!"); } } catch (NumberFormatException e) { diff --git a/src/main/java/de/srsoftware/web4rail/moving/Car.java b/src/main/java/de/srsoftware/web4rail/moving/Car.java index 6097ed0..17e6c9e 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Car.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Car.java @@ -37,6 +37,7 @@ public class Car extends BaseClass implements Comparable{ private static final String LENGTH = "length"; private static final String STOCK_ID = "stock-id"; private static final String TAGS = "tags"; + private static final String MAX_SPEED = "max_speed"; protected HashSet tags = new HashSet(); private int id; @@ -45,6 +46,7 @@ public class Car extends BaseClass implements Comparable{ protected String stockId = ""; private Train train; protected Plan plan; + protected int maxSpeed = 0; public Car(String name) { this(name,null); @@ -94,6 +96,7 @@ public class Car extends BaseClass implements Comparable{ json.put(ID,id); json.put(NAME, name); json.put(LENGTH, length); + if (maxSpeed != 0) json.put(MAX_SPEED, maxSpeed); json.put(STOCK_ID, stockId); if (!tags.isEmpty()) json.put(TAGS, tags); return json; @@ -122,7 +125,7 @@ public class Car extends BaseClass implements Comparable{ public static void loadAll(String filename, Plan plan) throws IOException { cars.clear(); - BufferedReader file = new BufferedReader(new FileReader(filename)); + BufferedReader file = new BufferedReader(new FileReader(filename, UTF8)); String line = file.readLine(); while (line != null) { JSONObject json = new JSONObject(line); @@ -139,6 +142,7 @@ public class Car extends BaseClass implements Comparable{ protected Car load(JSONObject json) { if (json.has(ID)) id = json.getInt(ID); if (json.has(LENGTH)) length = json.getInt(LENGTH); + if (json.has(MAX_SPEED)) maxSpeed = json.getInt(MAX_SPEED); if (json.has(STOCK_ID)) stockId = json.getString(STOCK_ID); if (json.has(TAGS)) json.getJSONArray(TAGS).forEach(elem -> { tags.add(elem.toString()); }); return this; @@ -149,8 +153,8 @@ public class Car extends BaseClass implements Comparable{ new Tag("h4").content(t("known cars")).addTo(win); new Tag("p").content(t("Click on a name to edit the entry.")).addTo(win); - Table table = new Table().addHead(t("Stock ID"),t("Name"),t("Length"),t("Tags")); - cars.values().stream().filter(car -> !(car instanceof Locomotive)).forEach(car -> table.addRow(car.stockId,car.link(),car.length,String.join(", ", car.tags()))); + Table table = new Table().addHead(t("Stock ID"),t("Name"),t("Max. Speed",speedUnit),t("Length"),t("Tags")); + cars.values().stream().filter(car -> !(car instanceof Locomotive)).forEach(car -> table.addRow(car.stockId,car.maxSpeed == 0 ? "–":(car.maxSpeed+NBSP+speedUnit),car.link(),car.length,String.join(", ", car.tags()))); table.addTo(win); Form form = new Form("add-car-form"); @@ -163,6 +167,10 @@ public class Car extends BaseClass implements Comparable{ return win; } + public int maxSpeed() { + return maxSpeed; + } + String name(){ return name; } @@ -186,6 +194,7 @@ public class Car extends BaseClass implements Comparable{ new Input(STOCK_ID,stockId).addTo(new Label(t("Stock ID")+NBSP)).addTo(fieldset); new Input(LENGTH,length).attr("type", "number").addTo(new Label(t("Length")+NBSP)).addTo(fieldset); new Input(TAGS,String.join(", ", tags)).addTo(new Label(t("Tags")+NBSP)).addTo(fieldset); + new Input(MAX_SPEED, maxSpeed).numeric().addTo(new Label(t("Maximum speed")+":"+NBSP)).content(NBSP+speedUnit).addTo(fieldset); fieldset.addTo(form); return form; } @@ -235,8 +244,9 @@ public class Car extends BaseClass implements Comparable{ public Car update(HashMap params) { if (params.containsKey(NAME)) name = params.get(NAME); - if (params.containsKey(STOCK_ID)) stockId = params.get(STOCK_ID); if (params.containsKey(LENGTH)) length = Integer.parseInt(params.get(LENGTH)); + if (params.containsKey(MAX_SPEED)) maxSpeed = Integer.parseInt(params.get(MAX_SPEED)); + if (params.containsKey(STOCK_ID)) stockId = params.get(STOCK_ID); if (params.containsKey(TAGS)) { String[] parts = params.get(TAGS).replace(",", " ").split(" "); tags.clear(); diff --git a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java index 6a47932..4ac2fe0 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java @@ -27,7 +27,6 @@ public class Locomotive extends Car implements Constants,Device{ private static final String REVERSE = "reverse"; public static final String LOCOMOTIVE = "locomotive"; - private static final int VMAX = 128; private boolean reverse = false; private Protocol proto = Protocol.DCC128; private int address = 3; @@ -96,7 +95,7 @@ public class Locomotive extends Car implements Constants,Device{ Fieldset fieldset = new Fieldset(t("Control")); - new Tag("span").content(t("Current velocity: {} km/h",speed)).addTo(fieldset); + new Tag("span").content(t("Current velocity: {} {}",speed)).addTo(fieldset); Tag par = new Tag("p"); Map.of("Slower (10 steps)",ACTION_SLOWER10,"Faster (10 steps)",ACTION_FASTER10).entrySet().forEach(e -> { @@ -146,17 +145,12 @@ public class Locomotive extends Car implements Constants,Device{ case MOTO: proto = "M 2 100 0"; break; // TODO: make configurable case DCC14: - proto = "N 1 14 5"; break; // TODO: make configurable case DCC27: - proto = "N 1 27 5"; break; // TODO: make configurable case DCC28: - proto = "N 1 28 5"; break; // TODO: make configurable case DCC128: - proto = "N 1 128 5"; break; // TODO: make configurable + proto = "N 1 "+this.proto.steps+" 5"; break; // TODO: make configurable case SELECTRIX: proto = "S"; break; - case ZIMO: - proto = "Z"; break; } plan.queue(new Command("INIT {} GL "+address+" "+proto) { @@ -182,8 +176,7 @@ public class Locomotive extends Car implements Constants,Device{ JSONObject loco = new JSONObject(); loco.put(REVERSE, reverse); loco.put(PROTOCOL, proto); - loco.put(ADDRESS, address); - + loco.put(ADDRESS, address); json.put(LOCOMOTIVE, loco); return json; } @@ -214,14 +207,14 @@ public class Locomotive extends Car implements Constants,Device{ new Tag("p").content(t("Click on a name to edit the entry.")).addTo(win); - Table table = new Table().addHead(t("Stock ID"),t("Name"),t("Protocol"),t("Address"),t("Length"),t("Tags")); + Table table = new Table().addHead(t("Stock ID"),t("Name"),t("Max. Speed",speedUnit),t("Protocol"),t("Address"),t("Length"),t("Tags")); cars.values() .stream() .filter(car -> car instanceof Locomotive) .map(car -> (Locomotive)car) .sorted(Comparator.comparing(loco -> loco.address)) .sorted(Comparator.comparing(loco -> loco.stockId)) - .forEach(loco -> table.addRow(loco.stockId,loco.link(),loco.proto,loco.address,loco.length,String.join(", ", loco.tags()))); + .forEach(loco -> table.addRow(loco.stockId,loco.link(),loco.maxSpeed == 0 ? "–":loco.maxSpeed+NBSP+speedUnit,loco.proto,loco.address,loco.length,String.join(", ", loco.tags()))); table.addTo(win); @@ -246,6 +239,7 @@ public class Locomotive extends Car implements Constants,Device{ @Override public Form propertyForm() { Form form = super.propertyForm(); + for (Tag tag : form.children()) { if (REALM.equals(tag.get(Input.NAME)) && REALM_CAR.equals(tag.get(Input.VALUE))) { tag.attr("value", REALM_LOCO); @@ -264,7 +258,8 @@ public class Locomotive extends Car implements Constants,Device{ } private void queue() { - plan.queue(new Command("SET {} GL "+address+" "+(reverse?1:0)+" "+speed+" "+VMAX+" "+(f1?1:0)+" "+(f2?1:0)+" "+(f3?1:0)+" "+(f4?1:0)) { + int step = proto.steps * speed / maxSpeed; + plan.queue(new Command("SET {} GL "+address+" "+(reverse?1:0)+" "+step+" "+proto.steps+" "+(f1?1:0)+" "+(f2?1:0)+" "+(f3?1:0)+" "+(f4?1:0)) { @Override public void onFailure(Reply reply) { @@ -274,11 +269,16 @@ public class Locomotive extends Car implements Constants,Device{ }); } + /** + * Sets the speed of the locomotive to the given velocity in [plan.speedUnit]s + * @param newSpeed + * @return + */ public String setSpeed(int newSpeed) { LOG.debug(this.detail()+".setSpeed({})",newSpeed); init(); speed = newSpeed; - if (speed > 128) speed = 128; + if (speed > maxSpeed()) speed = maxSpeed(); if (speed < 0) speed = 0; queue(); diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java index f5ac85a..d1fab5a 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Train.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java @@ -371,7 +371,7 @@ public class Train extends BaseClass implements Comparable { } public static void loadAll(String filename, Plan plan) throws IOException { - BufferedReader file = new BufferedReader(new FileReader(filename)); + BufferedReader file = new BufferedReader(new FileReader(filename, UTF8)); String line = file.readLine(); while (isSet(line)) { JSONObject json = new JSONObject(line); @@ -439,18 +439,21 @@ public class Train extends BaseClass implements Comparable { new Tag("p").content(t("Click on a name to edit the entry.")).addTo(win); - Table table = new Table().addHead(t("Name"),t("Length"),t("Tags"),t("Route"),t("Current location"),t("Destination"),t("Auto pilot")); - list().forEach(train -> table.addRow( + Table table = new Table().addHead(t("Name"),t("Length"),t("Max. Speed"),t("Tags"),t("Route"),t("Current location"),t("Destination"),t("Auto pilot")); + list().forEach(train -> { + int ms = train.maxSpeed(); + table.addRow( train.link(), train.length(), + ms == Integer.MAX_VALUE ? "–" : ms+NBSP+speedUnit, String.join(", ", train.tags()), train.route, isSet(train.currentBlock) ? train.currentBlock.link() : null, train.destination(), t(isSet(train.autopilot)?"On":"Off") - )); + ); + }); table.addTo(win); - Form form = new Form(); new Input(ACTION, ACTION_ADD).hideIn(form); @@ -468,6 +471,22 @@ public class Train extends BaseClass implements Comparable { return win; } + + + private int maxSpeed() { + int maxSpeed = Integer.MAX_VALUE; + for (Locomotive loco : locos) { + int max = loco.maxSpeed(); + if (max == 0) continue; + maxSpeed = Math.min(max, maxSpeed); + } + for (Car car : cars) { + int max = car.maxSpeed(); + if (max == 0) continue; + maxSpeed = Math.min(max, maxSpeed); + } + return maxSpeed; + } public String name() { return (isSet(name) ? name : locos.firstElement().name()); @@ -498,9 +517,7 @@ public class Train extends BaseClass implements Comparable { new Input(TAGS,String.join(", ", tags)).addTo(new Label(t("Tags")+NBSP)).addTo(form); new Button(t("Apply")).addTo(form).addTo(fieldset); - HashMap props = new HashMap(Map.of(REALM,REALM_TRAIN,ID,id)); - props.put(ACTION, ACTION_TURN); - new Button(t("Turn"), props).addTo(fieldset).addTo(window); + fieldset.addTo(window); fieldset = new Fieldset(t("other train properties")); @@ -509,6 +526,10 @@ public class Train extends BaseClass implements Comparable { locoList().addTo(propList); carList().addTo(propList); + int ms = maxSpeed(); + if (ms < Integer.MAX_VALUE) new Tag("li").content(t("Max. Speed")+": "+maxSpeed()+NBSP+speedUnit).addTo(propList); + + HashMap props = new HashMap(Map.of(REALM,REALM_TRAIN,ID,id)); 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); @@ -626,13 +647,12 @@ public class Train extends BaseClass implements Comparable { } public void setSpeed(int newSpeed) { - speed = newSpeed; - if (speed > 128) speed = 128; + speed = Math.min(newSpeed,maxSpeed()); if (speed < 0) speed = 0; for (Locomotive loco : locos) loco.setSpeed(speed); - plan.stream(t("Set {} to {} km/h",this,speed)); + plan.stream(t("Set {} to {} {}",this,speed,speedUnit)); } - + public void setWaitTime(Range waitTime) { if (isNull(autopilot)) return; autopilot.waitTime = waitTime.random(); diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java index 7ccdd98..fa3ce18 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java @@ -1,9 +1,7 @@ package de.srsoftware.web4rail.tiles; -import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; -import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.lang.reflect.InvocationTargetException; @@ -161,22 +159,16 @@ public abstract class Tile extends BaseClass{ } - public static void loadAll(String filename, Plan plan) throws IOException { - BufferedReader file = new BufferedReader(new FileReader(filename)); - String line = file.readLine(); - while (isSet(line)) { - JSONObject json = new JSONObject(line); + public static void load(Object object, Plan plan) { + if (object instanceof JSONObject) { + JSONObject json = (JSONObject) object; String clazz = json.getString(TYPE); - try { Tile.inflate(clazz,json,plan); - } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | ClassNotFoundException e) { + } catch (InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException | SecurityException | ClassNotFoundException | IOException e) { e.printStackTrace(); } - - line = file.readLine(); } - file.close(); } protected Tile load(JSONObject json) throws IOException {