From 11cf882830c8e9c47bce0ee712c6b5506c64df9c Mon Sep 17 00:00:00 2001 From: nossr50 Date: Sun, 18 Dec 2022 15:04:59 -0800 Subject: [PATCH] Probability factory should live within the interface --- .../commands/skills/FishingCommand.java | 3 +- .../skills/subskills/acrobatics/Roll.java | 5 +- .../nossr50/datatypes/treasure/Treasure.java | 6 +- .../nossr50/util/random/Probability.java | 57 +++++++++++++ .../util/random/ProbabilityFactory.java | 82 ------------------- .../nossr50/util/random/ProbabilityImpl.java | 2 +- .../gmail/nossr50/util/skills/SkillUtils.java | 6 +- ...lTest.java => ProbabilityFactoryTest.java} | 15 +++- .../nossr50/util/random/ProbabilityTest.java | 24 ++++++ 9 files changed, 102 insertions(+), 98 deletions(-) delete mode 100644 src/main/java/com/gmail/nossr50/util/random/ProbabilityFactory.java rename src/test/java/com/gmail/nossr50/util/random/{RandomChanceUtilTest.java => ProbabilityFactoryTest.java} (88%) create mode 100644 src/test/java/com/gmail/nossr50/util/random/ProbabilityTest.java diff --git a/src/main/java/com/gmail/nossr50/commands/skills/FishingCommand.java b/src/main/java/com/gmail/nossr50/commands/skills/FishingCommand.java index 3cf6c9117..95614ffe6 100644 --- a/src/main/java/com/gmail/nossr50/commands/skills/FishingCommand.java +++ b/src/main/java/com/gmail/nossr50/commands/skills/FishingCommand.java @@ -10,7 +10,6 @@ import com.gmail.nossr50.skills.fishing.FishingManager; import com.gmail.nossr50.util.Permissions; import com.gmail.nossr50.util.player.UserManager; import com.gmail.nossr50.util.random.Probability; -import com.gmail.nossr50.util.random.ProbabilityFactory; import com.gmail.nossr50.util.skills.RankUtils; import com.gmail.nossr50.util.skills.SkillUtils; import com.gmail.nossr50.util.text.StringUtils; @@ -82,7 +81,7 @@ public class FishingCommand extends SkillCommand { // FISHING_SHAKE if (canShake) { - Probability shakeProbability = ProbabilityFactory.ofPercentageValue(fishingManager.getShakeChance()); + Probability shakeProbability = Probability.ofPercentageValue(fishingManager.getShakeChance()); String[] shakeStrings = SkillUtils.getRNGDisplayValues(shakeProbability); shakeChance = shakeStrings[0]; shakeChanceLucky = shakeStrings[1]; 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 da8c057d2..eb165ebb0 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 @@ -136,9 +136,8 @@ public class Roll extends AcrobaticsSubSkill { /* * Graceful is double the odds of a normal roll */ - //TODO: Yeah I know, ...I'm tired I'll clean it up later Probability probability = getRollProbability(player); - Probability gracefulProbability = new ProbabilityImpl(probability.getValue() * 2); + Probability gracefulProbability = Probability.ofPercentageValue(probability.getValue() * 2); String[] gracefulRollStrings = SkillUtils.getRNGDisplayValues(gracefulProbability); gracefulRollChance = gracefulRollStrings[0]; gracefulRollChanceLucky = gracefulRollStrings[1]; @@ -249,7 +248,7 @@ public class Roll extends AcrobaticsSubSkill { double modifiedDamage = calculateModifiedRollDamage(damage, mcMMO.p.getAdvancedConfig().getRollDamageThreshold() * 2); double gracefulOdds = SkillUtils.getSubSkillProbability(subSkillType, player).getValue() * 2; - Probability gracefulProbability = new ProbabilityImpl(gracefulOdds); + Probability gracefulProbability = Probability.ofPercentageValue(gracefulOdds); if (!isFatal(player, modifiedDamage) //TODO: Graceful isn't sending out an event diff --git a/src/main/java/com/gmail/nossr50/datatypes/treasure/Treasure.java b/src/main/java/com/gmail/nossr50/datatypes/treasure/Treasure.java index 9a8a05521..16d4ac20a 100644 --- a/src/main/java/com/gmail/nossr50/datatypes/treasure/Treasure.java +++ b/src/main/java/com/gmail/nossr50/datatypes/treasure/Treasure.java @@ -1,8 +1,6 @@ package com.gmail.nossr50.datatypes.treasure; -import com.gmail.nossr50.config.Config; import com.gmail.nossr50.util.random.Probability; -import com.gmail.nossr50.util.random.ProbabilityFactory; import com.gmail.nossr50.util.random.ProbabilityImpl; import com.google.common.base.Objects; import org.bukkit.inventory.ItemStack; @@ -19,7 +17,7 @@ public abstract class Treasure { this.drop = drop; this.xp = xp; this.dropChance = dropChance; - this.dropProbability = new ProbabilityImpl(ProbabilityFactory.probabilityFromPercent(dropChance)); + this.dropProbability = Probability.ofPercentageValue(dropChance / 100); this.dropLevel = dropLevel; } @@ -49,7 +47,7 @@ public abstract class Treasure { public void setDropChance(double dropChance) { this.dropChance = dropChance; - this.dropProbability = new ProbabilityImpl(ProbabilityFactory.probabilityFromPercent(dropChance)); + this.dropProbability = Probability.ofPercentageValue(dropChance / 100); } public int getDropLevel() { diff --git a/src/main/java/com/gmail/nossr50/util/random/Probability.java b/src/main/java/com/gmail/nossr50/util/random/Probability.java index 0e939bc8b..d2b16fd5f 100644 --- a/src/main/java/com/gmail/nossr50/util/random/Probability.java +++ b/src/main/java/com/gmail/nossr50/util/random/Probability.java @@ -1,5 +1,13 @@ package com.gmail.nossr50.util.random; +import com.gmail.nossr50.datatypes.player.McMMOPlayer; +import com.gmail.nossr50.datatypes.skills.SubSkillType; +import com.gmail.nossr50.mcMMO; +import com.gmail.nossr50.util.player.UserManager; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + public interface Probability { /** * The value of this Probability @@ -11,4 +19,53 @@ public interface Probability { * @return the value of probability */ double getValue(); + + static @NotNull Probability ofSubSkill(@Nullable Player player, + @NotNull SubSkillType subSkillType, + @NotNull SkillProbabilityType skillProbabilityType) { + + switch (skillProbabilityType) { + case DYNAMIC_CONFIGURABLE: + double probabilityCeiling; + double xCeiling; + double xPos; + + if (player != null) { + McMMOPlayer mmoPlayer = UserManager.getPlayer(player); + if(mmoPlayer != null) + xPos = mmoPlayer.getSkillLevel(subSkillType.getParentSkill()); + else + xPos = 0; + } else { + xPos = 0; + } + + //Probability ceiling is configurable in this type + probabilityCeiling = mcMMO.p.getAdvancedConfig().getMaximumProbability(subSkillType); + //The xCeiling is configurable in this type + xCeiling = mcMMO.p.getAdvancedConfig().getMaxBonusLevel(subSkillType); + return new ProbabilityImpl(xPos, xCeiling, probabilityCeiling); + case STATIC_CONFIGURABLE: + try { + return ofPercentageValue(getStaticRandomChance(subSkillType)); + } catch (InvalidStaticChance invalidStaticChance) { + invalidStaticChance.printStackTrace(); + } + default: + throw new RuntimeException("No case in switch statement for Skill Probability Type!"); + } + } + + static @NotNull Probability ofPercentageValue(double percentageValue) { + return new ProbabilityImpl(percentageValue / 100); + } + + static double getStaticRandomChance(@NotNull SubSkillType subSkillType) throws InvalidStaticChance { + return switch (subSkillType) { + case AXES_ARMOR_IMPACT -> mcMMO.p.getAdvancedConfig().getImpactChance(); + case AXES_GREATER_IMPACT -> mcMMO.p.getAdvancedConfig().getGreaterImpactChance(); + case TAMING_FAST_FOOD_SERVICE -> mcMMO.p.getAdvancedConfig().getFastFoodChance(); + default -> throw new InvalidStaticChance(); + }; + } } diff --git a/src/main/java/com/gmail/nossr50/util/random/ProbabilityFactory.java b/src/main/java/com/gmail/nossr50/util/random/ProbabilityFactory.java deleted file mode 100644 index 443a035de..000000000 --- a/src/main/java/com/gmail/nossr50/util/random/ProbabilityFactory.java +++ /dev/null @@ -1,82 +0,0 @@ -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 com.gmail.nossr50.util.player.UserManager; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -public class ProbabilityFactory { - - public static @NotNull Probability ofPercentageValue(double percentageValue) { - return new ProbabilityImpl(probabilityFromPercent(percentageValue)); - } - - public static @NotNull Probability ofSubSkill(@Nullable Player player, - @NotNull SubSkillType subSkillType, - @NotNull SkillProbabilityType skillProbabilityType) { - - switch (skillProbabilityType) { - case DYNAMIC_CONFIGURABLE: - double probabilityCeiling; - double xCeiling; - double xPos; - - if (player != null) { - McMMOPlayer mmoPlayer = UserManager.getPlayer(player); - if(mmoPlayer != null) - xPos = mmoPlayer.getSkillLevel(subSkillType.getParentSkill()); - else - xPos = 0; - } else { - xPos = 0; - } - - //Probability ceiling is configurable in this type - probabilityCeiling = mcMMO.p.getAdvancedConfig().getMaximumProbability(subSkillType); - //The xCeiling is configurable in this type - xCeiling = mcMMO.p.getAdvancedConfig().getMaxBonusLevel(subSkillType); - return new ProbabilityImpl(xPos, xCeiling, probabilityCeiling); - case STATIC_CONFIGURABLE: - try { - return ofPercentageValue(getStaticRandomChance(subSkillType)); - } catch (InvalidStaticChance invalidStaticChance) { - invalidStaticChance.printStackTrace(); - } - default: - throw new RuntimeException("No case in switch statement for Skill Probability Type!"); - } - } - - /** - * Convert a probability from a percentage - * @param percentage value to convert - * @return 0 -> 1 inclusive representation of probability - */ - public static double probabilityFromPercent(double percentage) { - return percentage / 100; - } - - /** - * Grabs static activation rolls for Secondary Abilities - * - * @param subSkillType The secondary ability to grab properties of - * @return The static activation roll involved in the RNG calculation - * @throws InvalidStaticChance if the skill has no defined static chance this exception will be thrown and you should know you're a naughty boy - */ - private static double getStaticRandomChance(@NotNull SubSkillType subSkillType) throws InvalidStaticChance { - switch (subSkillType) { - case AXES_ARMOR_IMPACT: - return mcMMO.p.getAdvancedConfig().getImpactChance(); - case AXES_GREATER_IMPACT: - return mcMMO.p.getAdvancedConfig().getGreaterImpactChance(); - case TAMING_FAST_FOOD_SERVICE: - return mcMMO.p.getAdvancedConfig().getFastFoodChance(); - default: - throw new InvalidStaticChance(); - } - } -} diff --git a/src/main/java/com/gmail/nossr50/util/random/ProbabilityImpl.java b/src/main/java/com/gmail/nossr50/util/random/ProbabilityImpl.java index e5b4a5cc8..09b46fefc 100644 --- a/src/main/java/com/gmail/nossr50/util/random/ProbabilityImpl.java +++ b/src/main/java/com/gmail/nossr50/util/random/ProbabilityImpl.java @@ -12,7 +12,7 @@ public class ProbabilityImpl implements Probability { * * @param staticProbability the value to assign to this probability */ - public ProbabilityImpl(double staticProbability) throws ValueOutOfBoundsException { + ProbabilityImpl(double staticProbability) throws ValueOutOfBoundsException { if (staticProbability < 0) { throw new ValueOutOfBoundsException("Value should never be negative for Probability! This suggests a coding mistake, contact the devs!"); } diff --git a/src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java b/src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java index 1ef607b3a..9108e3e9c 100644 --- a/src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java +++ b/src/main/java/com/gmail/nossr50/util/skills/SkillUtils.java @@ -391,7 +391,7 @@ public final class SkillUtils { //Mutate probability if(resultModifier != 1.0D) - probability = ProbabilityFactory.ofPercentageValue(probability.getValue() * resultModifier); + probability = Probability.ofPercentageValue(probability.getValue() * resultModifier); //Luck boolean isLucky = Permissions.lucky(player, subSkillType.getParentSkill()); @@ -414,7 +414,7 @@ public final class SkillUtils { */ public static boolean isStaticSkillRNGSuccessful(@NotNull PrimarySkillType primarySkillType, @Nullable Player player, double probabilityPercentage) { //Grab a probability converted from a "percentage" value - Probability probability = ProbabilityFactory.ofPercentageValue(probabilityPercentage); + Probability probability = Probability.ofPercentageValue(probabilityPercentage); return isStaticSkillRNGSuccessful(primarySkillType, player, probability); } @@ -463,7 +463,7 @@ public final class SkillUtils { if(subSkillType == SubSkillType.TAMING_FAST_FOOD_SERVICE || subSkillType == SubSkillType.AXES_ARMOR_IMPACT || subSkillType == SubSkillType.AXES_GREATER_IMPACT) skillProbabilityType = SkillProbabilityType.STATIC_CONFIGURABLE; - return ProbabilityFactory.ofSubSkill(player, subSkillType, skillProbabilityType); + return Probability.ofSubSkill(player, subSkillType, skillProbabilityType); } public static @NotNull String[] getRNGDisplayValues(@NotNull Player player, @NotNull SubSkillType subSkill) { diff --git a/src/test/java/com/gmail/nossr50/util/random/RandomChanceUtilTest.java b/src/test/java/com/gmail/nossr50/util/random/ProbabilityFactoryTest.java similarity index 88% rename from src/test/java/com/gmail/nossr50/util/random/RandomChanceUtilTest.java rename to src/test/java/com/gmail/nossr50/util/random/ProbabilityFactoryTest.java index c08770bfa..e83395516 100644 --- a/src/test/java/com/gmail/nossr50/util/random/RandomChanceUtilTest.java +++ b/src/test/java/com/gmail/nossr50/util/random/ProbabilityFactoryTest.java @@ -10,7 +10,7 @@ import java.util.stream.Stream; import static com.gmail.nossr50.util.random.RandomChanceUtil.processProbability; import static org.junit.jupiter.api.Assertions.*; -class RandomChanceUtilTest { +class ProbabilityFactoryTest { private static Stream provideProbabilitiesForWithinExpectations() { return Stream.of( @@ -48,6 +48,15 @@ class RandomChanceUtilTest { } } + @Test + void testIsSuccessfulRollFailsOfPercentage() { + Probability probability = Probability.ofPercentageValue(100); + + for (int i = 0; i < 100000; i++) { + assertFalse(processProbability(probability)); + } + } + @ParameterizedTest @MethodSource("provideProbabilitiesForWithinExpectations") void testProcessProbabilityWithinExpectations(Probability probability, double expectedWinPercent) { @@ -67,10 +76,10 @@ class RandomChanceUtilTest { } @Test - void chanceOfSuccessPercentage() { + void ofPercentageValue() { } @Test - void testChanceOfSuccessPercentage() { + void ofSubSkill() { } } \ No newline at end of file diff --git a/src/test/java/com/gmail/nossr50/util/random/ProbabilityTest.java b/src/test/java/com/gmail/nossr50/util/random/ProbabilityTest.java new file mode 100644 index 000000000..da3b6ee56 --- /dev/null +++ b/src/test/java/com/gmail/nossr50/util/random/ProbabilityTest.java @@ -0,0 +1,24 @@ +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 ProbabilityTest { + + + + @Test + void chanceOfSuccessPercentage() { + } + + @Test + void testChanceOfSuccessPercentage() { + } +} \ No newline at end of file