/*
* This file is part of NucleusFramework for Bukkit, licensed under the MIT License (MIT).
*
* Copyright (c) JCThePants (www.jcwhatever.com)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package com.jcwhatever.nucleus.utils;
import com.jcwhatever.nucleus.providers.math.FastMath;
import java.util.List;
import java.util.concurrent.ThreadLocalRandom;
/**
* Randomizing utilities.
*/
public final class Rand {
private Rand() {}
static final String SAFE_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
static final String UNSAFE_CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" +
"01234567890`~!@#$%^&*()_+-=";
/**
* Get a random item from a list.
*
* @param items The list to get a random item from.
*
* @param <T> The list generic type.
*/
public static <T> T get(List<T> items) {
PreCon.notNull(items);
PreCon.isValid(items.size() > 0);
if (items.size() == 1)
return items.get(0);
return items.get(getInt(items.size()));
}
/**
* Get a random item from an array of items.
*
* @param items The array of items.
*
* @param <T> The array item type.
*/
public static <T> T get(T[] items) {
PreCon.notNull(items);
PreCon.isValid(items.length > 0);
if (items.length == 1)
return items[0];
return items[getInt(items.length)];
}
/**
* Remove a random item from a list.
*
* @param items The list to remove a random item from.
*
* @param <T> The list generic type.
*/
public static <T> T remove(List<T> items) {
PreCon.notNull(items);
PreCon.isValid(items.size() > 0);
if (items.size() == 1)
return items.remove(0);
return items.remove(getInt(items.size()));
}
/**
* Get a random integer equal to or between the specified minimum and maximum
* amount.
*
* @param min The minimum result.
* @param max The maximum result.
*/
public static int getInt(int min, int max) {
int range = max - min + 1;
int i = Math.abs(getInt()) % range;
return min + i;
}
/**
* Get a random integer from 0 up to the specified maximum number.
*
* @param max The maximum result.
*/
public static int getInt(int max) {
if (max <= 1)
return 0;
return getInt() % max;
}
/**
* Get a random integer.
*/
public static int getInt() {
long l = FastMath.randomLong();
return Math.abs((int) ((l >> 32) ^ ((int) l)));
}
/**
* Get a random double equal to or between the specified minimum and maximum
* amount.
*
* @param min The minimum result.
* @param max The maximum result.
*/
public static double getDouble(double min, double max) {
return ThreadLocalRandom.current().nextDouble(min, max);
}
/**
* Get a random double from 0 up to the specified maximum number.
*
* @param max The maximum result.
*/
public static double getDouble(double max) {
return ThreadLocalRandom.current().nextDouble(0, max);
}
/**
* Get a random double.
*/
public static double getDouble() {
return ThreadLocalRandom.current().nextDouble();
}
/**
* Get a random gaussian double with an average of 0 and a
* deviation of 1.
*/
public static double getGaussian() {
return ThreadLocalRandom.current().nextGaussian();
}
/**
* Get a random gaussian double.
*
* @param average The average.
* @param deviation The deviation from average.
*/
public static double getGaussian(double average, double deviation) {
return ThreadLocalRandom.current().nextGaussian() * deviation + average;
}
/**
* Get a random alphabet string of the specified length.
*
* <p>Returned string should be safe to use in contexts such as node names in
* config files.</p>
*
* @param length The length of the returned string.
*/
public static String getSafeString(int length) {
PreCon.positiveNumber(length);
return getString(length, SAFE_CHARACTERS);
}
/**
* Get a random string of characters, including symbols, of the specified length.
*
* <p>May not be safe to use where the usage context does not allow for symbols in
* the string.</p>
*
* @param length The length of the returned string.
*/
public static String getUnsafeString(int length) {
PreCon.positiveNumber(length);
return getString(length, UNSAFE_CHARACTERS);
}
/**
* Get a random string of characters using the specified character pool.
*
* @param length The length of the returned string.
* @param characterPool The pool of characters to construct a string with.
*/
public static String getString(int length, String characterPool) {
PreCon.positiveNumber(length);
PreCon.notNullOrEmpty(characterPool);
StringBuilder sb = new StringBuilder(length);
for (int i=0; i < length; i++) {
int index = getInt(0, characterPool.length() - 1);
sb.append(characterPool.charAt(index));
}
return sb.toString();
}
/**
* Get a random boolean using the specified chance.
*
* <p>The maximum effective chance is 100.</p>
*
* @param chance The chance of getting a result of true.
*/
public static boolean chance(int chance) {
return chance > getInt(100);
}
/**
* Get a random boolean using the specified chance.
*
* <p>The maximum effective chance is 1.0.</p>
*
* @param chance The chance of getting a result of true.
*/
public static boolean chance(double chance) {
return chance > getDouble(1);
}
/**
* Roll dice of the specified number of sides.
*
* <p>Maximum effective sides is 100.</p>
*
* @param sides The number of sides the dice has.
*/
public static boolean rollDice(int sides) {
PreCon.positiveNumber(sides);
if (sides == 0 || sides > 100)
return false;
if (sides == 1)
return true;
int chance = 100 / sides;
return chance(chance);
}
}