MutableAbsoluteProbabilityChooser { public void setProbability(T outcome, @Nonnegative double probability) { Preconditions.checkArgument(!outcome.equals(defaultOutcome), "Attempted to set the probability of the default result %s", defaultOutcome); Preconditions.checkArgument(probability >= 0, "Attempted to set probability for outcome %s to invalid value %s (must be >= 0)", outcome, probability); if (probability == 0) { outcomesToProbability.remove(outcome); } else { double newTotalProbability = outcomesToProbability.values().stream().reduce(0.0, Double::sum) + probability - outcomesToProbability.getOrDefault(outcome, 0.0); Preconditions.checkState(newTotalProbability <= 1 + ROUNDING_TOLERANCE, "Sum of probabilities for all outcomes has exceeded 1"); outcomesToProbability.put(outcome, probability); } } MutableAbsoluteProbabilityChooser(T defaultOutcome); void setProbability(T outcome, @Nonnegative double probability); void removeOutcome(T outcome); void clear(); T choose(); static final double ROUNDING_TOLERANCE; }
@Test void whenOutcomeProbabilityDefined_thenReturnsExpectedValue() { chooser.setProbability(VALUE_1, 0.5); testInRange(0, 0.5, VALUE_1); testInRange(0.5, 1, DEFAULT); }
@Test void whenMultipleOutcomeProbabilitiesDefined_thenReturnsExpectedValue() { chooser.setProbability(VALUE_1, 0.5); chooser.setProbability(VALUE_2, 0.3); chooser.setProbability(VALUE_3, 0.2); testInRange(0, 0.5, VALUE_1); testInRange(0.5, 0.8, VALUE_2); testInRange(0.8, 1, VALUE_3); }
@Test void whenOutcomeProbabilityOverridden_thenUsesNewProbability() { chooser.setProbability(VALUE_1, 0.5); testInRange(0, 0.5, VALUE_1); testInRange(0.5, 1, DEFAULT); chooser.setProbability(VALUE_1, 0.7); testInRange(0, 0.7, VALUE_1); testInRange(0.7, 1, DEFAULT); }
@Test void whenDefaultResultProbabilitySet_thenThrowsException() { Assertions.assertThrows(IllegalArgumentException.class, () -> chooser.setProbability(DEFAULT, 0.5)); }
@Test void whenNegativeProbabilitySet_thenThrowsException() { Assertions.assertThrows(IllegalArgumentException.class, () -> chooser.setProbability(VALUE_1, -0.1)); }
@Test void whenSingleTooLargeProbabilitySet_thenThrowsException() { Assertions.assertThrows(IllegalStateException.class, () -> chooser.setProbability(VALUE_1, 1.1)); }
@Test void whenCumulativeProbabilitySetTooLarge_thenThrowsException() { chooser.setProbability(VALUE_1, 0.9); Assertions.assertThrows(IllegalStateException.class, () -> chooser.setProbability(VALUE_2, 0.2)); }