From 05c86f1125d157894a3e899022e772d9f824d07b Mon Sep 17 00:00:00 2001 From: nossr50 Date: Sun, 11 Dec 2022 15:38:04 -0800 Subject: [PATCH] Add some unit tests for new RNG dice rolls --- pom.xml | 2 +- .../nossr50/util/random/RandomChanceUtil.java | 10 +-- .../nossr50/util/random/RandomChanceTest.java | 18 +---- .../util/random/RandomChanceUtilTest.java | 76 +++++++++++++++++++ 4 files changed, 83 insertions(+), 23 deletions(-) create mode 100644 src/test/java/com/gmail/nossr50/util/random/RandomChanceUtilTest.java diff --git a/pom.xml b/pom.xml index 1b70bbae7..7a832016e 100755 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ 4.0.0 com.gmail.nossr50.mcMMO mcMMO - 2.1.218 + 2.2.000-BETA-SNAPSHOT mcMMO https://github.com/mcMMO-Dev/mcMMO diff --git a/src/main/java/com/gmail/nossr50/util/random/RandomChanceUtil.java b/src/main/java/com/gmail/nossr50/util/random/RandomChanceUtil.java index 65b6b1980..f47e4e8ac 100644 --- a/src/main/java/com/gmail/nossr50/util/random/RandomChanceUtil.java +++ b/src/main/java/com/gmail/nossr50/util/random/RandomChanceUtil.java @@ -4,12 +4,11 @@ import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.util.skills.SkillUtils; import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.VisibleForTesting; import java.text.DecimalFormat; import java.util.concurrent.ThreadLocalRandom; -//TODO: Normalize chance values -//TODO: Update calls to this class and its members public class RandomChanceUtil { public static final @NotNull DecimalFormat percent = new DecimalFormat("##0.00%"); public static final double LUCKY_MODIFIER = 1.333D; @@ -43,8 +42,9 @@ public class RandomChanceUtil { * @param probabilityValue probability value * @return true for succeeding, false for failing */ - private static boolean isSuccessfulRoll(double probabilityValue) { - return probabilityValue >= ThreadLocalRandom.current().nextDouble(1.0D); + @VisibleForTesting + static boolean isSuccessfulRoll(double probabilityValue) { + return probabilityValue >= ThreadLocalRandom.current().nextDouble(100D); } /** @@ -52,7 +52,7 @@ public class RandomChanceUtil { * * @param player target player * @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 */ diff --git a/src/test/java/com/gmail/nossr50/util/random/RandomChanceTest.java b/src/test/java/com/gmail/nossr50/util/random/RandomChanceTest.java index d417635fc..982acdc6b 100644 --- a/src/test/java/com/gmail/nossr50/util/random/RandomChanceTest.java +++ b/src/test/java/com/gmail/nossr50/util/random/RandomChanceTest.java @@ -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) { // RandomChanceSkill randomChanceSkill = new RandomChanceSkill(mmoPlayer.getPlayer(), subSkillType, true); diff --git a/src/test/java/com/gmail/nossr50/util/random/RandomChanceUtilTest.java b/src/test/java/com/gmail/nossr50/util/random/RandomChanceUtilTest.java new file mode 100644 index 000000000..c08770bfa --- /dev/null +++ b/src/test/java/com/gmail/nossr50/util/random/RandomChanceUtilTest.java @@ -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 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() { + } +} \ No newline at end of file