Skip to content

Commit

Permalink
Allow value with formula in variable filter
Browse files Browse the repository at this point in the history
Signed-off-by: Pablo Herrera <[email protected]>
  • Loading branch information
Pablete1234 committed Nov 7, 2024
1 parent 144ca2d commit bcb644e
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package tc.oc.pgm.filters.matcher.match;

import com.google.common.collect.Range;
import tc.oc.pgm.api.filter.Filter;
import tc.oc.pgm.api.filter.FilterDefinition;
import tc.oc.pgm.api.filter.Filterables;
import tc.oc.pgm.api.filter.query.MatchQuery;
import tc.oc.pgm.api.filter.query.PartyQuery;
Expand All @@ -10,6 +12,7 @@
import tc.oc.pgm.filters.Filterable;
import tc.oc.pgm.filters.matcher.WeakTypedFilter;
import tc.oc.pgm.filters.matcher.party.CompetitorFilter;
import tc.oc.pgm.util.math.Formula;
import tc.oc.pgm.util.xml.InvalidXMLException;
import tc.oc.pgm.util.xml.Node;
import tc.oc.pgm.variables.Variable;
Expand Down Expand Up @@ -39,6 +42,14 @@ public static VariableFilter<?> of(Variable<?> var, Integer idx, Range<Double> r
}
}

public static <T extends Filterable<?>> Filter of(
Formula<?> formula, Class<T> scope, Range<Double> range) throws InvalidXMLException {
//noinspection unchecked
return scope == Party.class
? new TeamFormula((Formula<Party>) formula, range)
: new GenericFormula<>((Formula<T>) formula, scope, range);
}

@Override
public QueryResponse queryTyped(Q query) {
Filterable<?> filterable = query.extractFilterable();
Expand Down Expand Up @@ -127,4 +138,55 @@ protected double getValue(Variable<?> variable, Filterable<?> filterable) {
return ((Variable.Indexed<?>) variable).getValue(filterable, idx);
}
}

public static class GenericFormula<T extends Filterable<?>> implements FilterDefinition {
private final Formula<T> formula;
private final Class<T> scope;
private final Range<Double> values;

public GenericFormula(Formula<T> variable, Class<T> scope, Range<Double> values) {
this.formula = variable;
this.scope = scope;
this.values = values;
}

@Override
public QueryResponse query(Query q) {
T target;
if (!(q instanceof MatchQuery mq) || (target = mq.filterable(scope)) == null)
return QueryResponse.ABSTAIN;
return QueryResponse.fromBoolean(values.contains(formula.apply(target)));
}

@Override
public boolean respondsTo(Class<? extends Query> queryType) {
//noinspection unchecked
return Filterable.class.isAssignableFrom(queryType)
&& Filterables.isAssignable((Class<Filterable<?>>) queryType, scope);
}
}

/**
* Specialization for team formulas implementing CompetitorFilter. Allows team to be set to a
* specific one.
*/
public static class TeamFormula implements CompetitorFilter {
private final Formula<Party> formula;
private final Range<Double> values;

public TeamFormula(Formula<Party> variable, Range<Double> values) {
this.formula = variable;
this.values = values;
}

@Override
public boolean matches(PartyQuery query) {
return values.contains(formula.apply(query.getParty()));
}

@Override
public boolean matches(MatchQuery query, Competitor competitor) {
return matches(competitor);
}
}
}
24 changes: 19 additions & 5 deletions core/src/main/java/tc/oc/pgm/filters/parse/FilterParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.jetbrains.annotations.Nullable;
import tc.oc.pgm.api.filter.Filter;
import tc.oc.pgm.api.filter.FilterDefinition;
import tc.oc.pgm.api.filter.Filterables;
import tc.oc.pgm.api.map.factory.MapFactory;
import tc.oc.pgm.api.player.PlayerRelation;
import tc.oc.pgm.api.region.Region;
Expand Down Expand Up @@ -90,17 +91,20 @@
import tc.oc.pgm.util.math.OffsetVector;
import tc.oc.pgm.util.xml.InvalidXMLException;
import tc.oc.pgm.util.xml.Node;
import tc.oc.pgm.util.xml.XMLFluentParser;
import tc.oc.pgm.util.xml.XMLUtils;
import tc.oc.pgm.variables.Variable;

public abstract class FilterParser implements XMLParser<Filter, FilterDefinition> {

protected final Map<String, Method> methodParsers;
protected final MapFactory factory;
protected final XMLFluentParser parser;
protected final FeatureDefinitionContext features;

public FilterParser(MapFactory factory) {
this.factory = factory;
this.parser = factory.getParser();
this.features = factory.getFeatures();

this.methodParsers = MethodParsers.getMethodParsersForClass(getClass());
Expand Down Expand Up @@ -621,13 +625,23 @@ public PlayerCountFilter parsePlayerCountFilter(Element el) throws InvalidXMLExc

@MethodParser("variable")
public Filter parseVariableFilter(Element el) throws InvalidXMLException {
Variable<?> varDef = features.resolve(Node.fromRequiredAttr(el, "var"), Variable.class);
Integer index = null;
if (varDef.isIndexed())
index = XMLUtils.parseNumber(Node.fromRequiredAttr(el, "index"), Integer.class);
Range<Double> range = XMLUtils.parseNumericRange(new Node(el), Double.class);

VariableFilter<?> filter = VariableFilter.of(varDef, index, range, new Node(el));
Filter filter;
if (el.getAttribute("var") != null) {
Variable<?> varDef = parser.variable(el, "var").required();
Integer index = varDef.isIndexed() ? parser.parseInt(el, "index").required() : null;

filter = VariableFilter.of(varDef, index, range, new Node(el));
} else if (el.getAttribute("value") != null) {
var scope = Filterables.parse(Node.fromRequiredAttr(el, "scope"));
var formula = parser.formula(scope, el, "value").attr().required();

filter = VariableFilter.of(formula, scope, range);
} else {
throw new InvalidXMLException("Expected one of 'var' or 'value'", el);
}

return filter instanceof CompetitorFilter
? parseExplicitTeam(el, (CompetitorFilter) filter)
: filter;
Expand Down

0 comments on commit bcb644e

Please sign in to comment.