diff --git a/pom.xml b/pom.xml index abacc18..eabad51 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.srsoftware web4rail - 1.2.30 + 1.2.31 Web4Rail jar Java Model Railway Control diff --git a/resources/translations/Application.de.translation b/resources/translations/Application.de.translation index d6cecc5..8568b0f 100644 --- a/resources/translations/Application.de.translation +++ b/resources/translations/Application.de.translation @@ -54,8 +54,10 @@ ConditionalAction : bedingte Aktion Conditions : Bedingungen Condition type\: : Bedingungs-Typ: Connected to {}. : Mit {} verbunden. +Contact : Kontakt Control : Steuerung Control unit : Zentrale +copy : kopieren Counterpart : Gegenstück Create action : Aktion erzeugen Current location\: : Aktueller Ort: @@ -218,16 +220,20 @@ Train : Zug Train\: : Zug: train does not have tag "{}" : Zug hat keine Markierung „{}“ train has tag "{}" : Zug hat Markierung „{}“ +TrainHasTag : Zug mit Tag train is a push-pull train : Zug ist ein Wendezug -train is longer than {} : Zug ist länger als {} +train is faster than {} {} : Zug ist schneller als {} {} +train is longer than {} {} : Zug ist länger als {} {} train is not a push-pull train : Zug ist kein Wendezug -train is shorter than {} : Zug ist kürzer als {} +train is shorter than {} {} : Zug ist kürzer als {} {} +train is slower than {} {} : Zug ist langsamer als {} {} +TrainLength : Zug-Länge Train manager : Zug-Verwaltung Trains : Züge Trains\: : Züge: -TrainHasTag : Zug mit Tag -TrainLength : Zug-Länge TrainSelect : Zug-Auswahl +TrainSpeed : Zug-Geschwindigkeit +Train speed : Zug-Geschwindigkeit Trigger {} : {} betätigen TriggerContact : Kontakt auslösen Turn : Richtung wechseln diff --git a/src/main/java/de/srsoftware/web4rail/BaseClass.java b/src/main/java/de/srsoftware/web4rail/BaseClass.java index 46fc742..9fb6505 100644 --- a/src/main/java/de/srsoftware/web4rail/BaseClass.java +++ b/src/main/java/de/srsoftware/web4rail/BaseClass.java @@ -59,15 +59,7 @@ public abstract class BaseClass implements Constants{ private Direction direction; public Context(BaseClass object) { - main = object; - if (main instanceof Tile) this.tile = (Tile) main; - if (main instanceof Contact) this.contact = (Contact) main; - if (main instanceof Block) this.block = (Block) main; - if (main instanceof Train) this.train = (Train) main; - if (main instanceof Route) this.route = (Route) main; - if (main instanceof Action) this.action = (Action) main; - if (main instanceof Condition) this.condition = (Condition) main; - if (main instanceof Car) this.car = (Car) main; + setMain(object); } public Action action() { @@ -139,7 +131,19 @@ public abstract class BaseClass implements Constants{ public boolean invalidated() { return isNull(main); } - + + public Context setMain(BaseClass object) { + main = object; + if (main instanceof Tile) this.tile = (Tile) main; + if (main instanceof Contact) this.contact = (Contact) main; + if (main instanceof Block) this.block = (Block) main; + if (main instanceof Train) this.train = (Train) main; + if (main instanceof Route) this.route = (Route) main; + if (main instanceof Action) this.action = (Action) main; + if (main instanceof Condition) this.condition = (Condition) main; + if (main instanceof Car) this.car = (Car) main; + return this; + } public Route route() { return route; diff --git a/src/main/java/de/srsoftware/web4rail/actions/Action.java b/src/main/java/de/srsoftware/web4rail/actions/Action.java index 981b102..ecf19fa 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/Action.java +++ b/src/main/java/de/srsoftware/web4rail/actions/Action.java @@ -48,6 +48,7 @@ public abstract class Action extends BaseClass { DelayedAction.class, DetermineTrainInBlock.class, FinishRoute.class, + Loop.class, PreserveRoute.class, SavePlan.class, SendCommand.class, diff --git a/src/main/java/de/srsoftware/web4rail/actions/Loop.java b/src/main/java/de/srsoftware/web4rail/actions/Loop.java new file mode 100644 index 0000000..60106f2 --- /dev/null +++ b/src/main/java/de/srsoftware/web4rail/actions/Loop.java @@ -0,0 +1,105 @@ +package de.srsoftware.web4rail.actions; + +import java.util.HashMap; +import java.util.List; +import java.util.stream.Collectors; + +import org.json.JSONObject; + +import de.srsoftware.tools.Tag; +import de.srsoftware.web4rail.BaseClass; +import de.srsoftware.web4rail.Route; +import de.srsoftware.web4rail.Window; +import de.srsoftware.web4rail.moving.Train; +import de.srsoftware.web4rail.tags.Fieldset; +import de.srsoftware.web4rail.tags.Select; +import de.srsoftware.web4rail.tiles.Block; +import de.srsoftware.web4rail.tiles.Contact; +import de.srsoftware.web4rail.tiles.Signal; +import de.srsoftware.web4rail.tiles.Turnout; + +public class Loop extends ActionList { + + private String subject = Train.class.getSimpleName(); + private static final String SUBJECT = "subject"; + + public Loop(BaseClass parent) { + super(parent); + } + + @Override + public boolean fire(Context context) { + if (isNull(subject)) return false; + List elements = null; + switch (subject) { + case "Block": + elements = BaseClass.listElements(Block.class); + break; + case "Contact": + elements = BaseClass.listElements(Contact.class); + break; + case "Route": + elements = BaseClass.listElements(Route.class); + break; + case "Signal": + elements = BaseClass.listElements(Signal.class); + break; + case "Turnout": + elements = BaseClass.listElements(Turnout.class); + break; + case "Train": + elements = BaseClass.listElements(Train.class); + break; + } + if (elements == null) return false; + for (BaseClass element : elements) super.fire(context.setMain(element)); + return true; + } + + @Override + public JSONObject json() { + JSONObject json = super.json(); + if (isSet(subject)) json.put(SUBJECT, subject); + return json; + } + + @Override + public Action load(JSONObject json) { + super.load(json); + if (json.has(SUBJECT)) subject = json.getString(SUBJECT); + return this; + } + + @Override + protected Window properties(List
preForm, FormInput formInputs, List
postForm) { + formInputs.add(t("Select subject"),typeSelector()); + return super.properties(preForm, formInputs, postForm); + } + + public String toString() { + return t("For each {} do:",subject); + }; + + private Tag typeSelector() { + Select select = new Select(SUBJECT); + List types = List.of(Block.class,Contact.class,Route.class,Signal.class,Train.class,Turnout.class) + .stream() + .map(cls -> cls.getSimpleName()) + .sorted((s1,s2) -> (t(s1).compareTo(t(s2)))) + .collect(Collectors.toList()); + for (String cls : types) { + Tag option = select.addOption(cls,t(cls)); + if (cls.equals(subject)) option.attr("selected", "selected"); + } + return select; + } + + @Override + protected Object update(HashMap params) { + LOG.debug("update: {}",params); + String newSubject = params.get(SUBJECT); + if (isSet(newSubject)) subject = newSubject; + return super.update(params); + } + +} diff --git a/src/main/java/de/srsoftware/web4rail/conditions/Condition.java b/src/main/java/de/srsoftware/web4rail/conditions/Condition.java index fa51c58..128b576 100644 --- a/src/main/java/de/srsoftware/web4rail/conditions/Condition.java +++ b/src/main/java/de/srsoftware/web4rail/conditions/Condition.java @@ -119,8 +119,9 @@ public abstract class Condition extends BaseClass { OrCondition.class, PushPullTrain.class, TrainHasTag.class, + TrainLength.class, TrainSelect.class, - TrainLength.class); + TrainSpeed.class); } public Condition load(JSONObject json) { diff --git a/src/main/java/de/srsoftware/web4rail/conditions/TrainLength.java b/src/main/java/de/srsoftware/web4rail/conditions/TrainLength.java index f60f041..6d954ed 100644 --- a/src/main/java/de/srsoftware/web4rail/conditions/TrainLength.java +++ b/src/main/java/de/srsoftware/web4rail/conditions/TrainLength.java @@ -12,43 +12,44 @@ import de.srsoftware.web4rail.tags.Input; public class TrainLength extends Condition { - private static final String MAX_LENGTH = "max_length"; - private int maxLength = 0; + private static final String LENGTH = "length"; + private int treshold = 0; @Override public boolean fulfilledBy(Context context) { if (isNull(context.train())) return false; - return (context.train().length() < maxLength) != inverted; + int len = context.train().length(); + return inverted ? len > treshold : len < treshold; } @Override public JSONObject json() { - return super.json().put(MAX_LENGTH, maxLength); + return super.json().put(LENGTH, treshold); } public Condition load(JSONObject json) { super.load(json); - if (json.has(MAX_LENGTH)) maxLength = json.getInt(MAX_LENGTH); + if (json.has(LENGTH)) treshold = json.getInt(LENGTH); return this; } @Override protected Window properties(List
preForm, FormInput formInputs, List
postForm) { - formInputs.add(t("Maximum train length"),new Input(MAX_LENGTH, maxLength).numeric()); + formInputs.add(t("Maximum train length"),new Input(LENGTH, treshold).numeric().addTo(new Tag("span")).content(lengthUnit)); return super.properties(preForm, formInputs, postForm); } @Override public String toString() { - return t(inverted ? "train is longer than {}" : "train is shorter than {}",maxLength) ; + return t(inverted ? "train is longer than {} {}" : "train is shorter than {} {}",treshold,lengthUnit) ; } @Override protected Object update(HashMap params) { - if (params.containsKey(MAX_LENGTH)) try { - int ml = Integer.parseInt(params.get(MAX_LENGTH)); + if (params.containsKey(LENGTH)) try { + int ml = Integer.parseInt(params.get(LENGTH)); if (ml < 1) throw new NumberFormatException(t("length must be larger than zero!")); - maxLength = ml; + treshold = ml; } catch (NumberFormatException nfe) { Window win = properties(); win.children().insertElementAt(new Tag("div").content(nfe.getMessage()),1); diff --git a/src/main/java/de/srsoftware/web4rail/conditions/TrainSpeed.java b/src/main/java/de/srsoftware/web4rail/conditions/TrainSpeed.java new file mode 100644 index 0000000..2610f3e --- /dev/null +++ b/src/main/java/de/srsoftware/web4rail/conditions/TrainSpeed.java @@ -0,0 +1,59 @@ +package de.srsoftware.web4rail.conditions; + +import java.util.HashMap; +import java.util.List; + +import org.json.JSONObject; + +import de.srsoftware.tools.Tag; +import de.srsoftware.web4rail.Window; +import de.srsoftware.web4rail.tags.Fieldset; +import de.srsoftware.web4rail.tags.Input; + +public class TrainSpeed extends Condition { + + private static final String SPEED = "speed"; + private int treshold = 0; + + @Override + public boolean fulfilledBy(Context context) { + if (isNull(context.train())) return false; + return inverted ? context.train().speed > treshold : context.train().speed < treshold; + } + + @Override + public JSONObject json() { + return super.json().put(SPEED, treshold); + } + + public Condition load(JSONObject json) { + super.load(json); + if (json.has(SPEED)) treshold = json.getInt(SPEED); + return this; + } + + @Override + protected Window properties(List
preForm, FormInput formInputs, List
postForm) { + formInputs.add(t("Train speed"),new Input(SPEED, treshold).numeric().addTo(new Tag("span")).content(speedUnit)); + return super.properties(preForm, formInputs, postForm); + } + + @Override + public String toString() { + return t(inverted ? "train is faster than {} {}" : "train is slower than {} {}",treshold,speedUnit) ; + } + + @Override + protected Object update(HashMap params) { + if (params.containsKey(SPEED)) try { + int ml = Integer.parseInt(params.get(SPEED)); + if (ml < 0) throw new NumberFormatException(t("speed must be non-negative!")); + treshold = ml; + } catch (NumberFormatException nfe) { + Window win = properties(); + win.children().insertElementAt(new Tag("div").content(nfe.getMessage()),1); + return win; + } + return super.update(params); + } +} diff --git a/src/main/java/de/srsoftware/web4rail/moving/Car.java b/src/main/java/de/srsoftware/web4rail/moving/Car.java index 6b42ad3..47c4b1a 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Car.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Car.java @@ -11,7 +11,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.TreeSet; -import java.util.Vector; import org.json.JSONObject; import org.slf4j.Logger; @@ -119,14 +118,6 @@ public class Car extends BaseClass implements Comparable{ return link(type, tx); } - static Vector list() { - Vector cars = new Vector(); - for (Car car : Car.cars.values()) { - if (!(car instanceof Locomotive)) cars.add(car); - } - return cars; - } - public static void loadAll(String filename, Plan plan) throws IOException { cars.clear(); BufferedReader file = new BufferedReader(new FileReader(filename, UTF8)); @@ -157,15 +148,17 @@ 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("Max. Speed",speedUnit),t("Length"),t("Tags"),t("Actions")); + Table table = new Table().addHead(t("Stock ID"),t("Name"),t("Max. Speed",speedUnit),t("Length"),t("Train"),t("Tags"),t("Actions")); cars.values() .stream() .filter(car -> !(car instanceof Locomotive)) + .sorted((c1,c2)->c2.stockId.compareTo(c1.stockId)) .forEach(car -> table.addRow( car.stockId, car.link(), car.maxSpeed == 0 ? "–":(car.maxSpeed+NBSP+speedUnit), car.length+NBSP+lengthUnit, + car.train, String.join(", ", car.tags()), car.cloneButton() )); diff --git a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java index b94da01..f8002b9 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Locomotive.java @@ -5,7 +5,6 @@ import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Vector; import org.json.JSONObject; @@ -213,14 +212,6 @@ public class Locomotive extends Car implements Constants,Device{ return json; } - static Vector list() { - Vector locos = new Vector(); - for (Car car : Car.cars.values()) { - if (car instanceof Locomotive) locos.add((Locomotive) car); - } - return locos; - } - @Override public Car load(JSONObject json) { super.load(json); diff --git a/src/main/java/de/srsoftware/web4rail/moving/Train.java b/src/main/java/de/srsoftware/web4rail/moving/Train.java index 2db9306..f27224f 100644 --- a/src/main/java/de/srsoftware/web4rail/moving/Train.java +++ b/src/main/java/de/srsoftware/web4rail/moving/Train.java @@ -5,6 +5,7 @@ import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -233,8 +234,10 @@ public class Train extends BaseClass implements Comparable { new Input(ACTION, ACTION_ADD).hideIn(addCarForm); new Input(ID,id).hideIn(addCarForm); Select select = new Select(CAR_ID); - for (Car car : Car.list()) { - if (isNull(car.train())) select.addOption(car.id(), car+(car.stockId.isEmpty()?"":" ("+car.stockId+")")); + for (Car car : BaseClass.listElements(Car.class)) { + if (car instanceof Locomotive) continue; + if (isSet(car.train())) continue; + select.addOption(car.id(), car+(car.stockId.isEmpty()?"":" ("+car.stockId+")")); } if (!select.children().isEmpty()) { select.addTo(addCarForm); @@ -259,7 +262,7 @@ public class Train extends BaseClass implements Comparable { Train train = new Train(loco); train.parent(plan); if (params.containsKey(NAME)) train.name(params.get(NAME)); - return train; + return train.properties(); } public Block currentBlock() { @@ -368,8 +371,10 @@ public class Train extends BaseClass implements Comparable { return link(type, tx); } - public static TreeSet list() { - return new TreeSet(trains.values()); + public static ArrayList list() { + ArrayList list = new ArrayList(trains.values()); + list.sort((t1,t2)->t1.name.compareTo(t2.name)); + return list; } public static void loadAll(String filename, Plan plan) throws IOException { @@ -418,7 +423,7 @@ public class Train extends BaseClass implements Comparable { new Input(ACTION, ACTION_ADD).hideIn(addLocoForm); new Input(ID,id).hideIn(addLocoForm); Select select = new Select(CAR_ID); - for (Car loco : Locomotive.list()) { + for (Car loco : BaseClass.listElements(Locomotive.class)) { if (isNull(loco.train())) select.addOption(loco.id(), loco); } if (!select.children().isEmpty()) { @@ -456,20 +461,22 @@ public class Train extends BaseClass implements Comparable { }); table.addTo(win); - Form form = new Form(); + Form form = new Form("create-train-form"); new Input(ACTION, ACTION_ADD).hideIn(form); new Input(REALM,REALM_TRAIN).hideIn(form); Fieldset fieldset = new Fieldset(t("add new train")); new Input(Train.NAME, t("new train")).addTo(new Label(t("Name:")+NBSP)).addTo(fieldset); Select select = new Select(LOCO_ID); - for (Car loco : Locomotive.list()) select.addOption(loco.id(),loco.name()); + for (Locomotive loco : BaseClass.listElements(Locomotive.class)) { + if (isSet(loco.train())) continue; + select.addOption(loco.id(),loco.name()); + } select.addTo(new Label(t("Locomotive:")+NBSP)).addTo(fieldset); - new Button(t("Apply")).addTo(fieldset); + new Button(t("Apply"),form).addTo(fieldset); fieldset.addTo(form).addTo(win); - return win; }