- added else branch to conditional actions
- implemented history for any object extending BaseClass (i.e. almost any)
- added distance() calculation method to base class
- Button "edit JSON" in Action Lists now hidden by default, can be enabled in plan properties
- fixed bugs:
- updating json of DisplayText was not working properly
- log output in Tile.isFreeFor was broken
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,6 +5,7 @@
|
||||
*.cu
|
||||
*.routes
|
||||
*.trains
|
||||
*.history
|
||||
/backup
|
||||
/bin/
|
||||
/Debug/
|
||||
|
||||
4
pom.xml
4
pom.xml
@@ -4,7 +4,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>de.srsoftware</groupId>
|
||||
<artifactId>web4rail</artifactId>
|
||||
<version>1.4.17</version>
|
||||
<version>1.4.18</version>
|
||||
<name>Web4Rail</name>
|
||||
<packaging>jar</packaging>
|
||||
<description>Java Model Railway Control</description>
|
||||
@@ -38,7 +38,7 @@
|
||||
<dependency>
|
||||
<groupId>de.srsoftware</groupId>
|
||||
<artifactId>tools</artifactId>
|
||||
<version>1.1.12</version>
|
||||
<version>1.1.15</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
||||
@@ -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 <em>not</em> fulfilled : Aktionen, wenn Bedingungen <em>nicht</em> 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 v<sub>min</sub> : Mindestanfahrspannung v<sub>min</sub>
|
||||
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.
|
||||
Your plan currently has {} routes. : Ihr Plan hat im Moment {} Fahrstraßen.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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<String,String> customFieldValues = new HashMap<String, String>();
|
||||
protected HashMap<String,String> customFieldValues = new HashMap<String, String>();
|
||||
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<String,String> 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<Map.Entry<String, Tag>> 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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";
|
||||
|
||||
102
src/main/java/de/srsoftware/web4rail/History.java
Normal file
102
src/main/java/de/srsoftware/web4rail/History.java
Normal file
@@ -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<BaseClass.Id, Vector<LogEntry>> 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<LogEntry> list = log.get(id);
|
||||
if (list == null) log.put(id, list = new Vector<>());
|
||||
list.insertElementAt(logEntry,0);
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
public static Vector<LogEntry> getFor(BaseClass object){
|
||||
Vector<LogEntry> list = log.get(object.id());
|
||||
return list != null ? list : new Vector<>();
|
||||
}
|
||||
|
||||
public static Object action(HashMap<String, String> 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<LogEntry> 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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!");
|
||||
|
||||
@@ -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<EventListener> 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.");
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -123,23 +123,22 @@ public class ActionList extends Action implements Iterable<Action>{
|
||||
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 extends Tag> 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<Action>{
|
||||
|
||||
@Override
|
||||
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 extends Tag> 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<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm,String...errors) {
|
||||
preForm.add(conditions.list());
|
||||
return super.properties(preForm, formInputs, postForm,errors);
|
||||
Window win = super.properties(preForm, formInputs, postForm,errors);
|
||||
Optional<Fieldset> 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<Tag> children = actionFieldSet.get().children();
|
||||
children.insertElementAt(new Tag("h3").content(t("Actions in case conditions are fulfilled")),1);
|
||||
LOG.debug("children: "+children);
|
||||
Optional<Tag> 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 <em>not</em> fulfilled")),0);
|
||||
} else {
|
||||
children.add(new Tag("h3").content(t("Actions in case conditions are <em>not</em> fulfilled")));
|
||||
elseActions.listAt(actionFieldSet.get());
|
||||
}
|
||||
}
|
||||
|
||||
return win;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -69,14 +69,14 @@ public class WaitForContact extends ActionList {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tag list() {
|
||||
Tag list = super.list();
|
||||
public <T extends Tag> 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);
|
||||
|
||||
@@ -31,6 +31,9 @@ public class ConditionList extends Condition implements Iterable<Condition>{
|
||||
this.conditions.addAll(conditions.conditions);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
conditions.clear();
|
||||
}
|
||||
|
||||
public boolean fulfilledBy(Context context) {
|
||||
for (Condition condition : conditions) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -129,11 +129,11 @@ public class Switch extends Tile{
|
||||
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> 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);
|
||||
}
|
||||
|
||||
@@ -149,18 +149,18 @@ public abstract class Tile extends BaseClass implements Comparable<Tile> {
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user