diff --git a/.gitignore b/.gitignore index d943149..faa5c7c 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ *.cu *.routes *.trains +*.history /backup /bin/ /Debug/ diff --git a/pom.xml b/pom.xml index c9dced1..3398015 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 de.srsoftware web4rail - 1.4.17 + 1.4.18 Web4Rail jar Java Model Railway Control @@ -38,7 +38,7 @@ de.srsoftware tools - 1.1.12 + 1.1.15 compile diff --git a/resources/translations/Application.de.translation b/resources/translations/Application.de.translation index d0f422a..0a42987 100644 --- a/resources/translations/Application.de.translation +++ b/resources/translations/Application.de.translation @@ -7,6 +7,8 @@ Actions (On) : Aktionen (Ein) Actions (Off) : Aktionen (Aus) Actions and contacts : Aktionen und Kontakte Action type : Aktions-Typ +Actions in case conditions are fulfilled : Aktionen, wenn Bedingungen erfüllt sind +Actions in case conditions are not fulfilled : Aktionen, wenn Bedingungen nicht erfüllt sind Actions will only fire, if all conditions are fullfilled. : Aktionen werden nur ausgeführt, wenn alle Bedingungen erfüllt sind. ActivateRoute : Route aktivieren add : hinzufügen @@ -16,6 +18,7 @@ add action : Aktion hinzufügen Add action to action list : Aktion zur Liste hinzufügen add car : Waggon hinzufügen Add condition : Bedingung hinzufügen +Add entry : Eintrag hinzufügen add locomotive : Lok hinzufügen add new aspect : neues Signalbild hinzufügen add new car : neuen Waggon anlegen @@ -28,6 +31,7 @@ Address : Adresse Add tag "{}" to train : Markierung "{}" zu Zug hinzufügen Add tile : Kachel hinzufügen Add {} to destinations of train : {} zu den Zielen des Zugs hinzufügen +Allow editing JSON of action lists : Bearbeiten von Action-Lists per JSON-Editor erlauben analyze : analysieren Analyze : analysieren Analyze may overwrite these routes! : Durch die Analyse können diese Fahrstraßen überschrieben werden! @@ -109,6 +113,7 @@ Current location\: {} : Aufenthaltsort: {} Current orientation : aktuelle Fahrtrichtung Current velocity\: {} {} : Aktuelle Geschwindigkeit: {} {} custom fields : benutzerdefinierte Felder +Date/Time : Datum/Zeit Decoder address : Decoder-Adresse decouple : Abkuppeln decoupler : decoupler @@ -130,6 +135,7 @@ disable {} : {} deaktivieren disabled routes : deaktivierte Fahrstraßen DisableEnableBlock : Block (de)aktivieren Display "{}" on {}. : „{}“ auf {} anzeigen. +Do you know, what you are doing? : Weißt du, was du da tust? driven distance : zurückgelegte Strecke Drop : Verwerfen Drop brake times : Bremszeiten löschen @@ -138,10 +144,12 @@ due after : fällig ab 1) Duration between 5 {} steps during brake process. : 1) Zeit zwischen 5 {}-Schritten beim Bremsvorgang. EAST : Osten edit : bearbeiten +edit JSON : JSON bearbeiten Editable properties : veränderliche Eigenschaften editable train properties : veränderliche Zug-Eigenschaften Edit json : JSON bearbeiten Effect : Effekt +else\: : falls nicht: Emergency : Notfall empty train : leerer Zug enable : aktivieren @@ -150,8 +158,9 @@ Engage {} : {} aktivieren EngageDecoupler : Entkuppler aktivieren Enter new name for plan : Neuen Namen für den Plan eingeben executed : ausgeführt +executed "{}" after {} : "{}" nach {} ausgeführt extended address : erweiterte Adresse -export : exportieren +Event : Ereignis Faster ({} {}) : {} {} schneller Final speed after breaking, before halting : Endgeschwindigkeit nach Bremsvorgang, vor dem Anhalten FinishRoute : Route abschließen @@ -167,12 +176,12 @@ Function : Funktion Hardware settings : Hardware-Einstellungen Height : Höhe Help : Hilfe +History : Logbuch Hold : an lassen (id\: {}, length\: {}) : (Id: {}, Länge: {}) if ({}) : falls ({}) If car of train\: inspect car number : Falls Fahrzeug aus Zug: Untersuche Fahrzeug Nummer -If checked, tiles behind the train are freed according to the length of the train and the tiles. If it is unchecked, tiles will not get free before route is finished. -Falls aktiviert, wird die Strecke anhand von Zug- und Kachel-Länge hinter dem Zug freigegeben, Falls deaktiviert wird die Strecke hinter dem Zug erst bei Abschluss der Route freigegeben. +If checked, tiles behind the train are freed according to the length of the train and the tiles. If it is unchecked, tiles will not get free before route is finished. : Falls aktiviert, wird die Strecke anhand von Zug- und Kachel-Länge hinter dem Zug freigegeben, Falls deaktiviert wird die Strecke hinter dem Zug erst bei Abschluss der Route freigegeben. internal contacts : interne Kontakte Interval : Intervall inverted : invertiert @@ -215,6 +224,7 @@ Minimum delay : minimale Verzögerung Minimum and maximum times (in Miliseconds) trains with the respective tag have to wait in this block. : Minamle und maximale Block-Haltezeit (in Millisekunden) für Züge mit der entsprchender Markierung. minimum starting voltage vmin : Mindestanfahrspannung vmin Move tiles : Kacheln verschieben +move up : nach oben schieben name : Name new car : neuer Waggon new contact : neuer Kontakt @@ -366,6 +376,7 @@ Text to display on clients : Text, welcher auf den Clients angezeigt werden soll Text to show on display : Text, welcher in der Anzeige dargestellt werden soll Tile(s) : Kachel(n) Tile(s) moved. : Kachel(n) verschoben. +Timeout : maximale Wartezeit5 Toggle : umschalten toggle {} : {} umschalten Toggle power : Stom umschalten @@ -429,4 +440,4 @@ Was not able to set all turnouts! : Konnte nicht alle Weichen stellen! WEST : Westen Width : Breite {} within last {} blocks of train : {} ist in den letzten {} Blöcken des Zugs -Your plan currently has {} routes. : Ihr Plan hat im Moment {} Fahrstraßen. \ No newline at end of file +Your plan currently has {} routes. : Ihr Plan hat im Moment {} Fahrstraßen. diff --git a/src/main/java/de/srsoftware/web4rail/Application.java b/src/main/java/de/srsoftware/web4rail/Application.java index 27e7364..54e6562 100644 --- a/src/main/java/de/srsoftware/web4rail/Application.java +++ b/src/main/java/de/srsoftware/web4rail/Application.java @@ -125,6 +125,8 @@ public class Application extends BaseClass{ return Condition.action(params,plan); case REALM_CU: return plan.controlUnit().process(params); + case REALM_HISTORY: + return History.action(params); case REALM_LOCO: return Locomotive.action(params,plan); case REALM_MAINTENANCE: diff --git a/src/main/java/de/srsoftware/web4rail/BaseClass.java b/src/main/java/de/srsoftware/web4rail/BaseClass.java index 7d6071c..cc6fd9e 100644 --- a/src/main/java/de/srsoftware/web4rail/BaseClass.java +++ b/src/main/java/de/srsoftware/web4rail/BaseClass.java @@ -18,8 +18,9 @@ import org.json.JSONObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import de.srsoftware.tools.translations.Translation; import de.srsoftware.tools.Tag; +import de.srsoftware.tools.translations.Translation; +import de.srsoftware.web4rail.History.LogEntry; import de.srsoftware.web4rail.Plan.Direction; import de.srsoftware.web4rail.actions.Action; import de.srsoftware.web4rail.conditions.Condition; @@ -54,7 +55,7 @@ public abstract class BaseClass implements Constants{ public static final Logger LOG = LoggerFactory.getLogger(BaseClass.class); private static final String CUSTOM_FIELDS = "custom_Fields"; private static final String NEW_CUSTOM_FIELD_NAME = "new_custom_field_name"; - protected HashMap customFieldValues = new HashMap(); + protected HashMap customFieldValues = new HashMap(); private BaseClass parent; public static class Context { @@ -308,6 +309,12 @@ public abstract class BaseClass implements Constants{ } } + + public Window addLogEntry(String text) { + History.assign(new History.LogEntry(text),this); + return properties(); + } + public Button button(String text,Map additionalProps) { return new Button(text,props(additionalProps)); } @@ -320,6 +327,25 @@ public abstract class BaseClass implements Constants{ LOG.debug(tx, fills); return false; } + + public static String distance(long l) { + String unit = Plan.lengthUnit; + if (DEFAULT_LENGTH_UNIT.equals(unit)) { + if (l > 1_000_000) { + l/=1_000_000; + unit = t("km"); + } else + if (l > 1_000) { + l/=1_000; + unit = t("m"); + } else + if (l > 10) { + l/=10; + unit = t("cm"); + } + } + return l+NBSP+unit; + } public Form form(String id,List> elements) { Form form = new Form(id); @@ -503,6 +529,21 @@ public abstract class BaseClass implements Constants{ new Button(t("Apply"),customForm).addTo(customForm).addTo(customFields); customFields.addTo(win); + Fieldset history = new Fieldset(t("History")); + + Form form = new Form("add-history-entry"); + new Input(REALM, REALM_HISTORY).hideIn(form); + new Input(ACTION, ACTION_ADD).hideIn(form); + new Input(ID,id()).hideIn(form); + new TextArea(NOTES).addTo(form); + new Button(t("Add entry"), form).addTo(form); + form.addTo(history); + + table = new Table(); + table.addHead(t("Date/Time"),t("Event")); + for (LogEntry entry : History.getFor(this)) table.addRow(new SimpleDateFormat("YYYY-dd-MM HH:mm").format(entry.date()),entry.getText()); + table.addTo(history).addTo(win); + return win; } diff --git a/src/main/java/de/srsoftware/web4rail/Constants.java b/src/main/java/de/srsoftware/web4rail/Constants.java index 6a6ebf0..0a2a296 100644 --- a/src/main/java/de/srsoftware/web4rail/Constants.java +++ b/src/main/java/de/srsoftware/web4rail/Constants.java @@ -46,6 +46,7 @@ public interface Constants { public static final String REALM_CONDITION = "condition"; public static final String REALM_CONTACT = "contact"; public static final String REALM_CU = "cu"; + public static final String REALM_HISTORY = "history"; public static final String REALM_LOCO = "loco"; public static final String REALM_MAINTENANCE = "maintenance"; public static final String REALM_ROUTE = "route"; diff --git a/src/main/java/de/srsoftware/web4rail/History.java b/src/main/java/de/srsoftware/web4rail/History.java new file mode 100644 index 0000000..6bbfbb0 --- /dev/null +++ b/src/main/java/de/srsoftware/web4rail/History.java @@ -0,0 +1,102 @@ +package de.srsoftware.web4rail; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.Vector; + +import org.json.JSONObject; + +import de.srsoftware.web4rail.BaseClass.Id; + +public class History { + + private static HashMap> log = new HashMap<>(); + + static class LogEntry extends BaseClass { + private long timestamp; + private String text; + + public LogEntry(String text) { + this.text = text; + timestamp = new Date().getTime(); + } + + public Date date() { + return new Date(timestamp); + } + + public long getTime() { + return timestamp; + } + + public String getText() { + return text; + } + }; + + public static LogEntry assign(LogEntry logEntry, BaseClass object) { + Id id = object.id(); + Vector list = log.get(id); + if (list == null) log.put(id, list = new Vector<>()); + list.insertElementAt(logEntry,0); + return logEntry; + } + + public static Vector getFor(BaseClass object){ + Vector list = log.get(object.id()); + return list != null ? list : new Vector<>(); + } + + public static Object action(HashMap params) { + + switch (params.get(Constants.ACTION)) { + case Constants.ACTION_ADD: + BaseClass object = BaseClass.get(Id.from(params)); + return object != null ? object.addLogEntry(params.get(Constants.NOTES)) : BaseClass.t("Unknown object!"); + + } + + return BaseClass.t("Unknown action: {}",params.get(Constants.ACTION)); + } + + public static void save(String filename) { + try { + FileWriter file = new FileWriter(filename, Constants.UTF8); + JSONObject json = new JSONObject(); + log.entrySet().forEach(entry -> { + JSONObject list = new JSONObject(); + entry.getValue().forEach(le -> list.put(le.timestamp+"", le.getText())); + json.put(entry.getKey().toString(), list); + }); + json.write(file); + file.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + public static void load(String filename) throws IOException { + BufferedReader file = new BufferedReader(new FileReader(filename, Constants.UTF8)); + JSONObject json = new JSONObject(file.readLine()); + file.close(); + + for (String id : json.keySet()) { + JSONObject o = json.getJSONObject(id); + Vector entries = new Vector<>(); + + for (String time : o.keySet()) { + LogEntry le = new LogEntry(o.getString(time)); + le.timestamp = Long.parseLong(time); + entries.add(le); + } + Collections.sort(entries, (a,b) -> Long.compare(b.timestamp, a.timestamp)); + log.put(new Id(id), entries); + } + + } +} diff --git a/src/main/java/de/srsoftware/web4rail/MaintnanceTask.java b/src/main/java/de/srsoftware/web4rail/MaintnanceTask.java index 2a6d2a8..f7f2d47 100644 --- a/src/main/java/de/srsoftware/web4rail/MaintnanceTask.java +++ b/src/main/java/de/srsoftware/web4rail/MaintnanceTask.java @@ -84,6 +84,7 @@ public class MaintnanceTask extends BaseClass{ Block block = train.currentBlock(); if (isSet(block)) plan.place(block); } + car.addLogEntry(t("executed \"{}\" after {}",name,BaseClass.distance(lastExecutionDist))); return car.properties(); } return t("parent is not a car!"); diff --git a/src/main/java/de/srsoftware/web4rail/Plan.java b/src/main/java/de/srsoftware/web4rail/Plan.java index bb2da0a..d8d0e55 100644 --- a/src/main/java/de/srsoftware/web4rail/Plan.java +++ b/src/main/java/de/srsoftware/web4rail/Plan.java @@ -157,12 +157,14 @@ public class Plan extends BaseClass{ private static final String FREE_BEHIND_TRAIN = "free_behind_train"; private static final String RENAME = "rename"; private static final String SPEED_STEP = "speed_step"; + private static final String ALLOW_JSON_EDIT = "allow_json_edit"; private String name = DEFAULT_NAME; private ControlUnit controlUnit = new ControlUnit(this); // the control unit, to which the plan is connected private Contact learningContact; private Configuration appConfig; private LinkedList listeners = new LinkedList<>(); + public static boolean allowJsonEdit = false; /** * creates a new plan, starts to send heart beats @@ -563,6 +565,9 @@ public class Plan extends BaseClass{ } catch (Exception e) { LOG.warn("Was not able to establish connection to control unit!"); } + + History.load(name+".history"); + LoadCallback.fire(); } @@ -714,6 +719,7 @@ public class Plan extends BaseClass{ formInputs.add(t("Speed step"),new Input(SPEED_STEP, Train.defaultSpeedStep).attr("title", t("Speeds are always increadsed/decreased by this value"))); formInputs.add(t("Lower speed limit"),new Input(FINAL_SPEED, Train.defaultEndSpeed).attr("title", t("Final speed after breaking, before halting"))); formInputs.add(t("Free tiles behind train"),new Checkbox(FREE_BEHIND_TRAIN, t("If checked, tiles behind the train are freed according to the length of the train and the tiles. If it is unchecked, tiles will not get free before route is finished."), Route.freeBehindTrain)); + formInputs.add(t("Allow editing JSON of action lists"),new Checkbox(ALLOW_JSON_EDIT, t("Do you know, what you are doing?"), allowJsonEdit )); postForm.add(relayProperties()); postForm.add(routeProperties()); @@ -859,6 +865,8 @@ public class Plan extends BaseClass{ file.write(json().toString()); file.close(); + History.save(name+".history"); + return t("Plan saved as \"{}\".",name); } @@ -1026,7 +1034,8 @@ public class Plan extends BaseClass{ if (params.containsKey(LENGTH_UNIT)) lengthUnit = params.get(LENGTH_UNIT); if (params.containsKey(SPEED_UNIT)) speedUnit = params.get(SPEED_UNIT); if (params.containsKey(SPEED_STEP)) Train.defaultSpeedStep = Integer.parseInt(params.get(SPEED_STEP)); - if (params.containsKey(FINAL_SPEED)) Train.defaultEndSpeed = Integer.parseInt(params.get(FINAL_SPEED)); + if (params.containsKey(FINAL_SPEED)) Train.defaultEndSpeed = Integer.parseInt(params.get(FINAL_SPEED)); + allowJsonEdit = "on".equalsIgnoreCase(params.get(ALLOW_JSON_EDIT)); Route.freeBehindTrain = "on".equalsIgnoreCase(params.get(FREE_BEHIND_TRAIN)); return t("Plan updated."); diff --git a/src/main/java/de/srsoftware/web4rail/Route.java b/src/main/java/de/srsoftware/web4rail/Route.java index e787c25..7ae9e58 100644 --- a/src/main/java/de/srsoftware/web4rail/Route.java +++ b/src/main/java/de/srsoftware/web4rail/Route.java @@ -348,7 +348,7 @@ public class Route extends BaseClass { setupActions = new ActionList(this); triggeredActions.put(ROUTE_SETUP, setupActions); } - setupActions.list().addTo(setup).addTo(list); + setupActions.listAt(setup).addTo(list); Tag start = new Tag("li").content(t("Start actions")+COL); ActionList startActions = triggeredActions.get(ROUTE_START); @@ -356,7 +356,7 @@ public class Route extends BaseClass { startActions = new ActionList(this); triggeredActions.put(ROUTE_START, startActions); } - startActions.list().addTo(start).addTo(list); + startActions.listAt(start).addTo(list); for (Contact c : contacts) { Tag item = c.link("span", c).addTo(new Tag("li")).content(NBSP); @@ -365,7 +365,7 @@ public class Route extends BaseClass { actions = new ActionList(this); triggeredActions.put(c.trigger(), actions); } - actions.list().addTo(item).addTo(list); + actions.listAt(item).addTo(list); } list.addTo(win); return win; diff --git a/src/main/java/de/srsoftware/web4rail/actions/Action.java b/src/main/java/de/srsoftware/web4rail/actions/Action.java index 605e6eb..6cac058 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/Action.java +++ b/src/main/java/de/srsoftware/web4rail/actions/Action.java @@ -12,6 +12,7 @@ import org.slf4j.LoggerFactory; import de.srsoftware.tools.Tag; import de.srsoftware.web4rail.BaseClass; +import de.srsoftware.web4rail.LoadCallback; import de.srsoftware.web4rail.tags.Button; import de.srsoftware.web4rail.tags.Fieldset; import de.srsoftware.web4rail.tags.Form; @@ -110,6 +111,7 @@ public abstract class Action extends BaseClass { ((ActionList)this).clear(); } load(json); + LoadCallback.fire(); return context().properties(); } Window win = new Window("json-import-export-"+id(), t("JSON code of {}",this)); diff --git a/src/main/java/de/srsoftware/web4rail/actions/ActionList.java b/src/main/java/de/srsoftware/web4rail/actions/ActionList.java index d662cda..631bd03 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/ActionList.java +++ b/src/main/java/de/srsoftware/web4rail/actions/ActionList.java @@ -123,23 +123,22 @@ public class ActionList extends Action implements Iterable{ return json; } - public Tag list() { - Tag span = new Tag("span"); - button(t("add action"), Map.of(ACTION, ACTION_ADD)).addTo(span); - button(t("export"), Map.of(ACTION, ACTION_SAVE)).addTo(span); + public T listAt(T parent) { + button(parent.is("fieldset") ? t("add action") : "+", Map.of(ACTION, ACTION_ADD)).title(t("add action")).addTo(parent); + if (plan.allowJsonEdit) button(t("edit JSON"), Map.of(ACTION, ACTION_SAVE)).addTo(parent); if (!isEmpty()) { Tag list = new Tag("ol"); for (Action action : actions) { Tag item = action.link("span",action).addTo(new Tag("li")).content(NBSP); - action.button("-", Map.of(ACTION,ACTION_DROP)).addTo(item); - action.button("↑", Map.of(ACTION,ACTION_MOVE)).addTo(item); - if (action instanceof ActionList) ((ActionList) action).list().addTo(item); + action.button("↑", Map.of(ACTION,ACTION_MOVE)).title(t("move up")).addTo(item); + action.button("-", Map.of(ACTION,ACTION_DROP)).title(t("delete")).addTo(item); + if (action instanceof ActionList) ((ActionList) action).listAt(item); item.addTo(list); } - list.addTo(span); + list.addTo(parent); } - return span; + return (T)parent; } public Action load(JSONObject json) { @@ -248,9 +247,7 @@ public class ActionList extends Action implements Iterable{ @Override protected Window properties(List
preForm, FormInput formInputs, List
postForm,String...errors) { - Fieldset fieldset = new Fieldset(t("Actions")); - list().addTo(fieldset); - postForm.add(fieldset); + preForm.add(listAt(new Fieldset(t("Actions")).clazz("actions"))); return super.properties(preForm, formInputs, postForm,errors); } diff --git a/src/main/java/de/srsoftware/web4rail/actions/ConditionalAction.java b/src/main/java/de/srsoftware/web4rail/actions/ConditionalAction.java index ae86c67..ab0a590 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/ConditionalAction.java +++ b/src/main/java/de/srsoftware/web4rail/actions/ConditionalAction.java @@ -2,10 +2,13 @@ package de.srsoftware.web4rail.actions; import java.util.HashMap; import java.util.List; +import java.util.Optional; +import java.util.Vector; import org.json.JSONArray; import org.json.JSONObject; +import de.srsoftware.tools.Tag; import de.srsoftware.web4rail.BaseClass; import de.srsoftware.web4rail.conditions.Condition; import de.srsoftware.web4rail.conditions.ConditionList; @@ -15,11 +18,14 @@ import de.srsoftware.web4rail.tags.Window; public class ConditionalAction extends ActionList { private static final String CONDITIONS = "conditions"; + private static final String ELSE_ACTONS = "else_actions"; private ConditionList conditions = new ConditionList(); + private ActionList elseActions; public ConditionalAction(BaseClass parent) { super(parent); conditions.parent(this); + elseActions = new ActionList(parent); } public boolean equals(ConditionalAction other) { @@ -29,7 +35,7 @@ public class ConditionalAction extends ActionList { @Override public boolean fire(Context context,Object cause) { for (Condition condition : conditions) { - if (!condition.fulfilledBy(context)) return true; // wenn die Bedingung nicht erfüllt ist, ist das kein Fehler! + if (!condition.fulfilledBy(context)) return elseActions.fire(context, cause); } return super.fire(context.clone(),cause); // actions, that happen within the conditional action list must not modify the global context. } @@ -48,13 +54,27 @@ public class ConditionalAction extends ActionList { JSONArray conditions = new JSONArray(); for (Condition condition : this.conditions) conditions.put(condition.json()); json.put(CONDITIONS, conditions); + if (!elseActions.isEmpty()) json.put(ELSE_ACTONS, elseActions.json()); return json; } + @Override + public T listAt(T parent) { + T tag = super.listAt(parent); + if (!elseActions.isEmpty()) { + Tag div = new Tag("div").clazz("else"); + new Tag("span").content(t("else:")+NBSP).addTo(div); + elseActions.listAt(div); + div.addTo(tag); + } + return tag; + } + @Override public Action load(JSONObject json) { - super.load(json); + super.load(json); if (json.has(CONDITIONS)) { + conditions.clear(); for (Object o : json.getJSONArray(CONDITIONS)) { if (o instanceof JSONObject) { JSONObject j = (JSONObject) o; @@ -66,13 +86,37 @@ public class ConditionalAction extends ActionList { } } } + if (json.has(ELSE_ACTONS)) elseActions.load(json.getJSONObject(ELSE_ACTONS)); return this; } @Override protected Window properties(List
preForm, FormInput formInputs, List
postForm,String...errors) { preForm.add(conditions.list()); - return super.properties(preForm, formInputs, postForm,errors); + Window win = super.properties(preForm, formInputs, postForm,errors); + Optional
actionFieldSet = win.children() + .stream() + .filter(tag -> tag instanceof Fieldset) + .map(tag -> (Fieldset)tag) + .filter(fs -> "actions".equals(fs.get("class"))) + .findFirst(); + + if (actionFieldSet.isPresent()) { + Vector children = actionFieldSet.get().children(); + children.insertElementAt(new Tag("h3").content(t("Actions in case conditions are fulfilled")),1); + LOG.debug("children: "+children); + Optional elseTag = children.stream().filter(tag -> "else".equals(tag.get("class"))).findFirst(); + if (elseTag.isPresent()) { + children = elseTag.get().children(); + children.remove(0); + children.insertElementAt(new Tag("h3").content(t("Actions in case conditions are not fulfilled")),0); + } else { + children.add(new Tag("h3").content(t("Actions in case conditions are not fulfilled"))); + elseActions.listAt(actionFieldSet.get()); + } + } + + return win; } diff --git a/src/main/java/de/srsoftware/web4rail/actions/WaitForContact.java b/src/main/java/de/srsoftware/web4rail/actions/WaitForContact.java index c922c9b..e3a48ae 100644 --- a/src/main/java/de/srsoftware/web4rail/actions/WaitForContact.java +++ b/src/main/java/de/srsoftware/web4rail/actions/WaitForContact.java @@ -69,14 +69,14 @@ public class WaitForContact extends ActionList { } @Override - public Tag list() { - Tag list = super.list(); + public T listAt(T parent) { + T list = super.listAt(parent); for (Tag child : list.children()) { if (child.is("ol")) { break; } } - timeoutActions.list().addTo(new Tag("span").content(t("On timeout (after {} ms)",timeout)+":")).addTo(list); + timeoutActions.listAt(new Tag("span").content(t("On timeout (after {} ms)",timeout)+":")).addTo(list); return list; } @@ -103,7 +103,7 @@ public class WaitForContact extends ActionList { Fieldset fieldset = new Fieldset(t("Actions on timeout")); fieldset.id("actions"); - timeoutActions.list().addTo(fieldset); + timeoutActions.listAt(fieldset); postForm.add(fieldset); return super.properties(preForm, formInputs, postForm,errors); diff --git a/src/main/java/de/srsoftware/web4rail/conditions/ConditionList.java b/src/main/java/de/srsoftware/web4rail/conditions/ConditionList.java index 435ef4c..14402a0 100644 --- a/src/main/java/de/srsoftware/web4rail/conditions/ConditionList.java +++ b/src/main/java/de/srsoftware/web4rail/conditions/ConditionList.java @@ -31,6 +31,9 @@ public class ConditionList extends Condition implements Iterable{ this.conditions.addAll(conditions.conditions); } + public void clear() { + conditions.clear(); + } public boolean fulfilledBy(Context context) { for (Condition condition : conditions) { diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Contact.java b/src/main/java/de/srsoftware/web4rail/tiles/Contact.java index cf26039..e555a08 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Contact.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Contact.java @@ -189,7 +189,7 @@ public class Contact extends Tile{ formInputs.add(t("Address"),span); Fieldset fieldset = new Fieldset(t("Actions")).id("props-actions"); - actions.list().addTo(fieldset); + actions.listAt(fieldset); postForm.add(fieldset); return super.properties(preForm, formInputs, postForm,errors); } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Switch.java b/src/main/java/de/srsoftware/web4rail/tiles/Switch.java index 7a00a3d..0eb546a 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Switch.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Switch.java @@ -129,11 +129,11 @@ public class Switch extends Tile{ protected Window properties(List
preForm, FormInput formInputs, List
postForm,String...errors) { Fieldset fieldset = new Fieldset(t("Actions (On)")); fieldset.id("actionsOn"); - actionsOn.list().addTo(fieldset); + actionsOn.listAt(fieldset); postForm.add(fieldset); fieldset = new Fieldset(t("Actions (Off)")); fieldset.id("actionsOff"); - actionsOff.list().addTo(fieldset); + actionsOff.listAt(fieldset); postForm.add(fieldset); return super.properties(preForm, formInputs, postForm,errors); } diff --git a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java index c07e125..6e96669 100644 --- a/src/main/java/de/srsoftware/web4rail/tiles/Tile.java +++ b/src/main/java/de/srsoftware/web4rail/tiles/Tile.java @@ -149,18 +149,18 @@ public abstract class Tile extends BaseClass implements Comparable { Train train = newTrain.train(); if (isSet(reservingTrain) && reservingTrain != train) { - LOG.debug("{} is reserved for {}",reservingTrain); + LOG.debug("{} is reserved for {}",this,reservingTrain); return false; // nicht in reservierten Block einfahren! } if (isSet(lockingTrain) && lockingTrain != train) { - LOG.debug("{} is locked for {}",lockingTrain); + LOG.debug("{} is locked for {}",this,lockingTrain); return false; // nicht in reservierten Block einfahren! } if (isSet(occupyingTrain) && occupyingTrain != train) { - LOG.debug("{} is occupied by {}",occupyingTrain); - return train.isShunting(); // nur in belegte Blöcke einfahren, wenn Rangiermodus aktiv! + LOG.debug("{} is occupied by {}",this,occupyingTrain); + return isSet(train) && train.isShunting(); // nur in belegte Blöcke einfahren, wenn Rangiermodus aktiv! } return true;