From e65c40268437051cb1752e85f5bc19daa3026846 Mon Sep 17 00:00:00 2001 From: Marc Baloup Date: Thu, 7 May 2020 18:37:06 +0200 Subject: [PATCH] Suggestions + BiMap improvement --- src/main/java/fr/pandacube/util/BiMap.java | 17 ++- src/main/java/fr/pandacube/util/ListUtil.java | 13 +++ .../pandacube/util/commands/Suggestions.java | 100 +++++++++++++++++- 3 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 src/main/java/fr/pandacube/util/ListUtil.java diff --git a/src/main/java/fr/pandacube/util/BiMap.java b/src/main/java/fr/pandacube/util/BiMap.java index 3f2e0cc..7da87c7 100644 --- a/src/main/java/fr/pandacube/util/BiMap.java +++ b/src/main/java/fr/pandacube/util/BiMap.java @@ -1,8 +1,10 @@ package fr.pandacube.util; +import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map.Entry; +import java.util.Set; import java.util.function.BiConsumer; public class BiMap implements Iterable> { @@ -49,7 +51,15 @@ public class BiMap implements Iterable> { @Override public Iterator> iterator() { - return map.entrySet().iterator(); + return Collections.unmodifiableSet(map.entrySet()).iterator(); + } + + public Set keySet() { + return Collections.unmodifiableSet(map.keySet()); + } + + public Set valuesSet() { + return Collections.unmodifiableSet(inversedMap.keySet()); } public synchronized void forEach(BiConsumer c) { @@ -61,5 +71,10 @@ public class BiMap implements Iterable> { public int size() { return map.size(); } + + public synchronized void clear() { + map.clear(); + inversedMap.clear(); + } } diff --git a/src/main/java/fr/pandacube/util/ListUtil.java b/src/main/java/fr/pandacube/util/ListUtil.java new file mode 100644 index 0000000..45578ef --- /dev/null +++ b/src/main/java/fr/pandacube/util/ListUtil.java @@ -0,0 +1,13 @@ +package fr.pandacube.util; + +import java.util.List; + +public class ListUtil { + + + public static void addLongRangeToList(List list, long min, long max) { + for (long i = min; i <= max; i++) { + list.add(i); + } + } +} diff --git a/src/main/java/fr/pandacube/util/commands/Suggestions.java b/src/main/java/fr/pandacube/util/commands/Suggestions.java index 765f0a4..c2ca298 100644 --- a/src/main/java/fr/pandacube/util/commands/Suggestions.java +++ b/src/main/java/fr/pandacube/util/commands/Suggestions.java @@ -7,12 +7,18 @@ import java.util.Collections; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; -import java.util.stream.IntStream; import java.util.stream.Stream; +import fr.pandacube.util.ListUtil; + @FunctionalInterface public interface Suggestions { + /** + * Number of suggestion visible at once without having to scrolleeeeeeeeeeeeeeee + */ + public static int VISIBLE_SUGGESTION_COUNT = 10; + public abstract List getSuggestions(S sender, int tokenIndex, String token, String[] args); @@ -74,14 +80,93 @@ public interface Suggestions { }; } + + /** + * Create a {@link Suggestions} that suggest numbers according to the provided range. + * + * The current implementation only support range that include either -1 or 1. + * @param min + * @param max + * @return + */ public static Suggestions fromIntRange(int min, int max) { - return (s, ti, token, a) -> { - return collectFilteredStream(IntStream.range(min, max + 1).mapToObj(Integer::toString), token); - }; + return fromLongRange(min, max); } + + /** + * Create a {@link Suggestions} that suggest numbers according to the provided range. + * + * The current implementation only support range that include either -1 or 1. + * @param min + * @param max + * @return + */ + public static Suggestions fromLongRange(long min, long max) { + if (max < min) { + throw new IllegalArgumentException("min should be less or equals than max"); + } + return (s, ti, token, a) -> { + try { + List proposedValues = new ArrayList<>(); + if (token.length() == 0) { + long start = Math.max(Math.max(Math.min(-4, max - 9), min), -9); + long end = Math.min(Math.min(start + 9, max), 9); + ListUtil.addLongRangeToList(proposedValues, start, end); + } + else if (token.length() == 1) { + if (token.charAt(0) == '0') { + if (min > 0 || max < 0) { + return Collections.emptyList(); + } + else + return Collections.singletonList(token); + } + else if (token.charAt(0) == '-') { + ListUtil.addLongRangeToList(proposedValues, Math.max(-9, min), -1); + } + else { + long lToken = Long.parseLong(token); + if (lToken > max) { + return Collections.emptyList(); + } + + lToken *= 10; + if (lToken > max) { + return Collections.singletonList(token); + } + + ListUtil.addLongRangeToList(proposedValues, lToken, Math.min(lToken + 9, max)); + } + } + else { + long lToken = Long.parseLong(token); + if (lToken < min || lToken > max) { + return Collections.emptyList(); + } + + lToken *= 10; + if (lToken < min || lToken > max) { + return Collections.singletonList(token); + } + + if (lToken < 0) { + ListUtil.addLongRangeToList(proposedValues, Math.max(lToken - 9, min), lToken); + } + else { + ListUtil.addLongRangeToList(proposedValues, lToken, Math.min(lToken + 9, max)); + } + } + + return collectFilteredStream(proposedValues.stream().map(i -> i.toString()), token); + } catch (NumberFormatException e) { + return Collections.emptyList(); + } + }; + } + /** * Create a {@link Suggestions} that support greedy strings argument using the suggestion from this {@link Suggestions}. * @param args all the arguments currently in the buffer @@ -121,4 +206,11 @@ public interface Suggestions { + public default Suggestions requires(Predicate check) { + return (s, ti, to, a) -> { + return check.test(s) ? getSuggestions(s, ti, to, a) : Collections.emptyList(); + }; + } + + } \ No newline at end of file