Working on stores:

* Action to set store values
* Conditions to check store values
* Displaying stored values
This commit is contained in:
2021-10-08 18:47:22 +02:00
parent 005ff02646
commit eeec07900e
14 changed files with 259 additions and 25 deletions

View File

@@ -81,6 +81,7 @@ public interface Constants {
public static final String ROUTE = "route";
public static final String SPEED = "speed";
public static final String STATE = "state";
public static final String SWITCH = "switch";
public static final String TIME = "time";
public static final String TURNOUT = "turnout";
public static final String TYPE = "type";

View File

@@ -1,6 +1,8 @@
package de.srsoftware.web4rail;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Set;
import org.slf4j.Logger;
@@ -9,27 +11,48 @@ import de.srsoftware.web4rail.tags.Select;
public class Store {
public interface Listener{
public void storeUpdated(Store store);
}
private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(Store.class);
private static HashMap<String,Store> stores = new HashMap<>();
private HashSet<Listener> listeners = new HashSet<>();
private String name;
private Integer value = null;
private String value = null;
private Integer intValue = null;
public Store(String name) {
this.name = name;
stores.put(name, this);
}
public void addListener(Listener listener) {
listeners.add(listener);
}
public static Store get(String name) {
Store store = stores.get(name);
if (BaseClass.isNull(store)) store = new Store(name);
return store;
}
public Integer intValue() {
return intValue;
}
public String name() {
return name;
}
public static Set<String> names() {
return stores.keySet();
}
public static void removeListener(Listener listener) {
stores.values().forEach(store -> store.listeners.remove(listener));
}
public static Select selector(Store store) {
Select selector = new Select(Store.class.getSimpleName());
@@ -45,9 +68,19 @@ public class Store {
return BaseClass.t(txt, fills);
}
public void setValue(int newVal) {
public void setValue(String newVal) {
LOG.debug("Updating {}: {} → {}",name,value,newVal);
value = newVal;
intValue = null;
for (char c : value.toCharArray()) {
if (!Character.isDigit(c)) {
if (isSet(intValue)) break;
} else {
int add = ((byte)c-48);
intValue = isNull(intValue) ? add : 10*intValue + add;
}
}
listeners.forEach(listener -> listener.storeUpdated(this));
}
@Override
@@ -55,7 +88,7 @@ public class Store {
return name+"&nbsp;("+(BaseClass.isNull(value) ? t("no value") : value)+")";
}
public Integer value() {
public String value() {
return value;
}
}

View File

@@ -66,6 +66,7 @@ public abstract class Action extends BaseClass {
SetSignal.class,
SetSpeed.class,
SetTurnout.class,
SetValue.class,
ShowText.class,
SplitTrain.class,
StartStopAuto.class,

View File

@@ -34,7 +34,7 @@ public class DelayedAction extends ActionList {
@Override
public boolean fire(Context context) {
try {
int delay = isSet(store) ? store.value() : min_delay + (min_delay < max_delay ? random.nextInt(max_delay - min_delay) : 0);
int delay = isSet(store) ? store.intValue() : min_delay + (min_delay < max_delay ? random.nextInt(max_delay - min_delay) : 0);
new DelayedExecution(delay,this) {

View File

@@ -30,7 +30,7 @@ public class LookupValue extends Action {
try {
if (!isSet(store,lookupTable)) return false;
int value = lookupTable.getValue(context);
store.setValue(value);
store.setValue(""+value);
} catch (NullPointerException npe) {
return false;
}

View File

@@ -0,0 +1,76 @@
package de.srsoftware.web4rail.actions;
import java.util.List;
import org.json.JSONObject;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Params;
import de.srsoftware.web4rail.Store;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Window;
public class SetValue extends Action {
private static final String VALUE = "value";
private static final String STORE = "store";
private String value = null;
private Store store = null;
public SetValue(BaseClass parent) {
super(parent);
}
@Override
public boolean fire(Context context) {
try {
if (!isSet(store,value)) return false;
store.setValue(value);
} catch (NullPointerException npe) {
return false;
}
return true;
}
@Override
public JSONObject json() {
JSONObject json = super.json();
if (isSet(value)) json.put(VALUE, value);
if (isSet(store)) json.put(STORE, store.name());
return json;
}
@Override
public Action load(JSONObject json) {
super.load(json);
if (json.has(VALUE)) value = json.getString(VALUE);
if (json.has(STORE)) store = Store.get(json.getString(STORE));
return this;
}
@Override
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm,String...errors) {
formInputs.add(t("Store"), new Input(STORE,isSet(store)?store.name():""));
formInputs.add(t("Value"), new Input(VALUE,isSet(value)?value:0));
return super.properties(preForm, formInputs, postForm,errors);
}
@Override
public String toString() {
if (isSet(store,value)) return t("Set \"{}\" to \"{}\"",store.name(),value);
return "["+t("Click here to setup assignment")+"]";
}
@Override
protected Object update(Params params) {
LOG.debug("update: {}",params);
String newValue = params.getString(VALUE);
if (isSet(newValue)) value = newValue;
String storeName = params.getString(STORE);
if (isSet(storeName) && !storeName.isEmpty()) store = Store.get(storeName);
return super.update(params);
}
}

View File

@@ -11,6 +11,8 @@ import de.srsoftware.web4rail.Params;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Window;
import de.srsoftware.web4rail.tiles.Contact;
import de.srsoftware.web4rail.tiles.Switch;
import de.srsoftware.web4rail.tiles.Tile;
public class TriggerContact extends Action {
@@ -18,64 +20,78 @@ public class TriggerContact extends Action {
super(parent);
}
private Contact contact = null;
private Tile contactOrSwitch = null;
@Override
public boolean fire(Context context) {
if (isSet(contact)) return contact.trigger(200);
if (contactOrSwitch instanceof Contact) return ((Contact)contactOrSwitch).trigger(200);
if (contactOrSwitch instanceof Switch) return ((Switch)contactOrSwitch).trigger(context);
return false;
}
@Override
protected String highlightId() {
return isSet(contact) ? contact.id().toString() : null;
return isSet(contactOrSwitch) ? contactOrSwitch.id().toString() : null;
}
@Override
public JSONObject json() {
JSONObject json = super.json();
if (isSet(contact)) json.put(CONTACT, contact.id());
if (contactOrSwitch instanceof Contact) json.put(CONTACT, contactOrSwitch.id());
if (contactOrSwitch instanceof Switch) json.put(SWITCH, contactOrSwitch.id());
return json;
}
@Override
public Action load(JSONObject json) {
super.load(json);
Id contactId = Id.from(json,CONTACT);
if (isSet(contactId)) new LoadCallback() {
if (json.has(CONTACT)) new LoadCallback() {
@Override
public void afterLoad() {
contact = Contact.get(contactId);
contactOrSwitch = Contact.get(Id.from(json,CONTACT));
}
};
if (json.has(SWITCH)) new LoadCallback() {
@Override
public void afterLoad() {
contactOrSwitch = Switch.get(Id.from(json,SWITCH));
}
};
return this;
}
@Override
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm,String...errors) {
formInputs.add(t("Select contact")+": "+(isNull(contact) ? t("unset") : contact),button(t("Select from plan"),Map.of(ACTION,ACTION_UPDATE,ASSIGN,CONTACT)));
formInputs.add(t("Select contact or switch")+": "+(isNull(contactOrSwitch) ? t("unset") : contactOrSwitch),button(t("Select from plan"),Map.of(ACTION,ACTION_UPDATE,ASSIGN,CONTACT)));
return super.properties(preForm, formInputs, postForm,errors);
}
@Override
protected void removeChild(BaseClass child) {
if (child == contact) contact = null;
if (child == contactOrSwitch) contactOrSwitch = null;
super.removeChild(child);
}
public String toString() {
return isSet(contact) ? t("Trigger {}",contact) : "["+t("Click here to setup contact")+"]";
return isSet(contactOrSwitch) ? t("Trigger {}",contactOrSwitch) : "["+t("Click here to setup contact/switch")+"]";
};
@Override
protected Object update(Params params) {
LOG.debug("update: {}",params);
Id contactId = Id.from(params,CONTACT);
if (isSet(contactId)) contact = Contact.get(contactId);
return properties();
String error = null;
if (isSet(contactId)) {
Tile tile = BaseClass.get(contactId);
if (tile instanceof Contact || tile instanceof Switch) {
contactOrSwitch = tile;
} else error = t("{} is neither a contact nor a switch!",tile);
}
return properties(error);
}
}

View File

@@ -127,6 +127,7 @@ public abstract class Condition extends BaseClass {
OrCondition.class,
PushPullTrain.class,
RouteEndBlock.class,
StoreHasValue.class,
SwitchIsOn.class,
TrainHasTag.class,
TrainIsShunting.class,

View File

@@ -0,0 +1,74 @@
package de.srsoftware.web4rail.conditions;
import java.util.List;
import org.json.JSONObject;
import de.srsoftware.web4rail.Params;
import de.srsoftware.web4rail.Store;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Window;
public class StoreHasValue extends Condition {
private static final String VALUE = "value";
private static final String STORE = "store";
private String value = null;
private Integer intValue = null;
private Store store = null;
private boolean evaluate() {
if (!isSet(store,value)) return false;
if (isSet(intValue)) return store.intValue() == intValue;
return value.equals(store.value());
}
@Override
public boolean fulfilledBy(Context context) {
return evaluate() != inverted;
}
@Override
public JSONObject json() {
JSONObject json = super.json();
if (isSet(value)) json.put(VALUE, value);
if (isSet(store)) json.put(STORE, store.name());
return json;
}
public Condition load(JSONObject json) {
super.load(json);
if (json.has(STORE)) store = Store.get(json.getString(STORE));
if (json.has(VALUE)) {
value = json.getString(VALUE);
try {
intValue = Integer.parseInt(value);
} catch (NumberFormatException nfe) {}
}
return this;
}
@Override
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm,String...errors) {
formInputs.add(t("Select store to read from:"),Store.selector(store));
formInputs.add(t("Value"),new Input(VALUE, isSet(value) ? value : ""));
return super.properties(preForm, formInputs, postForm,errors);
}
@Override
public String toString() {
if (isNull(store)) return "["+t("Click setup store lookup")+"]";
return t(inverted ? "Store \"{}\" does not have value \"{}\"" : "Store \"{}\" has value \"{}\"",store.name(),value) ;
}
@Override
protected Object update(Params params) {
String storeName = params.getString(Store.class.getSimpleName());
if (isSet(storeName)) store = Store.get(storeName);
String newVal = params.getString(VALUE);
if (isSet(newVal)) value = newVal;
return super.update(params);
}
}

View File

@@ -47,7 +47,7 @@ public class TrainHasTag extends Condition {
@Override
protected Window properties(List<Fieldset> preForm, FormInput formInputs, List<Fieldset> postForm,String...errors) {
formInputs.add(t("Tag"),new Input(TAG, tag == null ? "" : tag));
formInputs.add(t("Tag"),new Input(TAG, isNull(tag) ? "" : tag));
return super.properties(preForm, formInputs, postForm,errors);
}

View File

@@ -161,6 +161,10 @@ public class Switch extends Tile{
return state;
}
public boolean trigger(Context context) {
return state ? actionsOn.fire(context) : actionsOff.fire(context);
}
public void state(boolean newState) {
state = newState;

View File

@@ -13,14 +13,16 @@ import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Params;
import de.srsoftware.web4rail.Store;
import de.srsoftware.web4rail.tags.Fieldset;
import de.srsoftware.web4rail.tags.Input;
import de.srsoftware.web4rail.tags.Select;
import de.srsoftware.web4rail.tags.Window;
public class TextDisplay extends StretchableTile {
public class TextDisplay extends StretchableTile implements Store.Listener {
private static final String TEXT = "text";
private String text = "Hello, world!";
private String displayText = text;
@Override
public JSONObject json() {
@@ -29,7 +31,7 @@ public class TextDisplay extends StretchableTile {
@Override
public Tile load(JSONObject json) {
if (json.has(TEXT)) text = json.getString(TEXT);
if (json.has(TEXT)) text(json.getString(TEXT));
return super.load(json);
}
@@ -50,6 +52,12 @@ public class TextDisplay extends StretchableTile {
}
return select;
}
@Override
public void storeUpdated(Store store) {
displayText = text.replace("{"+store.name()+"}", store.value());
plan.place(this);
}
@Override
protected String stretchType() {
@@ -60,13 +68,24 @@ public class TextDisplay extends StretchableTile {
@Override
public Tag tag(Map<String, Object> replacements) throws IOException {
if (isNull(replacements)) replacements = new HashMap<String, Object>();
replacements.put("%text%",text);
replacements.put("%text%",displayText);
Tag tag = super.tag(replacements);
return tag.clazz(tag.get("class")+" fill");
}
public TextDisplay text(String tx) {
text = tx;
displayText = tx;
int pos = text.indexOf("{");
Store.removeListener(this);
while (pos > -1) {
int end = text.indexOf("}",pos);
if (end < 0) break;
String storeName = text.substring(pos+1, end);
Store.get(storeName).addListener(this);
pos = text.indexOf("{",end);
}
return this;
}