package tc.oc.commons.core.random;
import java.util.HashMap;
import java.util.Map;
/**
* A random chooser that supports insertion and removal of choices.
*/
public class MutableWeightedRandomChooser<T, N extends Number> extends WeightedRandomChooser<T, N> {
private final Map<T, Option> options = new HashMap<>();
private double totalWeight = 0;
public MutableWeightedRandomChooser() {}
public MutableWeightedRandomChooser(Map<T, N> weights) {
addAll(weights);
}
@Override
public boolean isEmpty() {
return options.isEmpty();
}
@Override
public double totalWeight() {
return totalWeight;
}
@Override
protected T chooseInternal(double n) {
n *= totalWeight;
Option result = null;
for(Option option : options.values()) {
if(n < option.weight) {
result = option;
break;
} else {
n -= option.weight;
}
}
return result.element; // NPE should be impossible
}
public void add(T choice, N weight) {
final double doubleWeight = weight.doubleValue();
if(doubleWeight > 0) {
totalWeight += doubleWeight;
options.put(choice, new Option(choice, doubleWeight));
}
}
public void remove(T choice) {
final Option c = options.remove(choice);
if(c != null) {
totalWeight -= c.weight;
}
}
public void addAll(Map<T, N> weightedChoices) {
weightedChoices.forEach(this::add);
}
public void removeAll(Iterable<T> choices) {
choices.forEach(this::remove);
}
}