Gradle
implementation group: 'org.apache.commons', name: 'commons-math3', version: '3.6.1'
Maven
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>3.6.1</version>
</dependency>
Test
public class GachaUnitTest {
@BeforeAll
public static void setup() {
}
@Test
@DisplayName("가챠 확률 테스트")
public void should_GetRandomItem_When_Gacha() {
List<Pair<String, Double>> items = getItems();
List<String> itemsName = Lists.newArrayList();
for (int testCount = 0; testCount < 1000; testCount++) {
String itemName = getGachaItemName(items);
boolean containsItem = items
.stream()
.anyMatch(stringDoublePair -> stringDoublePair.getKey().equals(itemName));
assertThat(containsItem, is(true));
itemsName.add(itemName);
}
List<Map<String, List<String>>> sortedItemMap = itemsName
.stream()
.collect(Collectors.groupingBy(i -> i))
.entrySet()
.stream()
.sorted(Comparator.comparing(i -> i.getValue().size(), Comparator.reverseOrder()))
.map(entry -> {
Map<String, List<String>> map = Maps.newLinkedHashMap();
map.put(entry.getKey(), entry.getValue());
return map;
})
.toList();
for (Map<String, List<String>> itemMap : sortedItemMap) {
for (Map.Entry<String, List<String>> item : itemMap.entrySet()) {
String key = item.getKey();
List<String> values = item.getValue();
int size = values.size();
System.out.println(key + " - " + size);
}
}
}
private String getGachaItemName(List<Pair<String, Double>> items) {
return new EnumeratedDistribution<>(items).sample();
}
private List<Pair<String, Double>> getItems() {
Pair<String, Double> item1 = new Pair<>("item1", 1.5);
Pair<String, Double> item2 = new Pair<>("item2", 4.1);
Pair<String, Double> item3 = new Pair<>("item3", 3.7);
Pair<String, Double> item4 = new Pair<>("item4", 7.3);
Pair<String, Double> item5 = new Pair<>("item5", 2.0);
Pair<String, Double> item6 = new Pair<>("item6", 2.8);
Pair<String, Double> item7 = new Pair<>("item7", 6.9);
Pair<String, Double> item8 = new Pair<>("item8", 9.0);
Pair<String, Double> item9 = new Pair<>("item9", 8.8);
Pair<String, Double> item10 = new Pair<>("item10", 5.2);
return Lists.newArrayList(item1, item2, item3, item4, item5, item6, item7, item8, item9,
item10);
}
}
결과
item8 - 184
item9 - 155
item7 - 147
item4 - 124
item10 - 103
item2 - 84
item3 - 64
item6 - 62
item5 - 52
item1 - 25
확률이기 때문에 간헐적으로 item9가 더 많이 나올때도 있지만 item8과 그리 많이 차이나지 않는다.
사용법
- 라이브러리 추가
- List<Pair<T, 가중치 Double>> 형태로 된 데이터 준비 (보통은 T를 Entity로 많이 사용할 듯)
- new EnumeratedDistribution<>(items).sample();으로 랜덤 아이템 획득