Minestom/src/main/java/net/minestom/server/utils/WeightedRandom.java

52 lines
1.5 KiB
Java
Raw Normal View History

2020-05-18 21:11:59 +02:00
package net.minestom.server.utils;
2020-08-03 10:35:46 +02:00
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.doubles.DoubleList;
2020-05-18 21:11:59 +02:00
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Random;
/**
2020-10-31 05:09:30 +01:00
* Produces a random element from a given set, with weights applied.
2020-08-03 10:35:46 +02:00
*
2020-05-18 21:11:59 +02:00
* @param <E>
*/
public class WeightedRandom<E extends WeightedRandomItem> {
private final List<E> entries;
2020-08-03 10:35:46 +02:00
private final DoubleList weightSums;
2020-05-18 21:11:59 +02:00
private final double totalWeight;
public WeightedRandom(Collection<E> items) {
2020-08-03 10:35:46 +02:00
if (items.isEmpty())
2020-05-18 21:11:59 +02:00
throw new IllegalArgumentException("items must not be empty");
this.entries = new ArrayList<>(items);
2020-08-03 10:35:46 +02:00
this.weightSums = new DoubleArrayList(items.size());
2020-05-18 21:11:59 +02:00
double sum = 0.0;
2020-08-03 10:35:46 +02:00
for (E item : items) {
2020-05-18 21:11:59 +02:00
sum += item.getWeight();
weightSums.add(sum);
}
this.totalWeight = sum;
}
/**
2020-10-31 05:09:30 +01:00
* Gets a random element from this set.
2020-08-03 10:35:46 +02:00
*
2020-05-18 21:11:59 +02:00
* @param rng Random Number Generator to generate random numbers with
2020-08-07 09:14:50 +02:00
* @return a random element from this set
2020-05-18 21:11:59 +02:00
*/
public E get(Random rng) {
2020-08-03 10:35:46 +02:00
final double p = rng.nextDouble() * totalWeight;
2020-05-18 21:11:59 +02:00
for (int i = 0; i < entries.size(); i++) {
2020-08-19 01:24:51 +02:00
final double weightSum = weightSums.getDouble(i);
2020-08-03 10:35:46 +02:00
if (weightSum >= p) {
2020-05-18 21:11:59 +02:00
return entries.get(i);
}
}
2020-08-03 10:35:46 +02:00
return entries.get(entries.size() - 1);
2020-05-18 21:11:59 +02:00
}
}