Unicopia/src/main/java/com/minelittlepony/unicopia/util/Weighted.java

81 lines
1.6 KiB
Java
Raw Normal View History

2020-05-28 18:30:23 +02:00
package com.minelittlepony.unicopia.util;
2019-02-07 10:46:59 +01:00
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.function.Consumer;
2021-08-04 15:38:03 +02:00
import org.jetbrains.annotations.NotNull;
2019-02-07 10:46:59 +01:00
import com.google.common.collect.Lists;
public class Weighted<T> {
private static final Random rand = new Random();
private float totalWeight = 0;
private final List<Entry> entries = Lists.newArrayList();
public static <T> Weighted<T> of(Consumer<Weighted<T>> constructor) {
Weighted<T> result = new Weighted<>();
constructor.accept(result);
return result;
}
2021-08-04 15:38:03 +02:00
public Weighted<T> put(int weight, @NotNull T value) {
2019-02-07 10:46:59 +01:00
entries.add(new Entry(weight, value));
totalWeight += weight;
recalculate();
return this;
}
private void recalculate() {
float rangeStart = 0;
for (Entry i : entries) {
i.min = rangeStart;
i.max = rangeStart + (i.weight/totalWeight);
rangeStart = i.max;
}
}
public Optional<T> get() {
if (entries.isEmpty()) {
return Optional.empty();
}
float random = rand.nextFloat();
return entries.stream()
.filter(i -> random >= i.min && random <= i.max)
.map(Entry::getResult)
.findFirst();
}
class Entry {
final float weight;
final T result;
float min;
float max;
Entry(int weight, T result) {
this.weight = weight;
this.result = result;
}
T getResult() {
return result;
}
}
}