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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|