OptionSelectorWeighted { FeatureOption select() { final double randomValue = Math.random(); int idx = Arrays.binarySearch(wheel, randomValue); if (idx < 0) { idx = -idx - 1; } return values[idx]; } OptionSelectorWeighted(List<FeatureOption> options);   }
@Test public void testFairStrings() { final ArrayList<FeatureOption> itemList = Lists.newArrayList( FeatureOption.newBuilder().setKey("10%").setWeight(1_000).build(), FeatureOption.newBuilder().setKey("20%").setWeight(2_000).build(), FeatureOption.newBuilder().setKey("30%").setWeight(3_000).build(), FeatureOption.newBuilder().setKey("40%").setWeight(4_000).build() ); final OptionSelectorWeighted or = new OptionSelectorWeighted(itemList); final int[] resultFrequencies = new int[4]; final int nearestRoundTo = 1_000; final int runs = 10_000; IntStream.range(0, runs).forEach(i -> { final int fitIntoArray = (or.select().getWeight() / nearestRoundTo) - 1; resultFrequencies[fitIntoArray]++; }); final Set<Integer> nearestFrequencies = Sets.newHashSet(); final int nearestRoundUp = nearestRoundTo / 2; for (int resultFrequency : resultFrequencies) { final int nearestFrequency = (int) (nearestRoundTo * Math.floor((resultFrequency + nearestRoundUp) / nearestRoundTo)); nearestFrequencies.add(nearestFrequency); } assertTrue(nearestFrequencies.contains(1_000)); assertTrue(nearestFrequencies.contains(2_000)); assertTrue(nearestFrequencies.contains(3_000)); assertTrue(nearestFrequencies.contains(4_000)); }
@Test public void testBaseCases() { final ArrayList<FeatureOption> itemList1 = Lists.newArrayList( FeatureOption.newBuilder().setWeight(0).build(), FeatureOption.newBuilder().setWeight(10000).build() ); OptionSelectorWeighted or1 = new OptionSelectorWeighted(itemList1); IntStream.range(0, 10000).forEach(i -> assertTrue(10000 == or1.select().getWeight())); final ArrayList<FeatureOption> itemList2 = Lists.newArrayList( FeatureOption.newBuilder().setWeight(10000).build() ); OptionSelectorWeighted or2 = new OptionSelectorWeighted(itemList2); IntStream.range(0, 10000).forEach(i -> assertTrue(10000 == or2.select().getWeight())); }