Skip to content

Commit

Permalink
Changes CondCompare to be able to directly compare two AND lists. (#6389
Browse files Browse the repository at this point in the history
)

* Add direct comparison and a few more tests

* Update CondCompare.java
  • Loading branch information
sovdeeth authored Apr 14, 2024
1 parent 441f770 commit 7759802
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 8 deletions.
45 changes: 37 additions & 8 deletions src/main/java/ch/njol/skript/conditions/CondCompare.java
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,8 @@ private Literal<?> attemptReconstruction(UnparsedLiteral one, Expression<?> two)
* a # x and y === a # x && a # y
* a # x or y === a # x || a # y
* a and b # x and y === a # x and y && b # x and y === a # x && a # y && b # x && b # y
* - Special case if # is =: (a and b = x and y) === (a = x && b = y)
* - This allows direct list comparisons for equality.
* a and b # x or y === a # x or y && b # x or y
* a or b # x and y === a # x and y || b # x and y
* a or b # x or y === a # x or y || b # x or y
Expand Down Expand Up @@ -343,13 +345,20 @@ private Literal<?> attemptReconstruction(UnparsedLiteral one, Expression<?> two)
*/
@Override
@SuppressWarnings("unchecked")
public boolean check(final Event e) {
public boolean check(final Event event) {
final Expression<?> third = this.third;
return first.check(e, (Checker<Object>) o1 ->
second.check(e, (Checker<Object>) o2 -> {
// if we are directly comparing the equality of two AND lists, we should change behavior to
// compare element-wise, instead of comparing everything to everything.
if (relation == Relation.EQUAL && third == null &&
first.getAnd() && !first.isSingle() &&
second.getAnd() && !second.isSingle())
return compareLists(event);

return first.check(event, (Checker<Object>) o1 ->
second.check(event, (Checker<Object>) o2 -> {
if (third == null)
return relation.isImpliedBy(comparator != null ? comparator.compare(o1, o2) : Comparators.compare(o1, o2));
return third.check(e, (Checker<Object>) o3 -> {
return third.check(event, (Checker<Object>) o3 -> {
boolean isBetween;
if (comparator != null) {
if (o1 instanceof Cyclical<?> && o2 instanceof Cyclical<?> && o3 instanceof Cyclical<?>) {
Expand Down Expand Up @@ -381,15 +390,35 @@ public boolean check(final Event e) {
}
), isNegated());
}


/**
* Used to directly compare two lists for equality.
* This method assumes that {@link CondCompare#first} and {@link CondCompare#second} are both non-single.
* @param event the event with which to evaluate {@link CondCompare#first} and {@link CondCompare#second}.
* @return Whether every element in {@link CondCompare#first} is equal to its counterpart in {@link CondCompare#second}.
* e.g. (1,2,3) = (1,2,3), but (1,2,3) != (3,2,1)
*/
private boolean compareLists(Event event) {
Object[] first = this.first.getArray(event);
Object[] second = this.second.getArray(event);
boolean shouldMatch = !isNegated(); // for readability
if (first.length != second.length)
return !shouldMatch;
for (int i = 0; i < first.length; i++) {
if (!relation.isImpliedBy(comparator != null ? comparator.compare(first[i], second[i]) : Comparators.compare(first[i], second[i])))
return !shouldMatch;
}
return shouldMatch;
}

@Override
public String toString(final @Nullable Event e, final boolean debug) {
public String toString(final @Nullable Event event, final boolean debug) {
String s;
final Expression<?> third = this.third;
if (third == null)
s = first.toString(e, debug) + " is " + (isNegated() ? "not " : "") + relation + " " + second.toString(e, debug);
s = first.toString(event, debug) + " is " + (isNegated() ? "not " : "") + relation + " " + second.toString(event, debug);
else
s = first.toString(e, debug) + " is " + (isNegated() ? "not " : "") + "between " + second.toString(e, debug) + " and " + third.toString(e, debug);
s = first.toString(event, debug) + " is " + (isNegated() ? "not " : "") + "between " + second.toString(event, debug) + " and " + third.toString(event, debug);
if (debug)
s += " (comparator: " + comparator + ")";
return s;
Expand Down
16 changes: 16 additions & 0 deletions src/test/skript/tests/syntaxes/conditions/CondCompare.sk
Original file line number Diff line number Diff line change
@@ -1,4 +1,20 @@
test "compare":
assert 1 is 1 with "Number isn't itself"
assert 1 is not 2 with "Number is equal to other number"
assert 1 is less than 2 with "Number is not less than a larger number"
assert 1 is greater than 0 with "Number is not greater than a smaller number"
assert 1 is greater than or equal to 0 and 1 with "Number is not greater than or equal to two smaller/equal numbers"
assert 1 is less than or equal to 1 and 2 with "Number is not smaller than or equal to two greater/equal numbers"

assert 1, 2 is 1, 2 with "direct list comparison of equal numbers failed"
assert 1, 2, 3 is not 1, 2 with "direct list comparison of non-equal numbers succeeded"
assert 1, 2 is 1, 2, or 3 with "comparison between AND list of numbers and OR list of superset of numbers failed"
assert 1, 2, 3 is 1 or 2 to fail with "comparison between AND list of numbers and OR list of subset of numbers succeeded"

assert 1, 2, 3 is greater than -1, -2, -3 with "Numbers are not larger than smaller numbers"
assert 1, 2, 3 is less than 5, 6, 7 with "Numbers are not smaller than larger numbers"
assert 1, 2, 3 is between -1, 1 and 3, 3.5 with "Numbers are not between smaller/equal numbers and larger/equal numbers"

assert 10 is between 5 and 15 with "Number isn't between smaller and larger"
assert 10 is between 9 and 11 with "Number isn't between smaller and larger"
assert 10 is between 11 and 9 with "Number isn't between larger and smaller"
Expand Down

0 comments on commit 7759802

Please sign in to comment.