diff --git a/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java b/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java index 40285c48e..bc6ca7988 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java +++ b/src/main/java/com/gmail/nossr50/datatypes/skills/subskills/acrobatics/Roll.java @@ -33,6 +33,7 @@ import org.bukkit.event.EventPriority; import org.bukkit.event.entity.EntityDamageEvent; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.VisibleForTesting; import java.util.Locale; @@ -198,7 +199,8 @@ public class Roll extends AcrobaticsSubSkill { * @param damage The amount of damage initially dealt by the event * @return the modified event damage if the ability was successful, the original event damage otherwise */ - private double rollCheck(Player player, McMMOPlayer mcMMOPlayer, double damage) { + @VisibleForTesting + public double rollCheck(Player player, McMMOPlayer mcMMOPlayer, double damage) { int skillLevel = mcMMOPlayer.getSkillLevel(getPrimarySkill()); @@ -246,8 +248,7 @@ public class Roll extends AcrobaticsSubSkill { private double gracefulRollCheck(Player player, McMMOPlayer mcMMOPlayer, double damage, int skillLevel) { double modifiedDamage = calculateModifiedRollDamage(damage, mcMMO.p.getAdvancedConfig().getRollDamageThreshold() * 2); - double gracefulOdds = ProbabilityUtil.getSubSkillProbability(subSkillType, player).getValue() * 2; - Probability gracefulProbability = Probability.ofPercent(gracefulOdds); + Probability gracefulProbability = getGracefulProbability(player); if (!isFatal(player, modifiedDamage) //TODO: Graceful isn't sending out an event @@ -271,6 +272,12 @@ public class Roll extends AcrobaticsSubSkill { return damage; } + @NotNull + public static Probability getGracefulProbability(Player player) { + double gracefulOdds = ProbabilityUtil.getSubSkillProbability(SubSkillType.ACROBATICS_ROLL, player).getValue() * 2; + return Probability.ofPercent(gracefulOdds); + } + /** * Check if the player is "farming" Acrobatics XP using * exploits in the game. diff --git a/src/test/java/com/gmail/nossr50/util/random/ProbabilityTest.java b/src/test/java/com/gmail/nossr50/util/random/ProbabilityTest.java index a454d5b20..d40182734 100644 --- a/src/test/java/com/gmail/nossr50/util/random/ProbabilityTest.java +++ b/src/test/java/com/gmail/nossr50/util/random/ProbabilityTest.java @@ -1,12 +1,9 @@ package com.gmail.nossr50.util.random; -import org.bukkit.entity.Player; -import org.junit.jupiter.api.BeforeEach; 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 org.mockito.Mockito; import java.util.stream.Stream; @@ -82,26 +79,17 @@ class ProbabilityTest { @ParameterizedTest @MethodSource("provideProbabilitiesForWithinExpectations") void testOddsExpectationsImplConstructor(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(probability.evaluate()) { - winCount++; - } - } - - double successPercent = (winCount / iterations) * 100; - System.out.println(successPercent + ", " + expectedWinPercent); - assertEquals(expectedWinPercent, successPercent, 0.01D); + assertExpectations(probability, expectedWinPercent); } @ParameterizedTest @MethodSource("provideOfPercentageProbabilitiesForWithinExpectations") void testOddsExpectationsOfPercent(Probability probability, double expectedWinPercent) { - // Probabilities are tested 2.0 x 10^9 with a margin of error of 0.01% - double iterations = 2.0e9; + assertExpectations(probability, expectedWinPercent); + } + + private static void assertExpectations(Probability probability, double expectedWinPercent) { + double iterations = 2.0e7; double winCount = 0; for (int i = 0; i < iterations; i++) { @@ -112,6 +100,6 @@ class ProbabilityTest { double successPercent = (winCount / iterations) * 100; System.out.println(successPercent + ", " + expectedWinPercent); - assertEquals(expectedWinPercent, successPercent, 0.01D); + assertEquals(expectedWinPercent, successPercent, 0.05D); } } diff --git a/src/test/java/com/gmail/nossr50/util/random/ProbabilityUtilTest.java b/src/test/java/com/gmail/nossr50/util/random/ProbabilityUtilTest.java index 9bb78fcf0..1a12913de 100644 --- a/src/test/java/com/gmail/nossr50/util/random/ProbabilityUtilTest.java +++ b/src/test/java/com/gmail/nossr50/util/random/ProbabilityUtilTest.java @@ -1,18 +1,22 @@ package com.gmail.nossr50.util.random; import com.gmail.nossr50.config.AdvancedConfig; +import com.gmail.nossr50.datatypes.player.McMMOPlayer; import com.gmail.nossr50.datatypes.skills.SubSkillType; import com.gmail.nossr50.mcMMO; +import org.bukkit.entity.Player; import org.junit.jupiter.api.BeforeEach; +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 org.mockito.Mockito; import java.util.stream.Stream; import static com.gmail.nossr50.datatypes.skills.SubSkillType.*; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; class ProbabilityUtilTest { @@ -25,13 +29,13 @@ class ProbabilityUtilTest { @BeforeEach public void setupMocks() throws NoSuchFieldException, IllegalAccessException { - this.mmoInstance = Mockito.mock(mcMMO.class); + this.mmoInstance = mock(mcMMO.class); mcMMO.class.getField("p").set(null, mmoInstance); - this.advancedConfig = Mockito.mock(AdvancedConfig.class); - Mockito.when(mmoInstance.getAdvancedConfig()).thenReturn(advancedConfig); - Mockito.when(advancedConfig.getImpactChance()).thenReturn(impactChance); - Mockito.when(advancedConfig.getGreaterImpactChance()).thenReturn(greaterImpactChance); - Mockito.when(advancedConfig.getFastFoodChance()).thenReturn(fastFoodChance); + this.advancedConfig = mock(AdvancedConfig.class); + when(mmoInstance.getAdvancedConfig()).thenReturn(advancedConfig); + when(advancedConfig.getImpactChance()).thenReturn(impactChance); + when(advancedConfig.getGreaterImpactChance()).thenReturn(greaterImpactChance); + when(advancedConfig.getFastFoodChance()).thenReturn(fastFoodChance); } private static Stream staticChanceSkills() { @@ -46,19 +50,21 @@ class ProbabilityUtilTest { @ParameterizedTest @MethodSource("staticChanceSkills") void testStaticChanceSkills(SubSkillType subSkillType, double expectedWinPercent) throws InvalidStaticChance { - // Probabilities are tested 2.0 x 10^9 with a margin of error of 0.01% - double iterations = 2.0e9; - double winCount = 0; - Probability staticRandomChance = ProbabilityUtil.getStaticRandomChance(subSkillType); + assertProbabilityExpectations(expectedWinPercent, staticRandomChance); + } + + private static void assertProbabilityExpectations(double expectedWinPercent, Probability probability) { + double iterations = 2.0e7; + double winCount = 0; for (int i = 0; i < iterations; i++) { - if(staticRandomChance.evaluate()) { + if(probability.evaluate()) { winCount++; } } double successPercent = (winCount / iterations) * 100; System.out.println(successPercent + ", " + expectedWinPercent); - assertEquals(expectedWinPercent, successPercent, 0.01D); + assertEquals(expectedWinPercent, successPercent, 0.05D); } -} \ No newline at end of file +}