Skip to content

Commit

Permalink
Adds Clamp Function (#5573)
Browse files Browse the repository at this point in the history
  • Loading branch information
sovdeeth authored Jun 25, 2023
1 parent 1949a23 commit 302f8f9
Show file tree
Hide file tree
Showing 2 changed files with 84 additions and 12 deletions.
53 changes: 41 additions & 12 deletions src/main/java/ch/njol/skript/classes/data/DefaultFunctions.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,10 @@
*/
package ch.njol.skript.classes.data;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;

import ch.njol.skript.lang.function.FunctionEvent;
import ch.njol.skript.lang.function.JavaFunction;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.util.Vector;

import ch.njol.skript.expressions.base.EventValueExpression;
import ch.njol.skript.lang.function.FunctionEvent;
import ch.njol.skript.lang.function.Functions;
import ch.njol.skript.lang.function.JavaFunction;
import ch.njol.skript.lang.function.Parameter;
import ch.njol.skript.lang.function.SimpleJavaFunction;
import ch.njol.skript.lang.util.SimpleLiteral;
Expand All @@ -41,8 +32,16 @@
import ch.njol.util.Math2;
import ch.njol.util.StringUtils;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.util.Vector;
import org.eclipse.jdt.annotation.Nullable;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Calendar;

public class DefaultFunctions {

private static String str(double n) {
Expand Down Expand Up @@ -305,7 +304,37 @@ public Number[] executeSimple(Object[][] params) {
}.description("Returns the minimum number from a list of numbers.")
.examples("min(1) = 1", "min(1, 2, 3, 4) = 1", "min({some list variable::*})")
.since("2.2"));


Functions.registerFunction(new SimpleJavaFunction<Number>("clamp", new Parameter[]{
new Parameter<>("values", DefaultClasses.NUMBER, false, null),
new Parameter<>("min", DefaultClasses.NUMBER, true, null),
new Parameter<>("max", DefaultClasses.NUMBER, true, null)
}, DefaultClasses.NUMBER, false) {
@Override
public @Nullable Number[] executeSimple(Object[][] params) {
Number[] values = (Number[]) params[0];
Double[] clampedValues = new Double[values.length];
double min = ((Number) params[1][0]).doubleValue();
double max = ((Number) params[2][0]).doubleValue();
// we'll be nice and swap them if they're in the wrong order
double trueMin = Math.min(min, max);
double trueMax = Math.max(min, max);
for (int i = 0; i < values.length; i++) {
double value = values[i].doubleValue();
clampedValues[i] = Math.max(Math.min(value, trueMax), trueMin);
}
return clampedValues;
}
}).description("Clamps one or more values between two numbers.")
.examples(
"clamp(5, 0, 10) = 5",
"clamp(5.5, 0, 5) = 5",
"clamp(0.25, 0, 0.5) = 0.25",
"clamp(5, 7, 10) = 7",
"clamp((5, 0, 10, 9, 13), 7, 10) = (7, 7, 10, 9, 10)",
"set {_clamped::*} to clamp({_values::*}, 0, 10)")
.since("INSERT VERSION");

// misc

Functions.registerFunction(new SimpleJavaFunction<World>("world", new Parameter[] {
Expand Down
43 changes: 43 additions & 0 deletions src/test/skript/tests/syntaxes/functions/clamp.sk
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
test "clamp numbers":
# Normal Cases
assert clamp(1, 0, 2) is 1 with "(single ints) min < value < max"
assert clamp(1, 1, 2) is 1 with "(single ints) min = value < max"
assert clamp(2, 1, 2) is 2 with "(single ints) min < value = max"
assert clamp(0, 1, 2) is 1 with "(single ints) value < min < max"
assert clamp(3, 1, 2) is 2 with "(single ints) min < max < value"
assert clamp(3, 2, 1) is 2 with "(single ints) max < min < value"

assert clamp(1.999, 0.0, 2.0) is 1.999 with "(single floats) min < value < max"
assert clamp(1.999, 1.999, 2.0) is 1.999 with "(single floats) min = value < max"
assert clamp(2.0, 1.999, 2.0) is 2.0 with "(single floats) min < value = max"
assert clamp(0.0, 1.999, 2.0) is 1.999 with "(single floats) value < min < max"
assert clamp(3.0, 1.999, 2.0) is 2.0 with "(single floats) min < max < value"
assert clamp(2.999, 2.0, 1.999) is 2.0 with "(single floats) max < min < value"

# Lists
set {_expected::*} to (0, 0, 1, 2, 2, and 2)
# this is dumb but comparing the lists directly didn't work
set {_got::*} to clamp((-1, 0, 1, 2, 3, and 4), 0, 2)
loop {_expected::*}:
assert {_got::%loop-index%} is loop-value with "(multiple ints)"
set {_got::*} to clamp((-1.999, 0.0, 1.0, 2.0, 3.0, and 4.0), 0.0, 2.0)
loop {_expected::*}:
assert {_got::%loop-index%} is loop-value with "(multiple floats)"

# Edge Cases
assert clamp(1, {_null}, 2) is not set with "(single ints) min = null"
assert clamp(2, 1, {_null}) is not set with "(single ints) max = null"
assert clamp({_null}, 1, 2) is not set with "(single ints) value = null"
assert clamp(1, 0, NaN value) is not clamp(1, 0, NaN value) with "(single ints) min < value < NaN"
assert clamp(1, NaN value, 2) is not clamp(1, NaN value, 2) with "(single ints) NaN < value < max"
assert clamp(NaN value, 1, 2) is not clamp(NaN value, 1, 2) with "(single ints) min < NaN < max"
assert clamp(infinity value, 1, 2) is 2 with "(single ints) min < infinity < max"
assert clamp(-infinity value, 1, 2) is 1 with "(single ints) min < -infinity < max"
assert clamp(1, 0, infinity value) is 1 with "(single ints) min < value < infinity"
assert clamp(1, -infinity value, 2) is 1 with "(single ints) -infinity < value < max"

set {_expected::*} to (NaN value, 0.0, and 2.0)
set {_got::*} to clamp(({_null}, NaN value, -infinity value, infinity value), 0.0, 2.0)
assert number within {_got::1} is not number within {_got::1} with "(edge cases list) NaN" # need within because the variables weren't cooperating
assert {_got::2} is {_expected::2} with "(edge cases list) -infinity"
assert {_got::3} is {_expected::3} with "(edge cases list) infinity"

0 comments on commit 302f8f9

Please sign in to comment.