From 029222ffa28ca54ba103d7e3856f17b8138003fe Mon Sep 17 00:00:00 2001 From: Stephan Richter Date: Sat, 15 May 2021 00:34:38 +0200 Subject: [PATCH] =?UTF-8?q?*=20verbesserte=20Geschwindigkeitsregelung=20*?= =?UTF-8?q?=20erweiterung=20der=20Aktion=20=E2=80=9EZug=20in=20Block=20bes?= =?UTF-8?q?timmen=E2=80=9C=20*=20verbesserungen=20beim=20Rangieren?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- resources/css/style.css | 90 +++++++++++++++++++ resources/js/plan.js | 13 ++- .../translations/Application.de.translation | 6 ++ .../de/srsoftware/web4rail/Constants.java | 3 + .../java/de/srsoftware/web4rail/Route.java | 6 +- .../actions/DetermineTrainInBlock.java | 19 ++-- .../web4rail/moving/Locomotive.java | 45 ++++++---- .../de/srsoftware/web4rail/moving/Train.java | 24 +++-- .../de/srsoftware/web4rail/tags/Range.java | 34 +++++++ .../de/srsoftware/web4rail/tiles/Block.java | 4 +- 11 files changed, 212 insertions(+), 34 deletions(-) create mode 100644 src/main/java/de/srsoftware/web4rail/tags/Range.java diff --git a/pom.xml b/pom.xml index c04294b..98d428a 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.srsoftware web4rail - 1.4.30 + 1.4.31 Web4Rail jar Java Model Railway Control diff --git a/resources/css/style.css b/resources/css/style.css index 4f6c141..0791ec3 100644 --- a/resources/css/style.css +++ b/resources/css/style.css @@ -448,3 +448,93 @@ svg.Block.disabled text{ #history table td:nth-child(2) { padding-left: 30px; } + +input[type=range] { + height: 39px; + -webkit-appearance: none; + margin: 10px 0; + width: 100%; +} +input[type=range]:focus { + outline: none; +} +input[type=range]::-webkit-slider-runnable-track { + width: 100%; + height: 10px; + cursor: pointer; + animate: 0.2s; + box-shadow: 1px 1px 1px #000000; + background: #3071A9; + border-radius: 5px; + border: 1px solid #000000; +} +input[type=range]::-webkit-slider-thumb { + box-shadow: 1px 1px 1px #000000; + border: 2px solid #000000; + height: 30px; + width: 30px; + border-radius: 10px; + background: #FFFFFF; + cursor: pointer; + -webkit-appearance: none; + margin-top: -11.5px; +} +input[type=range]:focus::-webkit-slider-runnable-track { + background: #3071A9; +} +input[type=range]::-moz-range-track { + width: 100%; + height: 10px; + cursor: pointer; + animate: 0.2s; + box-shadow: 1px 1px 1px #000000; + background: #3071A9; + border-radius: 5px; + border: 1px solid #000000; +} +input[type=range]::-moz-range-thumb { + box-shadow: 1px 1px 1px #000000; + border: 2px solid #000000; + height: 30px; + width: 30px; + border-radius: 10px; + background: #FFFFFF; + cursor: pointer; +} +input[type=range]::-ms-track { + width: 100%; + height: 10px; + cursor: pointer; + animate: 0.2s; + background: transparent; + border-color: transparent; + color: transparent; +} +input[type=range]::-ms-fill-lower { + background: #3071A9; + border: 1px solid #000000; + border-radius: 10px; + box-shadow: 1px 1px 1px #000000; +} +input[type=range]::-ms-fill-upper { + background: #3071A9; + border: 1px solid #000000; + border-radius: 10px; + box-shadow: 1px 1px 1px #000000; +} +input[type=range]::-ms-thumb { + margin-top: 1px; + box-shadow: 1px 1px 1px #000000; + border: 2px solid #000000; + height: 30px; + width: 30px; + border-radius: 10px; + background: #FFFFFF; + cursor: pointer; +} +input[type=range]:focus::-ms-fill-lower { + background: #3071A9; +} +input[type=range]:focus::-ms-fill-upper { + background: #3071A9; +} diff --git a/resources/js/plan.js b/resources/js/plan.js index 0bd30f6..725a484 100644 --- a/resources/js/plan.js +++ b/resources/js/plan.js @@ -65,6 +65,17 @@ function assign(context){ return false; } +function changeSpeed(inputId){ + console.log(inputId); + let parts = inputId.split('_'); + let val = $('#'+inputId).val(); + let data = { realm : parts[0], id : parts[1], action : "setSpeed", speed : val}; + console.log(data); + let caption = $('#'+inputId+'_caption'); + caption.text(caption.text().replace(/\d+/,val)); + request(data); +} + function clickLegend(ev){ lastTab = ev.data; $('.window > .tabs > legend').removeClass('front'); @@ -76,7 +87,7 @@ function clickLegend(ev){ } function clickTile(x,y,shift){ - console.log("clickTile("+x+","+y+")"); + console.log("clickTile("+x+","+y+")"); var id = x+"-"+y; var tiles = $('#'+id); if (tiles.length > 0) { diff --git a/resources/translations/Application.de.translation b/resources/translations/Application.de.translation index 2faacfc..e5e5289 100644 --- a/resources/translations/Application.de.translation +++ b/resources/translations/Application.de.translation @@ -166,6 +166,7 @@ Event : Ereignis Faster ({} {}) : {} {} schneller Final speed after breaking, before halting : Endgeschwindigkeit nach Bremsvorgang, vor dem Anhalten FinishRoute : Route abschließen +first parked train : ersten abgestellten Zug wählen Firing {} : starte {} For each {} do : Mit jedem {} forward : vorwärts @@ -192,6 +193,7 @@ Inverts the direction {} is heading to. : Kehrt die Richtung, in welche {} fähr {} is off : {} ist Aus {} is on : {} ist Ein {} is oriented {} : {} ist {} gerichtet +JSON code of {} : JSON-Code von {} known cars : bekannte Waggons known locomotives : bekannte Lokomotiven known trains : bekannte Züge @@ -235,6 +237,7 @@ new locomotive : neue Lok new tag : neue Markierung new train : neuer Zug No : keine +No direct route from {} to {} : keine direkte Verbindung von {} zu {} No free routes from {} : keine Route von {} frei NORTH : Norden Not connected to other bridge part! : Nicht mit anderem Brücken-Teil verbunden! @@ -262,6 +265,7 @@ other train properties : andere Zug-Eigenschaften other trains in {} : andere Züge in {} Origin and destination : Start und Ziel Origin\: {} to {} : Start: {} nach {} +parked train : abgestellter Zug parked trains : abgestellte Züge Plan saved as "{}". : Plan als „{}“ gespeichert. Plan updated. : Plan aktualisiert. @@ -336,6 +340,7 @@ SetTurnout : Weiche stellen Setup actions : Vorbereitung-Aktionen ShowText : Text anzeigen Shunting : Rangieren +shunting destination : Rangier-Ziel Signals : Signale simplify all names : alle Namen vereinfachen simplify name : Name vereinfachen @@ -435,6 +440,7 @@ Turns the train, as if it went through a loop. : Dreht den ZUg, als wenn er eine Unknown action\: {} : Unbekannte Aktion: {} Use negative number to count from end. : Nutze negative Nummern, um von Ende zu zählen. unset : ungesetzt +update : aktualisieren value : Wert WaitForContact : Auf Kontakt warten Wait for {}, then : auf {} warten, dann diff --git a/src/main/java/de/srsoftware/web4rail/Constants.java b/src/main/java/de/srsoftware/web4rail/Constants.java index e0c0f91..a9d2921 100644 --- a/src/main/java/de/srsoftware/web4rail/Constants.java +++ b/src/main/java/de/srsoftware/web4rail/Constants.java @@ -28,6 +28,7 @@ public interface Constants { public static final String ACTION_PROPS = "props"; public static final String ACTION_QUIT = "quit"; public static final String ACTION_SAVE = "save"; + public static final String ACTION_SET_SPEED = "setSpeed"; public static final String ACTION_SLOWER10 = "slower10"; public static final String ACTION_START = "start"; public static final String ACTION_STOP = "stop"; @@ -36,6 +37,7 @@ public interface Constants { public static final String ACTION_TOGGLE_F2 = "f2"; public static final String ACTION_TOGGLE_F3 = "f3"; public static final String ACTION_TOGGLE_F4 = "f4"; + public static final String ACTION_TOGGLE_SHUNTING = "shunt"; public static final String ACTION_TURN = "turn"; public static final String ACTION_UPDATE = "update"; @@ -75,6 +77,7 @@ public interface Constants { public static final String RELAY = "relay"; public static final String RESERVED = "reserved"; public static final String ROUTE = "route"; + public static final String SPEED = "speed"; public static final String STATE = "state"; public static final String TIME = "time"; public static final String TURNOUT = "turnout"; diff --git a/src/main/java/de/srsoftware/web4rail/Route.java b/src/main/java/de/srsoftware/web4rail/Route.java index c442c11..2654549 100644 --- a/src/main/java/de/srsoftware/web4rail/Route.java +++ b/src/main/java/de/srsoftware/web4rail/Route.java @@ -392,8 +392,10 @@ public class Route extends BaseClass { public void finish(Train train) { LOG.debug("{}.finish()",this); - context.onInvalidate(null); // do in invalidate context of route's nextRoute - context.invalidate(); + if (isSet(context)) { + context.onInvalidate(null); // do in invalidate context of route's nextRoute + context.invalidate(); + } train.endRoute(this); setSignals(Signal.RED); freeIgnoring(null); diff --git a/src/main/java/de/srsoftware/web4rail/actions/DetermineTrainInBlock.java b/src/main/java/de/srsoftware/web4rail/actions/DetermineTrainInBlock.java index 51232cf..0739d5e 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/DetermineTrainInBlock.java +++ b/src/main/java/de/srsoftware/web4rail/actions/DetermineTrainInBlock.java @@ -9,6 +9,7 @@ import org.json.JSONObject; import de.srsoftware.web4rail.BaseClass; import de.srsoftware.web4rail.LoadCallback; import de.srsoftware.web4rail.moving.Train; +import de.srsoftware.web4rail.tags.Checkbox; import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tiles.Block; @@ -16,27 +17,28 @@ import de.srsoftware.web4rail.tiles.Tile; public class DetermineTrainInBlock extends Action { + private static final String PARKED_TRAIN = "parked-train"; + public DetermineTrainInBlock(BaseClass parent) { super(parent); } + private boolean parked = false; private Block block = null; @Override public boolean fire(Context context,Object cause) { - if (isNull(block)) return false; - Train train = block.occupyingTrain(); - if (isSet(train)) { - context.block(block); - context.train(block.occupyingTrain()); - } - return true; + if (isNull(block)) return false; + Train train = parked ? (block.trains().isEmpty() ? null : block.trains().firstElement()) : block.occupyingTrain(); + context.train(train); + return (isSet(train)); } @Override public JSONObject json() { JSONObject json = super.json(); if (isSet(block)) json.put(BLOCK, block.id()); + if (parked) json.put(PARKED_TRAIN, true); return json; } @@ -51,12 +53,14 @@ public class DetermineTrainInBlock extends Action { block = Block.get(blockId); } }; + if (json.has(PARKED_TRAIN)) parked = json.getBoolean(PARKED_TRAIN); return this; } @Override protected Window properties(List
preForm, FormInput formInputs, List
postForm,String...errors) { formInputs.add(t("Block")+": "+(isNull(block) ? t("unset") : block),button(t("Select from plan"),Map.of(ACTION,ACTION_UPDATE,ASSIGN,BLOCK))); + formInputs.add(t("parked train"),new Checkbox(PARKED_TRAIN, t("first parked train"), parked)); return super.properties(preForm, formInputs, postForm,errors); } @@ -79,6 +83,7 @@ public class DetermineTrainInBlock extends Action { block = (Block) tile; } else return t("Clicked tile is not a {}!",t("block")); } + parked = ("on".equals(params.get(PARKED_TRAIN))); return context().properties(); } } diff --git a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java index 0bf6f01..2df1fad 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java @@ -26,6 +26,7 @@ import de.srsoftware.web4rail.tags.Form; import de.srsoftware.web4rail.tags.Input; import de.srsoftware.web4rail.tags.Label; import de.srsoftware.web4rail.tags.Radio; +import de.srsoftware.web4rail.tags.Range; import de.srsoftware.web4rail.tags.Table; import de.srsoftware.web4rail.tags.Window; import de.srsoftware.web4rail.tiles.Block; @@ -71,6 +72,8 @@ public class Locomotive extends Car implements Constants,Device{ return loco.update(params); case ACTION_PROPS: return loco == null ? Locomotive.manager() : loco.properties(); + case ACTION_SET_SPEED: + return loco.setSpeed(Integer.parseInt(params.get(SPEED))); case ACTION_SLOWER10: return loco.faster(-Train.defaultSpeedStep); case ACTION_STOP: @@ -98,42 +101,48 @@ public class Locomotive extends Car implements Constants,Device{ return address; } - public static Fieldset cockpit(Object locoOrTrain) { - Id id = null; + public static Fieldset cockpit(BaseClass locoOrTrain) { int speed = 0; String realm = null; Train train = null; Locomotive loco = null; + int maxSpeed = 0; boolean fun1=false,fun2=false,fun3=false,fun4=false; + String id = null; if (locoOrTrain instanceof Locomotive) { loco = (Locomotive) locoOrTrain; realm = REALM_LOCO; - id = loco.id(); speed = loco.speed; fun1 = loco.f1; fun2 = loco.f2; fun3 = loco.f3; fun4 = loco.f4; + maxSpeed = loco.orientation ? loco.maxSpeedForward : loco.maxSpeedReverse; + id = "loco_"+loco.id(); } else if (locoOrTrain instanceof Train) { train = (Train)locoOrTrain; realm = REALM_TRAIN; - id = train.id(); speed = train.speed; fun1 = train.getFunction(1); fun2 = train.getFunction(2); fun3 = train.getFunction(3); fun4 = train.getFunction(4); - } + maxSpeed = train.maxSpeed(); + id = "train_"+train.id(); + } else return null; - HashMap params = new HashMap(Map.of(REALM,realm,ID,id)); + HashMap params = new HashMap(Map.of(REALM,realm,ID,locoOrTrain.id())); Fieldset fieldset = new Fieldset(t("Control")).id("props-cockpit"); fieldset.clazz("cockpit"); - new Tag("span").content(t("Current velocity: {} {}",speed,speedUnit)).addTo(fieldset); - Tag par = new Tag("p"); + Range range = new Range(t("Current velocity: {} {}",speed,speedUnit),"speed",speed,0,maxSpeed); + range.id(id).onChange("changeSpeed('"+id+"');"); + range.addTo(par); + + params.put(ACTION, ACTION_FASTER10); new Button(t("Faster ({} {})",Train.defaultSpeedStep,speedUnit),params).addTo(par); @@ -149,7 +158,7 @@ public class Locomotive extends Car implements Constants,Device{ } params.put(ACTION, ACTION_TURN); - new Button(t("Turn"),params).title(t("Inverts the direction {} is heading to.",locoOrTrain)).clazz(ACTION_TURN).addTo(direction); + new Button(t("Turn"),params).title(t("Inverts the direction {} is heading to.",locoOrTrain)).clazz(ACTION_TURN).addTo(par); if (isSet(train)) { Block currentBlock = train.currentBlock(); @@ -192,7 +201,12 @@ public class Locomotive extends Car implements Constants,Device{ b4.addTo(functions); functions.addTo(fieldset); - if (isSet(train)) train.button(t("Select destination"),Map.of(ACTION,ACTION_MOVE,ASSIGN,DESTINATION)).addTo(fieldset); + if (isSet(train)) { + train.button(t("Select destination"),Map.of(ACTION,ACTION_MOVE,ASSIGN,DESTINATION)).addTo(direction); + Button toggleShunbting = train.button(t("Shunting"),Map.of(ACTION,ACTION_TOGGLE_SHUNTING)); + if (train.isShunting()) toggleShunbting.clazz(toggleShunbting.get("class")+" active"); + toggleShunbting.addTo(functions); + } return fieldset; } @@ -202,9 +216,8 @@ public class Locomotive extends Car implements Constants,Device{ } - public Object faster(int steps) { - setSpeed(speed + steps); - return properties(); + public Tag faster(int steps) { + return setSpeed(speed + steps); } private void init() { @@ -415,14 +428,16 @@ public class Locomotive extends Car implements Constants,Device{ * @param newSpeed * @return */ - public String setSpeed(int newSpeed) { + public Tag setSpeed(int newSpeed) { LOG.debug(this.detail()+".setSpeed({})",newSpeed); speed = newSpeed; if (speed > maxSpeedForward && maxSpeedForward > 0) speed = maxSpeed(); if (speed < 0) speed = 0; queue(); - return t("Speed of {} set to {}.",this,speed); + plan.stream(t("Speed of {} set to {} {}.",this,speed,BaseClass.speedUnit)); + return properties(); + } private Object setting(int cv) { diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java index 93b138f..50b2bcf 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Train.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java @@ -89,6 +89,8 @@ public class Train extends BaseClass implements Comparable { public int speed = 0; private static final String SHUNTING = "shunting"; + + public static final String SHUNT = "SHUNT"; private boolean shunting = false; private RoutePrepper routePrepper = null; @@ -141,6 +143,8 @@ public class Train extends BaseClass implements Comparable { case ACTION_REVERSE: train.quitAutopilot(); return train.reverse().properties(); + case ACTION_SET_SPEED: + return train.setSpeed(Integer.parseInt(params.get(SPEED))); case ACTION_SLOWER10: return train.slower(Train.defaultSpeedStep); case ACTION_START: @@ -149,6 +153,9 @@ public class Train extends BaseClass implements Comparable { return train.stopNow(); case ACTION_TIMES: return train.removeBrakeTimes(); + case ACTION_TOGGLE_SHUNTING: + train.shunting = !train.shunting; + return train.properties(); case ACTION_TURN: return train.turn().properties(); case ACTION_UPDATE: @@ -526,8 +533,7 @@ public class Train extends BaseClass implements Comparable { } private Tag faster(int steps) { - setSpeed(speed+steps); - return properties(); + return setSpeed(speed+steps); } public boolean getFunction(int num) { @@ -703,7 +709,7 @@ public class Train extends BaseClass implements Comparable { } - private int maxSpeed() { + int maxSpeed() { int maxSpeed = Integer.MAX_VALUE; for (Car car : cars) { int max = car.maxSpeed(); @@ -907,6 +913,7 @@ public class Train extends BaseClass implements Comparable { private Object setDestination(HashMap params) { String dest = params.get(DESTINATION); + if (isNull(currentBlock)) return properties("{} is not in a block!"); if (isNull(dest)) return properties(t("No destination supplied!")); if (dest.isEmpty()) { destination = null; @@ -915,6 +922,11 @@ public class Train extends BaseClass implements Comparable { Tile tile = plan.get(new Id(dest), true); if (isNull(tile)) return properties(t("Tile {} not known!",dest)); if (tile instanceof Block) { + if (shunting) { + boolean connection = currentBlock.routes().stream().anyMatch(route -> route.startBlock() == currentBlock && route.endBlock() == tile); + if (!connection) return t("No direct route from {} to {}",currentBlock,tile); + } + destination = (Block) tile; start(true); return t("{} now heading for {}",this,destination); @@ -953,17 +965,17 @@ public class Train extends BaseClass implements Comparable { return this; } - public void setSpeed(int newSpeed) { + public Tag setSpeed(int newSpeed) { LOG.debug("{}.setSpeed({})",this,newSpeed); speed = Math.min(newSpeed,maxSpeed()); if (speed < 0) speed = 0; cars.stream().filter(c -> c instanceof Locomotive).forEach(car -> ((Locomotive)car).setSpeed(speed)); plan.stream(t("Set {} to {} {}",this,speed,speedUnit)); + return properties(); } private Tag slower(int steps) { - setSpeed(speed-steps); - return properties(); + return setSpeed(speed-steps); } public boolean splitAfter(int position) { diff --git a/src/main/java/de/srsoftware/web4rail/tags/Range.java b/src/main/java/de/srsoftware/web4rail/tags/Range.java new file mode 100644 index 0000000..8f0529a --- /dev/null +++ b/src/main/java/de/srsoftware/web4rail/tags/Range.java @@ -0,0 +1,34 @@ +package de.srsoftware.web4rail.tags; + +import de.srsoftware.tools.Tag; + +public class Range extends Tag{ + + private static final long serialVersionUID = 1865176096163142641L; + private Tag range; + private Tag caption; + + public Range(String caption, String name, int current, int min, int max) { + super("div"); + this.caption = new Tag("span").content(caption); + this.caption.addTo(this); + Tag label = new Tag("label").content(""+min); + range = new Input(name).attr("type","range").attr("min",min).attr("max",max).attr("value",current); + range.addTo(label); + label.content(""+max); + label.addTo(this); + } + + @Override + @SuppressWarnings("unchecked") + public Range id(String id) { + range.id(id); + caption.id(id+"_caption"); + return this; + } + + public Range onChange(String script) { + range.attr("onchange", script); + return this; + } +} diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Block.java b/src/main/java/de/srsoftware/web4rail/tiles/Block.java index c529514..81f87e5 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Block.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Block.java @@ -71,7 +71,7 @@ public abstract class Block extends StretchableTile{ return trains.isEmpty() ? null : trains.getLast(); } - public List list() { + public Vector list() { return new Vector<>(trains); } @@ -496,7 +496,7 @@ public abstract class Block extends StretchableTile{ return fieldset; } - public List trains(){ + public Vector trains(){ return parkedTrains.list(); }