Skip to content

Commit

Permalink
Implement exclusive attribute on dummy variables (#1245)
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Herrera <[email protected]>
  • Loading branch information
Pablete1234 authored Sep 21, 2023
1 parent 2c25672 commit f9da16d
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 4 deletions.
6 changes: 5 additions & 1 deletion core/src/main/java/tc/oc/pgm/variables/VariableParser.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tc.oc.pgm.variables;

import com.google.common.collect.Range;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.regex.Pattern;
Expand Down Expand Up @@ -57,7 +58,10 @@ public VariableDefinition<?> parse(Element el) throws InvalidXMLException {
public VariableDefinition<?> parseDummy(Element el, String id) throws InvalidXMLException {
Class<? extends Filterable<?>> scope = Filterables.parse(Node.fromRequiredAttr(el, "scope"));
double def = XMLUtils.parseNumber(Node.fromAttr(el, "default"), Double.class, 0d);
return new VariableDefinition<>(id, scope, true, vd -> new DummyVariable<>(vd, def));
Integer excl =
XMLUtils.parseNumberInRange(
Node.fromAttr(el, "exclusive"), Integer.class, Range.closed(1, 50), null);
return new VariableDefinition<>(id, scope, true, vd -> new DummyVariable<>(vd, def, excl));
}

@MethodParser("lives")
Expand Down
28 changes: 25 additions & 3 deletions core/src/main/java/tc/oc/pgm/variables/types/DummyVariable.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package tc.oc.pgm.variables.types;

import java.lang.reflect.Array;
import java.util.HashMap;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.filters.FilterMatchModule;
import tc.oc.pgm.filters.Filterable;
import tc.oc.pgm.variables.VariableDefinition;
Expand All @@ -11,20 +13,40 @@ public class DummyVariable<T extends Filterable<?>> extends AbstractVariable<T>
private final double def;
private final Map<T, Double> values;

public DummyVariable(VariableDefinition<T> definition, double def) {
// Circular buffer of last additions, head marks next location to replace
private @Nullable final T[] additions;
private int head = 0;

public DummyVariable(VariableDefinition<T> definition, double def, Integer exclusive) {
super(definition);
this.def = def;
this.values = new HashMap<>();
//noinspection unchecked
this.additions =
exclusive == null ? null : (T[]) Array.newInstance(definition.getScope(), exclusive);
}

@Override
protected double getValueImpl(T obj) {
return values.computeIfAbsent(obj, k -> def);
return values.getOrDefault(obj, def);
}

@Override
protected void setValueImpl(T obj, double value) {
values.put(obj, value);
Double oldVal = values.put(obj, value);

// Limit is enabled, and we're not replacing a pre-existing key
if (additions != null && oldVal == null) {
T toRemove = additions[head];
if (toRemove != null) {
values.remove(toRemove);
toRemove.moduleRequire(FilterMatchModule.class).invalidate(toRemove);
}

additions[head] = obj;
head = (head + 1) % additions.length;
}

// For performance reasons, let's avoid launching an event for every variable change
obj.moduleRequire(FilterMatchModule.class).invalidate(obj);
}
Expand Down

0 comments on commit f9da16d

Please sign in to comment.