Add some unit tests for new RNG dice rolls

This commit is contained in:
nossr50 2022-12-11 15:38:04 -08:00
parent b077d9e0fb
commit 05c86f1125
4 changed files with 83 additions and 23 deletions

View File

@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>com.gmail.nossr50.mcMMO</groupId> <groupId>com.gmail.nossr50.mcMMO</groupId>
<artifactId>mcMMO</artifactId> <artifactId>mcMMO</artifactId>
<version>2.1.218</version> <version>2.2.000-BETA-SNAPSHOT</version>
<name>mcMMO</name> <name>mcMMO</name>
<url>https://github.com/mcMMO-Dev/mcMMO</url> <url>https://github.com/mcMMO-Dev/mcMMO</url>
<scm> <scm>

View File

@ -4,12 +4,11 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType;
import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.skills.SkillUtils;
import org.bukkit.entity.Player; import org.bukkit.entity.Player;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.VisibleForTesting;
import java.text.DecimalFormat; import java.text.DecimalFormat;
import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.ThreadLocalRandom;
//TODO: Normalize chance values
//TODO: Update calls to this class and its members
public class RandomChanceUtil { public class RandomChanceUtil {
public static final @NotNull DecimalFormat percent = new DecimalFormat("##0.00%"); public static final @NotNull DecimalFormat percent = new DecimalFormat("##0.00%");
public static final double LUCKY_MODIFIER = 1.333D; public static final double LUCKY_MODIFIER = 1.333D;
@ -43,8 +42,9 @@ public class RandomChanceUtil {
* @param probabilityValue probability value * @param probabilityValue probability value
* @return true for succeeding, false for failing * @return true for succeeding, false for failing
*/ */
private static boolean isSuccessfulRoll(double probabilityValue) { @VisibleForTesting
return probabilityValue >= ThreadLocalRandom.current().nextDouble(1.0D); static boolean isSuccessfulRoll(double probabilityValue) {
return probabilityValue >= ThreadLocalRandom.current().nextDouble(100D);
} }
/** /**
@ -52,7 +52,7 @@ public class RandomChanceUtil {
* *
* @param player target player * @param player target player
* @param subSkillType target subskill * @param subSkillType target subskill
* @param isLucky whether or not to apply luck modifiers * @param isLucky whether to apply luck modifiers
* *
* @return "percentage" representation of success * @return "percentage" representation of success
*/ */

View File

@ -85,25 +85,9 @@
//// } //// }
//// } //// }
// //
// @Test
// public void testFailsAboutExpected() {
// System.out.println(testASCIIHeader);
// System.out.println("Test - Player with 800 skill should fail about 20% of the time (100,000 iterations)");
// double ratioDivisor = 1000; //1000 because we run the test 100,000 times
// double expectedFailRate = 100.0D - 2.15D;
// //
// double win = 0, loss = 0;
// for(int x = 0; x < 100000; x++) {
// if(RandomChanceUtil.checkRandomChanceExecutionSuccess(normalPlayer, SubSkillType.MINING_MOTHER_LODE, true)) {
// win++;
// } else {
// loss++;
// }
// }
// //
// double lossRatio = (loss / ratioDivisor); //
// Assert.assertEquals(lossRatio, expectedFailRate, 0.01D);
// }
// //
// private double getSuccessChance(@NotNull McMMOPlayer mmoPlayer) { // private double getSuccessChance(@NotNull McMMOPlayer mmoPlayer) {
// RandomChanceSkill randomChanceSkill = new RandomChanceSkill(mmoPlayer.getPlayer(), subSkillType, true); // RandomChanceSkill randomChanceSkill = new RandomChanceSkill(mmoPlayer.getPlayer(), subSkillType, true);

View File

@ -0,0 +1,76 @@
package com.gmail.nossr50.util.random;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import java.util.stream.Stream;
import static com.gmail.nossr50.util.random.RandomChanceUtil.processProbability;
import static org.junit.jupiter.api.Assertions.*;
class RandomChanceUtilTest {
private static Stream<Arguments> provideProbabilitiesForWithinExpectations() {
return Stream.of(
// static probability, % of time for success
Arguments.of(new ProbabilityImpl(5), 5),
Arguments.of(new ProbabilityImpl(10), 10),
Arguments.of(new ProbabilityImpl(15), 15),
Arguments.of(new ProbabilityImpl(20), 20),
Arguments.of(new ProbabilityImpl(25), 25),
Arguments.of(new ProbabilityImpl(50), 50),
Arguments.of(new ProbabilityImpl(75), 75),
Arguments.of(new ProbabilityImpl(90), 90),
Arguments.of(new ProbabilityImpl(99.9), 99.9),
Arguments.of(new ProbabilityImpl(0.05), 0.05),
Arguments.of(new ProbabilityImpl(0.1), 0.1),
Arguments.of(new ProbabilityImpl(500), 100),
Arguments.of(new ProbabilityImpl(1000), 100)
);
}
@Test
void testIsSuccessfulRollSucceeds() {
Probability probability = new ProbabilityImpl(100);
for (int i = 0; i < 100000; i++) {
assertTrue(processProbability(probability));
}
}
@Test
void testIsSuccessfulRollFails() {
Probability probability = new ProbabilityImpl(0);
for (int i = 0; i < 100000; i++) {
assertFalse(processProbability(probability));
}
}
@ParameterizedTest
@MethodSource("provideProbabilitiesForWithinExpectations")
void testProcessProbabilityWithinExpectations(Probability probability, double expectedWinPercent) {
// Probabilities are tested 200,000,000 times with a margin of error of 0.01%
int iterations = 200000000;
double winCount = 0;
for (int i = 0; i < iterations; i++) {
if(processProbability(probability)) {
winCount++;
}
}
double successPercent = (winCount / iterations) * 100;
System.out.println(successPercent + ", " + expectedWinPercent);
assertEquals(expectedWinPercent, successPercent, 0.01D);
}
@Test
void chanceOfSuccessPercentage() {
}
@Test
void testChanceOfSuccessPercentage() {
}
}