mirror of
https://github.com/mcMMO-Dev/mcMMO.git
synced 2024-11-24 14:16:45 +01:00
Probability factory should live within the interface
This commit is contained in:
parent
05c86f1125
commit
11cf882830
@ -10,7 +10,6 @@ import com.gmail.nossr50.skills.fishing.FishingManager;
|
|||||||
import com.gmail.nossr50.util.Permissions;
|
import com.gmail.nossr50.util.Permissions;
|
||||||
import com.gmail.nossr50.util.player.UserManager;
|
import com.gmail.nossr50.util.player.UserManager;
|
||||||
import com.gmail.nossr50.util.random.Probability;
|
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.RankUtils;
|
||||||
import com.gmail.nossr50.util.skills.SkillUtils;
|
import com.gmail.nossr50.util.skills.SkillUtils;
|
||||||
import com.gmail.nossr50.util.text.StringUtils;
|
import com.gmail.nossr50.util.text.StringUtils;
|
||||||
@ -82,7 +81,7 @@ public class FishingCommand extends SkillCommand {
|
|||||||
|
|
||||||
// FISHING_SHAKE
|
// FISHING_SHAKE
|
||||||
if (canShake) {
|
if (canShake) {
|
||||||
Probability shakeProbability = ProbabilityFactory.ofPercentageValue(fishingManager.getShakeChance());
|
Probability shakeProbability = Probability.ofPercentageValue(fishingManager.getShakeChance());
|
||||||
String[] shakeStrings = SkillUtils.getRNGDisplayValues(shakeProbability);
|
String[] shakeStrings = SkillUtils.getRNGDisplayValues(shakeProbability);
|
||||||
shakeChance = shakeStrings[0];
|
shakeChance = shakeStrings[0];
|
||||||
shakeChanceLucky = shakeStrings[1];
|
shakeChanceLucky = shakeStrings[1];
|
||||||
|
@ -136,9 +136,8 @@ public class Roll extends AcrobaticsSubSkill {
|
|||||||
/*
|
/*
|
||||||
* Graceful is double the odds of a normal roll
|
* 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 probability = getRollProbability(player);
|
||||||
Probability gracefulProbability = new ProbabilityImpl(probability.getValue() * 2);
|
Probability gracefulProbability = Probability.ofPercentageValue(probability.getValue() * 2);
|
||||||
String[] gracefulRollStrings = SkillUtils.getRNGDisplayValues(gracefulProbability);
|
String[] gracefulRollStrings = SkillUtils.getRNGDisplayValues(gracefulProbability);
|
||||||
gracefulRollChance = gracefulRollStrings[0];
|
gracefulRollChance = gracefulRollStrings[0];
|
||||||
gracefulRollChanceLucky = gracefulRollStrings[1];
|
gracefulRollChanceLucky = gracefulRollStrings[1];
|
||||||
@ -249,7 +248,7 @@ public class Roll extends AcrobaticsSubSkill {
|
|||||||
double modifiedDamage = calculateModifiedRollDamage(damage, mcMMO.p.getAdvancedConfig().getRollDamageThreshold() * 2);
|
double modifiedDamage = calculateModifiedRollDamage(damage, mcMMO.p.getAdvancedConfig().getRollDamageThreshold() * 2);
|
||||||
|
|
||||||
double gracefulOdds = SkillUtils.getSubSkillProbability(subSkillType, player).getValue() * 2;
|
double gracefulOdds = SkillUtils.getSubSkillProbability(subSkillType, player).getValue() * 2;
|
||||||
Probability gracefulProbability = new ProbabilityImpl(gracefulOdds);
|
Probability gracefulProbability = Probability.ofPercentageValue(gracefulOdds);
|
||||||
|
|
||||||
if (!isFatal(player, modifiedDamage)
|
if (!isFatal(player, modifiedDamage)
|
||||||
//TODO: Graceful isn't sending out an event
|
//TODO: Graceful isn't sending out an event
|
||||||
|
@ -1,8 +1,6 @@
|
|||||||
package com.gmail.nossr50.datatypes.treasure;
|
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.Probability;
|
||||||
import com.gmail.nossr50.util.random.ProbabilityFactory;
|
|
||||||
import com.gmail.nossr50.util.random.ProbabilityImpl;
|
import com.gmail.nossr50.util.random.ProbabilityImpl;
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import org.bukkit.inventory.ItemStack;
|
import org.bukkit.inventory.ItemStack;
|
||||||
@ -19,7 +17,7 @@ public abstract class Treasure {
|
|||||||
this.drop = drop;
|
this.drop = drop;
|
||||||
this.xp = xp;
|
this.xp = xp;
|
||||||
this.dropChance = dropChance;
|
this.dropChance = dropChance;
|
||||||
this.dropProbability = new ProbabilityImpl(ProbabilityFactory.probabilityFromPercent(dropChance));
|
this.dropProbability = Probability.ofPercentageValue(dropChance / 100);
|
||||||
this.dropLevel = dropLevel;
|
this.dropLevel = dropLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,7 +47,7 @@ public abstract class Treasure {
|
|||||||
|
|
||||||
public void setDropChance(double dropChance) {
|
public void setDropChance(double dropChance) {
|
||||||
this.dropChance = dropChance;
|
this.dropChance = dropChance;
|
||||||
this.dropProbability = new ProbabilityImpl(ProbabilityFactory.probabilityFromPercent(dropChance));
|
this.dropProbability = Probability.ofPercentageValue(dropChance / 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getDropLevel() {
|
public int getDropLevel() {
|
||||||
|
@ -1,5 +1,13 @@
|
|||||||
package com.gmail.nossr50.util.random;
|
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 {
|
public interface Probability {
|
||||||
/**
|
/**
|
||||||
* The value of this Probability
|
* The value of this Probability
|
||||||
@ -11,4 +19,53 @@ public interface Probability {
|
|||||||
* @return the value of probability
|
* @return the value of probability
|
||||||
*/
|
*/
|
||||||
double getValue();
|
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();
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -12,7 +12,7 @@ public class ProbabilityImpl implements Probability {
|
|||||||
*
|
*
|
||||||
* @param staticProbability the value to assign to this probability
|
* @param staticProbability the value to assign to this probability
|
||||||
*/
|
*/
|
||||||
public ProbabilityImpl(double staticProbability) throws ValueOutOfBoundsException {
|
ProbabilityImpl(double staticProbability) throws ValueOutOfBoundsException {
|
||||||
if (staticProbability < 0) {
|
if (staticProbability < 0) {
|
||||||
throw new ValueOutOfBoundsException("Value should never be negative for Probability! This suggests a coding mistake, contact the devs!");
|
throw new ValueOutOfBoundsException("Value should never be negative for Probability! This suggests a coding mistake, contact the devs!");
|
||||||
}
|
}
|
||||||
|
@ -391,7 +391,7 @@ public final class SkillUtils {
|
|||||||
|
|
||||||
//Mutate probability
|
//Mutate probability
|
||||||
if(resultModifier != 1.0D)
|
if(resultModifier != 1.0D)
|
||||||
probability = ProbabilityFactory.ofPercentageValue(probability.getValue() * resultModifier);
|
probability = Probability.ofPercentageValue(probability.getValue() * resultModifier);
|
||||||
|
|
||||||
//Luck
|
//Luck
|
||||||
boolean isLucky = Permissions.lucky(player, subSkillType.getParentSkill());
|
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) {
|
public static boolean isStaticSkillRNGSuccessful(@NotNull PrimarySkillType primarySkillType, @Nullable Player player, double probabilityPercentage) {
|
||||||
//Grab a probability converted from a "percentage" value
|
//Grab a probability converted from a "percentage" value
|
||||||
Probability probability = ProbabilityFactory.ofPercentageValue(probabilityPercentage);
|
Probability probability = Probability.ofPercentageValue(probabilityPercentage);
|
||||||
|
|
||||||
return isStaticSkillRNGSuccessful(primarySkillType, player, probability);
|
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)
|
if(subSkillType == SubSkillType.TAMING_FAST_FOOD_SERVICE || subSkillType == SubSkillType.AXES_ARMOR_IMPACT || subSkillType == SubSkillType.AXES_GREATER_IMPACT)
|
||||||
skillProbabilityType = SkillProbabilityType.STATIC_CONFIGURABLE;
|
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) {
|
public static @NotNull String[] getRNGDisplayValues(@NotNull Player player, @NotNull SubSkillType subSkill) {
|
||||||
|
@ -10,7 +10,7 @@ import java.util.stream.Stream;
|
|||||||
import static com.gmail.nossr50.util.random.RandomChanceUtil.processProbability;
|
import static com.gmail.nossr50.util.random.RandomChanceUtil.processProbability;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
class RandomChanceUtilTest {
|
class ProbabilityFactoryTest {
|
||||||
|
|
||||||
private static Stream<Arguments> provideProbabilitiesForWithinExpectations() {
|
private static Stream<Arguments> provideProbabilitiesForWithinExpectations() {
|
||||||
return Stream.of(
|
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
|
@ParameterizedTest
|
||||||
@MethodSource("provideProbabilitiesForWithinExpectations")
|
@MethodSource("provideProbabilitiesForWithinExpectations")
|
||||||
void testProcessProbabilityWithinExpectations(Probability probability, double expectedWinPercent) {
|
void testProcessProbabilityWithinExpectations(Probability probability, double expectedWinPercent) {
|
||||||
@ -67,10 +76,10 @@ class RandomChanceUtilTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void chanceOfSuccessPercentage() {
|
void ofPercentageValue() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testChanceOfSuccessPercentage() {
|
void ofSubSkill() {
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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() {
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user