From 3567a9c5b7f031481789a7196b18f2e89804f847 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 Date: Sun, 15 Jun 2025 18:09:04 -0400 Subject: [PATCH 1/3] Initial Commit --- .../skript/expressions/ExprDecimalPlaces.java | 44 +++++++++++++++++++ .../syntaxes/expressions/ExprDecimalPlaces | 6 +++ 2 files changed, 50 insertions(+) create mode 100644 src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java create mode 100644 src/test/skript/tests/syntaxes/expressions/ExprDecimalPlaces diff --git a/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java b/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java new file mode 100644 index 00000000000..12aa433ec93 --- /dev/null +++ b/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java @@ -0,0 +1,44 @@ +package ch.njol.skript.expressions; + +import ch.njol.skript.doc.Description; +import ch.njol.skript.doc.Example; +import ch.njol.skript.doc.Name; +import ch.njol.skript.doc.Since; +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import ch.njol.util.Math2; +import org.jetbrains.annotations.Nullable; + +@Name("Number of Decimal Places") +@Description("Gets the number of decimal places in a number.") +@Example(""" + set {_decimalPlaces} to the number of decimal places from 1.23456789 + # {_decimalPlaces} = 8 + """) +@Since("INSERT VERSION") +public class ExprDecimalPlaces extends SimplePropertyExpression { + + static { + register(ExprDecimalPlaces.class, Long.class, "number of decimal places", "numbers"); + } + + @Override + public @Nullable Long convert(Number number) { + if (!(number instanceof Double doubleValue)) + return null; + String[] split = doubleValue.toString().split("\\."); + if (split.length != 2) + return null; + return Math2.fit(0, split[1].length(), Long.MAX_VALUE); + } + + @Override + public Class getReturnType() { + return Long.class; + } + + @Override + protected String getPropertyName() { + return "number of decimal places"; + } + +} diff --git a/src/test/skript/tests/syntaxes/expressions/ExprDecimalPlaces b/src/test/skript/tests/syntaxes/expressions/ExprDecimalPlaces new file mode 100644 index 00000000000..83affe55858 --- /dev/null +++ b/src/test/skript/tests/syntaxes/expressions/ExprDecimalPlaces @@ -0,0 +1,6 @@ +test "decimal places": + assert (the number of decimal places of 1.234) is 3 with "Should return 3 decimal places" + assert (the number of decimal places of 1.23456789) is 8 with "Should return 8 decimal places" + assert (the number of decimal places of 1.000000000000001) is 15 with "Should return 15 decimal places + assert (the number of decimal places of 1.0000000000) is not set with "Should return null for trailing zeros" + assert (the number of decimal places of 1) is not set with "Should return null for no decimal number" From ea29fc98162f852288b5c533d6eb6b64fc6cb6cf Mon Sep 17 00:00:00 2001 From: SirSmurfy2 Date: Sun, 15 Jun 2025 18:13:57 -0400 Subject: [PATCH 2/3] Update ExprDecimalPlaces.java --- src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java b/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java index 12aa433ec93..08777a20dd5 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java +++ b/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java @@ -11,7 +11,7 @@ @Name("Number of Decimal Places") @Description("Gets the number of decimal places in a number.") @Example(""" - set {_decimalPlaces} to the number of decimal places from 1.23456789 + set {_decimalPlaces} to the number of decimal places of 1.23456789 # {_decimalPlaces} = 8 """) @Since("INSERT VERSION") From 128b911aefe690a1f26527215a6ef23611b3c405 Mon Sep 17 00:00:00 2001 From: SirSmurfy2 Date: Wed, 18 Jun 2025 23:42:28 -0400 Subject: [PATCH 3/3] Requested Changes --- .../skript/expressions/ExprDecimalPlaces.java | 127 +++++++++++++++--- .../syntaxes/expressions/ExprDecimalPlaces | 23 +++- 2 files changed, 130 insertions(+), 20 deletions(-) diff --git a/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java b/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java index 08777a20dd5..bc19c745cc1 100644 --- a/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java +++ b/src/main/java/ch/njol/skript/expressions/ExprDecimalPlaces.java @@ -1,34 +1,123 @@ package ch.njol.skript.expressions; +import ch.njol.skript.Skript; +import ch.njol.skript.SkriptConfig; import ch.njol.skript.doc.Description; import ch.njol.skript.doc.Example; import ch.njol.skript.doc.Name; import ch.njol.skript.doc.Since; -import ch.njol.skript.expressions.base.SimplePropertyExpression; -import ch.njol.util.Math2; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser.ParseResult; +import ch.njol.skript.lang.SyntaxStringBuilder; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import org.bukkit.event.Event; import org.jetbrains.annotations.Nullable; +import java.util.ArrayList; +import java.util.List; + @Name("Number of Decimal Places") -@Description("Gets the number of decimal places in a number.") +@Description(""" + Gets the number of decimal places in a number. + This expression will limit the number of decimal places to the 'number accuracy' option in the config, which is 2 by default. + Providing a custom limit will override the default behavior with the provided integer limit. + Specifying 'with no limit' will get as many decimal places as possible from the provided number(s). + """) +@Example(""" + # the 'number accuracy' option in the config is 2 by default + set {_decimalPlaces1} to the number of decimal places of 1.2345 + # {_decimalPlaces} = 2 + set {_decimalPlaces} to the number of decimal places 1.2 + # {_decimalPlaces} = 1 + set {_decimalPlaces2} to the number of decimal places of 1.00000001 + # {_decimalPlaces} = 2 + """) @Example(""" - set {_decimalPlaces} to the number of decimal places of 1.23456789 + set {_decimalPlaces} to the number of decimal places of 1.234567 with a limit of 4 + # {_decimalPlaces} = 4 + set {_decimalPlaces} to the number of decimal places of 1.23456 with a limit of 7 + # {_decimalPlaces} = 5 + set {_decimalPlaces} to the number of decimal places of 1.000000001 with a limit of 6 + # {_decimalPlaces} = 6 + """) +@Example(""" + set {_decimalPlaces} to the number of decimal places of 1.23456789 with no limit # {_decimalPlaces} = 8 + set {_decimalPlaces} to the number of decimal places of 1.0000000000001 with no limit + # {_decimalPlaces} = 13 + """) +@Example(""" + set {_decimalPlaces} to the number of decimal places of 1 + set {_decimalPlaces} to the number of decimal places of 1.00000000000 + set {_decimalPlaces} to the number of decimal places of 1.00000 with a limit of 4 + set {_decimalPlaces} to the number of decimal places of 1.0000000 with no limit + # {_decimalPlaces} = """) @Since("INSERT VERSION") -public class ExprDecimalPlaces extends SimplePropertyExpression { +public class ExprDecimalPlaces extends SimpleExpression { + + private static final double EPSILON = 1e-9; static { - register(ExprDecimalPlaces.class, Long.class, "number of decimal places", "numbers"); + Skript.registerExpression(ExprDecimalPlaces.class, Long.class, ExpressionType.COMBINED, + "[the] number of decimal places of %numbers% [limited:with a (limit|cap) of %-integer%]", + "[the] number of decimal places of %numbers% with no (limit|cap)"); + } + + private Expression numbers; + private @Nullable Expression limit; + private boolean isLimited; + private boolean isUnlimited; + + @Override + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, ParseResult parseResult) { + //noinspection unchecked + numbers = (Expression) exprs[0]; + isLimited = parseResult.hasTag("limited"); + isUnlimited = matchedPattern == 1; + if (isLimited) { + //noinspection unchecked + limit = (Expression) exprs[1]; + } + return true; + } + + @Override + protected Long @Nullable [] get(Event event) { + List decimalPlaces = new ArrayList<>(); + Integer limit = Integer.MAX_VALUE; + if (isLimited) { + assert this.limit != null; + limit = this.limit.getSingle(event); + if (limit == null) + return null; + } else if (!isUnlimited) { + limit = SkriptConfig.numberAccuracy.value(); + } + for (Number number : numbers.getArray(event)) { + if (!(number instanceof Double doubleValue)) { + continue; + } + double x = Double.valueOf(doubleValue); + long decimalPlace = 0L; + for (int i = 0; i < limit; i++) { + if (Math.abs(x % 1) > EPSILON && Math.abs((x % 1) - 1) > EPSILON) { + x *= 10; + decimalPlace++; + } else { + break; + } + } + decimalPlaces.add(decimalPlace); + } + return decimalPlaces.toArray(Long[]::new); } @Override - public @Nullable Long convert(Number number) { - if (!(number instanceof Double doubleValue)) - return null; - String[] split = doubleValue.toString().split("\\."); - if (split.length != 2) - return null; - return Math2.fit(0, split[1].length(), Long.MAX_VALUE); + public boolean isSingle() { + return numbers.isSingle(); } @Override @@ -37,8 +126,16 @@ public Class getReturnType() { } @Override - protected String getPropertyName() { - return "number of decimal places"; + public String toString(@Nullable Event event, boolean debug) { + SyntaxStringBuilder builder = new SyntaxStringBuilder(event, debug); + builder.append("the number of decimal places of", numbers); + if (isLimited) { + assert limit != null; + builder.append("with a limit of", limit); + } else if (isUnlimited) { + builder.append("with no limit"); + } + return builder.toString(); } } diff --git a/src/test/skript/tests/syntaxes/expressions/ExprDecimalPlaces b/src/test/skript/tests/syntaxes/expressions/ExprDecimalPlaces index 83affe55858..f92423c38de 100644 --- a/src/test/skript/tests/syntaxes/expressions/ExprDecimalPlaces +++ b/src/test/skript/tests/syntaxes/expressions/ExprDecimalPlaces @@ -1,6 +1,19 @@ test "decimal places": - assert (the number of decimal places of 1.234) is 3 with "Should return 3 decimal places" - assert (the number of decimal places of 1.23456789) is 8 with "Should return 8 decimal places" - assert (the number of decimal places of 1.000000000000001) is 15 with "Should return 15 decimal places - assert (the number of decimal places of 1.0000000000) is not set with "Should return null for trailing zeros" - assert (the number of decimal places of 1) is not set with "Should return null for no decimal number" + assert (the number of decimal places of 1.2) is 1 with "Decimal places should be 1 (number accuracy)" + assert (the number of decimal places of 1.234) is 2 with "Decimal places should be limited to 2 (number accuracy)" + + assert (the number of decimal places of 1.2345 with a limit of 3) is 3 with "Decimal places should be limited to 3 (limit)" + assert (the number of decimal places of 1.2345 with a limit of 4) is 4 with "Decimal places should be 4 (limit)" + + assert (the number of decimal places of 1.23456789 with no limit) is 8 with "Decimal places should be 8 (no limit)" + assert (the number of decimal places of 1.23456789123456789 with no limit) is 17 with "Decimal places should be 17 (no limit)" + + assert (the number of decimal places of 1.00000000) is not set with "Decimal places should return null for trailing zeros" + assert (the number of decimal places of 1.00000000 with a limit of 4) is not set with "Decimal places should return null for trailing zeros (limit)" + assert (the number of decimal places of 1.00000000 with no limit) is not set with "Decimal places should return null for trailing zeros (no limit)" + + assert (the number of decimal places of 1.0000001) is 2 with "Decimal places of trailing zeros and a one, should be 2 (number accuracy)" + assert (the number of decimal places of 1.0000001 with a limit of 5) is 5 with "Decimal places of trailing zeros and a one, should be 5 (limit)" + assert (the number of decimal places of 1.0000001 with no limit) is 7 with "Decimal places of trailing zeros and a one, should be 7 (no limit)" + + assert (the number of decimal places of 1) is not set with "Decimal places of '1' should be null"