2022-07-20 13:18:57 +02:00
|
|
|
|
package fr.pandacube.lib.util;
|
2016-02-16 20:07:51 +01:00
|
|
|
|
|
2018-07-21 17:57:44 +02:00
|
|
|
|
import java.util.List;
|
2016-02-16 20:07:51 +01:00
|
|
|
|
import java.util.Random;
|
2019-03-15 19:01:34 +01:00
|
|
|
|
import java.util.Set;
|
2016-02-16 20:07:51 +01:00
|
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
|
/**
|
|
|
|
|
* Utility class to generate random things.
|
|
|
|
|
*/
|
2016-02-16 20:07:51 +01:00
|
|
|
|
public class RandomUtil {
|
2016-07-14 14:22:23 +02:00
|
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
|
/**
|
|
|
|
|
* The unique {@link Random} instance used in this class. Can also be used else where when needed.
|
|
|
|
|
*/
|
2022-07-10 00:55:56 +02:00
|
|
|
|
public static final Random rand = new Random();
|
2016-07-14 14:22:23 +02:00
|
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
|
/**
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* Returns a randomly generated integer between {@code minInclusive} included and {@code maxExclusive} excluded.
|
2022-07-28 03:11:40 +02:00
|
|
|
|
* This method is safer to use that Random#nextInt(int, int) because it does not check the validity of
|
|
|
|
|
* the parameters.
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* @param minInclusive the minimum value, included.
|
|
|
|
|
* @param maxExclusive the maximum value, excluded.
|
|
|
|
|
* @return a random number between {@code minInclusive} included and {@code maxExclusive} excluded.
|
2022-07-28 03:11:40 +02:00
|
|
|
|
* @see Random#nextInt(int, int)
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* @throws IllegalArgumentException if {@code minInclusive} is greater than {@code maxExclusive}.
|
2022-07-28 01:13:35 +02:00
|
|
|
|
*/
|
2023-06-20 00:15:46 +02:00
|
|
|
|
public static int nextIntBetween(int minInclusive, int maxExclusive) {
|
|
|
|
|
return minInclusive + rand.nextInt(maxExclusive - minInclusive);
|
2016-02-16 20:07:51 +01:00
|
|
|
|
}
|
2016-07-14 14:22:23 +02:00
|
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
|
/**
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* Returns a randomly generated double between {@code minInclusive} included and {@code maxExclusive} excluded.
|
2022-07-28 03:11:40 +02:00
|
|
|
|
* This method is safer to use that Random#nextDouble(double, double) because it does not check the validity of
|
|
|
|
|
* the parameters
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* @param minInclusive the minimum value, included.
|
|
|
|
|
* @param maxExclusive the maximum value, excluded.
|
|
|
|
|
* @return a random number between {@code minInclusive} included and {@code maxExclusive} excluded.
|
2022-07-28 01:13:35 +02:00
|
|
|
|
* @see Random#nextDouble(double, double)
|
|
|
|
|
*/
|
2023-06-20 00:15:46 +02:00
|
|
|
|
public static double nextDoubleBetween(double minInclusive, double maxExclusive) {
|
|
|
|
|
return minInclusive + rand.nextDouble() * (maxExclusive - minInclusive);
|
2016-02-16 20:07:51 +01:00
|
|
|
|
}
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a random element from the provided array.
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* @param array the array in which to pick a value randomly.
|
2022-07-28 01:13:35 +02:00
|
|
|
|
* @return the value randomly picked from the array, or null if the array is null or empty.
|
|
|
|
|
* @param <T> the type of the array elements.
|
|
|
|
|
* @see Random#nextInt(int)
|
|
|
|
|
*/
|
|
|
|
|
public static <T> T arrayElement(T[] array) {
|
|
|
|
|
return (array == null || array.length == 0) ? null : array[rand.nextInt(array.length)];
|
2018-07-21 17:57:44 +02:00
|
|
|
|
}
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a random element from the provided list.
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* @param list the list in which to pick a value randomly.
|
2022-07-28 01:13:35 +02:00
|
|
|
|
* @return the value randomly picked from the list, or null if the array is null or empty.
|
|
|
|
|
* @param <T> the type of the list elements.
|
|
|
|
|
* @see Random#nextInt(int)
|
|
|
|
|
*/
|
|
|
|
|
public static <T> T listElement(List<T> list) {
|
|
|
|
|
return (list == null || list.isEmpty()) ? null : list.get(rand.nextInt(list.size()));
|
2018-07-21 17:57:44 +02:00
|
|
|
|
}
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Returns a random character from the provided string.
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* @param str the string in which to pick a character randomly.
|
2022-07-28 01:13:35 +02:00
|
|
|
|
* @return the character randomly picked from the string, or {@code '\0'} if the string is null or empty.
|
|
|
|
|
* @see Random#nextInt(int)
|
|
|
|
|
*/
|
|
|
|
|
public static char stringChar(String str) {
|
|
|
|
|
return (str == null || str.isEmpty()) ? '\0' : str.charAt(rand.nextInt(str.length()));
|
2022-01-23 16:17:44 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-03-15 19:01:34 +01:00
|
|
|
|
/**
|
2022-07-28 01:13:35 +02:00
|
|
|
|
* Returns a random value from the provided set.
|
|
|
|
|
* @param set the set in which to pick a value randomly.
|
|
|
|
|
* @return the value randomly picked from the list, or null if the set is null or empty.
|
|
|
|
|
* @param <T> the type of the set elements.
|
|
|
|
|
* @implNote The current implementation uses the iterator of the set to pick a random value, since there is no way
|
|
|
|
|
* to directly pick a value using an index.
|
|
|
|
|
* @throws IllegalStateException if the set has reduced in size during the execution of this method, making the
|
|
|
|
|
* iterator reaching the end of the set before getting the value the random generator picked.
|
2019-03-15 19:01:34 +01:00
|
|
|
|
*/
|
|
|
|
|
public static <T> T setElement(Set<T> set) {
|
2022-07-28 01:13:35 +02:00
|
|
|
|
if (set == null || set.isEmpty())
|
|
|
|
|
return null;
|
2019-03-15 19:01:34 +01:00
|
|
|
|
int retI = rand.nextInt(set.size()), i = 0;
|
|
|
|
|
for (T e : set) {
|
|
|
|
|
if (retI == i)
|
|
|
|
|
return e;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
2022-07-28 01:13:35 +02:00
|
|
|
|
throw new IllegalStateException("Should never go to this line of code");
|
2019-03-15 19:01:34 +01:00
|
|
|
|
}
|
2021-08-23 02:24:34 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return a value between 0 and the number of parameter minus 1, using the provided frequencies.
|
2022-07-28 03:11:40 +02:00
|
|
|
|
* <p>
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* The probability of each value to be returned depends on the frequencies provided.
|
|
|
|
|
* @param frequencies the frequencies of each entry
|
2022-07-28 01:13:35 +02:00
|
|
|
|
* @return the index of an entry, or -1 if it is unable to pick anything (all the frequencies are 0 or there is no provided frequency)
|
|
|
|
|
* @throws IllegalArgumentException if frequencies is null.
|
2021-08-23 02:24:34 +02:00
|
|
|
|
*/
|
2022-07-28 01:13:35 +02:00
|
|
|
|
public static int randomIndexOfFrequencies(double... frequencies) {
|
|
|
|
|
if (frequencies == null)
|
|
|
|
|
throw new IllegalArgumentException("frequencies cannot be null");
|
|
|
|
|
int n = frequencies.length;
|
2022-07-10 00:55:56 +02:00
|
|
|
|
double[] fSums = new double[n];
|
2021-08-23 02:24:34 +02:00
|
|
|
|
double sum = 0;
|
2022-07-10 00:55:56 +02:00
|
|
|
|
for (int i = 0; i < n; i++) {
|
2022-07-28 01:13:35 +02:00
|
|
|
|
if (frequencies[i] < 0)
|
|
|
|
|
throw new IllegalArgumentException("frequencies[" + i + "] cannot be negative.");
|
|
|
|
|
fSums[i] = (sum += frequencies[i]);
|
2022-07-10 00:55:56 +02:00
|
|
|
|
}
|
2021-08-23 02:24:34 +02:00
|
|
|
|
double r = rand.nextDouble() * sum;
|
2022-07-10 00:55:56 +02:00
|
|
|
|
for (int i = 0; i < n; i++) {
|
|
|
|
|
if (fSums[i] > r)
|
2021-08-23 02:24:34 +02:00
|
|
|
|
return i;
|
|
|
|
|
}
|
2022-07-10 00:55:56 +02:00
|
|
|
|
return n - 1;
|
2021-08-23 02:24:34 +02:00
|
|
|
|
}
|
2022-01-23 16:17:44 +01:00
|
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A set of characters representing all the lowercase letters of the latin alphabet (only in the ASCII table).
|
|
|
|
|
*/
|
2022-01-23 16:17:44 +01:00
|
|
|
|
public static final String PASSWORD_CHARSET_LATIN_LOWERCASE = "abcdefghijklmnopqrstuvwxyz";
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A set of characters representing all the uppercase letters of the latin alphabet (only in the ASCII table).
|
|
|
|
|
*/
|
2022-01-23 16:17:44 +01:00
|
|
|
|
public static final String PASSWORD_CHARSET_LATIN_UPPERCASE = PASSWORD_CHARSET_LATIN_LOWERCASE.toUpperCase();
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A set of characters representing all the number digits, from 0 to 9.
|
|
|
|
|
*/
|
2022-01-23 16:17:44 +01:00
|
|
|
|
public static final String PASSWORD_CHARSET_DIGIT = "0123456789";
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A set of characters representing some visible special characters in the ASCII table.
|
|
|
|
|
*/
|
2022-07-10 00:55:56 +02:00
|
|
|
|
public static final String PASSWORD_CHARSET_SPECIAL = "@#+*/-;:,.?!='()[]{}&";
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* A set of characters representing uppercase and lowercase latin alphabet letters and digits, excluding some that
|
2022-07-28 01:13:35 +02:00
|
|
|
|
* can be confusing to read (like {@code iIl1} or {@code oO0}).
|
|
|
|
|
*/
|
2023-06-20 00:15:46 +02:00
|
|
|
|
public static final String PASSWORD_CHARSET_NO_AMBIGUITY = "abcdefghkmnpqrstwxyzACDEFGHKLMNPQRSTWXYZ2345679";
|
2022-01-23 16:17:44 +01:00
|
|
|
|
|
2022-07-28 01:13:35 +02:00
|
|
|
|
/**
|
2023-06-20 00:15:46 +02:00
|
|
|
|
* Generate a random password of the provided length, using the characters listed in {@link #PASSWORD_CHARSET_NO_AMBIGUITY}.
|
2022-07-28 01:13:35 +02:00
|
|
|
|
* @param length the length of the generated password.
|
|
|
|
|
* @return the generated password.
|
|
|
|
|
*/
|
2022-01-23 16:17:44 +01:00
|
|
|
|
public static String randomPassword(int length) {
|
2023-06-20 00:15:46 +02:00
|
|
|
|
return randomPassword(length, PASSWORD_CHARSET_NO_AMBIGUITY);
|
2022-01-23 16:17:44 +01:00
|
|
|
|
}
|
2022-07-28 01:13:35 +02:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Generate a random password of the provided length, using the provided characters in a string.
|
|
|
|
|
* @param length the length of the generated password.
|
|
|
|
|
* @param charset the characters to use. It’s possible to use of the {@code PASSWORD_*} static strings in this class.
|
|
|
|
|
* @return the generated password.
|
|
|
|
|
*/
|
2022-01-23 16:17:44 +01:00
|
|
|
|
public static String randomPassword(int length, String charset) {
|
|
|
|
|
char[] pw = new char[length];
|
|
|
|
|
for (int i = 0; i < length; i++) {
|
|
|
|
|
pw[i] = stringChar(charset);
|
|
|
|
|
}
|
|
|
|
|
return String.valueOf(pw);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-02-16 20:07:51 +01:00
|
|
|
|
|
|
|
|
|
}
|