summaryrefslogtreecommitdiff
path: root/base/src/main/java/bjc/utils/misc
diff options
context:
space:
mode:
authorbjculkin <bjculkin@BECK-GT5TRW1.wvu-ad.wvu.edu>2018-04-25 15:29:18 -0400
committerbjculkin <bjculkin@BECK-GT5TRW1.wvu-ad.wvu.edu>2018-04-25 15:29:18 -0400
commitd7bae4d2145d8337570fec03974272d49ba5269d (patch)
tree2f44ef7a13315990836344a4616ceaeaa1486916 /base/src/main/java/bjc/utils/misc
parent37e55c679f9a9ca1d57d061eac5e5deef0ef0a90 (diff)
Add some new classes
Import some new classes from an old project
Diffstat (limited to 'base/src/main/java/bjc/utils/misc')
-rw-r--r--base/src/main/java/bjc/utils/misc/Direction.java221
-rw-r--r--base/src/main/java/bjc/utils/misc/PropertyDB.java155
-rw-r--r--base/src/main/java/bjc/utils/misc/RelativeDirection.java123
3 files changed, 499 insertions, 0 deletions
diff --git a/base/src/main/java/bjc/utils/misc/Direction.java b/base/src/main/java/bjc/utils/misc/Direction.java
new file mode 100644
index 0000000..4833f14
--- /dev/null
+++ b/base/src/main/java/bjc/utils/misc/Direction.java
@@ -0,0 +1,221 @@
+package bjc.utils.misc;
+
+import java.util.Random;
+import java.util.function.Consumer;
+
+import bjc.utils.exceptions.InvalidDirectionException;
+import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IList;
+
+import org.apache.commons.lang3.text.WordUtils;
+
+/**
+ * A set of cardinal directions
+ *
+ * The particular axis assigned to the coordinates are based off of x being
+ * the bottom left axis on a conventional 3D plot
+ *
+ * @author ben
+ *
+ */
+public enum Direction {
+ /**
+ * Negative z-axis
+ */
+ DOWN,
+ /**
+ * Positive y-axis
+ */
+ EAST,
+ /**
+ * Positive x-axis
+ */
+ NORTH,
+ /**
+ * Negative x-axis
+ */
+ SOUTH,
+ /**
+ * Positive z-axis
+ */
+ UP,
+ /**
+ * Negative y-axis
+ */
+ WEST;
+
+ /**
+ * The source of randomness for picking random directions
+ */
+ private static final Random RNG = new Random();
+
+ /**
+ * Get a list of all the cardinal directions
+ *
+ * @return A list of all the cardinal directions
+ */
+ public static IList<Direction> cardinals() {
+ return new FunctionalList<>(NORTH, SOUTH, EAST, WEST);
+ }
+
+ /**
+ * Perform the specified action once with each of the cardinal
+ * directions
+ *
+ * @param act
+ * The action to perform for each cardinal direction
+ */
+ public static void forCardinalDirections(Consumer<Direction> act) {
+ cardinals().forEach(act);
+ }
+
+ /**
+ * Perform a specified action for a random number of cardinals.
+ *
+ * @param nCardinals
+ * The number of cardinal directions to act on. Must be
+ * greater than 0 and less then 5
+ * @param act
+ * The action to perform for each of the cardinals
+ */
+ public static void forRandomCardinals(int nCardinals,
+ Consumer<Direction> act) {
+ if (nCardinals <= 0 || nCardinals > 4) {
+ throw new IllegalArgumentException(
+ "Tried to do things with incorrect number of cardinal directions. Tried with "
+ + nCardinals);
+ }
+
+ IList<Direction> cards = cardinals();
+
+ for (int i = 0; i <= 4 - nCardinals; i++) {
+ Direction rDir = cards.randItem(RNG::nextInt);
+
+ cards.removeMatching(rDir);
+ }
+
+ cards.forEach(act);
+ }
+
+ /**
+ * Create a value of the enumeration from a string
+ *
+ * @param value
+ * The string to turn into a value
+ * @return The direction corresponding to the given value
+ */
+ public static Direction properValueOf(String value) {
+ return valueOf(value.toUpperCase());
+ }
+
+ /**
+ * Test if this direction is a cardinal direction
+ *
+ * @return If the direction is cardinal or not
+ */
+ public boolean isCardinal() {
+ switch (this) {
+ case EAST:
+ case NORTH:
+ case SOUTH:
+ case WEST:
+ return true;
+ case DOWN:
+ case UP:
+ return false;
+ default:
+ throw new InvalidDirectionException(
+ "WAT. Somehow ended up with an invalid direction "
+ + this);
+ }
+ }
+
+ /**
+ * Get the direction that opposes the current one
+ *
+ * @return The direction that is in the opposite direction of the
+ * current one
+ */
+ public Direction opposing() {
+ switch (this) {
+ case NORTH:
+ return SOUTH;
+ case EAST:
+ return WEST;
+ case SOUTH:
+ return NORTH;
+ case WEST:
+ return WEST;
+ case UP:
+ return DOWN;
+ case DOWN:
+ return UP;
+ default:
+ throw new IllegalStateException(
+ "Enumeration got into a invalid state. WAT");
+ }
+ }
+
+ /**
+ * Get the direction that is clockwise on the compass from this one.
+ *
+ * Only works on cardinals.
+ *
+ * @return The cardinal clockwise from this one
+ */
+ public Direction rotateClockwise() {
+ switch (this) {
+ case NORTH:
+ return EAST;
+ case EAST:
+ return SOUTH;
+ case SOUTH:
+ return WEST;
+ case WEST:
+ return NORTH;
+ case UP:
+ case DOWN:
+ default:
+ throw new InvalidDirectionException(
+ "Can't rotate non-cardinal direction clockwise: "
+ + this);
+
+ }
+ }
+
+ /**
+ * Get the direction that is counter-clockwise on the compass from this
+ * one.
+ *
+ * Only works on cardinals.
+ *
+ * @return The cardinal counter-clockwise from this one
+ */
+ public Direction rotateCounterClockwise() {
+ switch (this) {
+ case NORTH:
+ return WEST;
+ case EAST:
+ return NORTH;
+ case SOUTH:
+ return EAST;
+ case WEST:
+ return SOUTH;
+ case UP:
+ case DOWN:
+ default:
+ throw new InvalidDirectionException(
+ "Can't rotate non-cardinal direction counterclockwise: "
+ + this);
+
+ }
+ }
+
+ @Override
+ public String toString() {
+ /*
+ * Make sure the word is properly capitalized for english
+ */
+ return WordUtils.capitalize(super.toString().toLowerCase());
+ }
+}
diff --git a/base/src/main/java/bjc/utils/misc/PropertyDB.java b/base/src/main/java/bjc/utils/misc/PropertyDB.java
new file mode 100644
index 0000000..c9434ef
--- /dev/null
+++ b/base/src/main/java/bjc/utils/misc/PropertyDB.java
@@ -0,0 +1,155 @@
+package bjc.utils.misc;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.regex.Pattern;
+
+import bjc.utils.funcutils.LambdaLock;
+import bjc.utils.ioutils.SimpleProperties;
+
+/**
+ * Database for storage of properties from external files.
+ *
+ * @author EVE
+ *
+ */
+public class PropertyDB {
+ /* Regex storage. */
+ private static SimpleProperties regexes;
+ private static Map<String, Pattern> compiledRegexes;
+
+ /* Format string storage. */
+ private static SimpleProperties formats;
+
+ /*
+ * Whether or not to log during the loading.
+ */
+ private static final boolean LOGLOAD = false;
+
+ /*
+ * The lock to use to ensure a read can't happen during a reload
+ */
+ private static LambdaLock loadLock = new LambdaLock();
+
+ static {
+ /* Reload properties on class load. */
+ reloadProperties();
+ }
+
+ /**
+ * Reload all the properties from their files.
+ *
+ * NOTE: Any attempts to read from the property DB while properties are
+ * being loaded will block, to prevent reads from partial states.
+ */
+ public static void reloadProperties() {
+ /* * Do the load with the write lock taken. */
+ loadLock.write(() -> {
+ if(LOGLOAD) {
+ System.out.println("Reading regex properties:");
+ }
+
+ /* * Load regexes. */
+ regexes = new SimpleProperties();
+ regexes.loadFrom(PropertyDB.class.getResourceAsStream("/regexes.sprop"), false);
+ if(LOGLOAD) {
+ regexes.outputProperties();
+ System.out.println();
+ }
+ compiledRegexes = new HashMap<>();
+
+ if(LOGLOAD) {
+ System.out.println("Reading format properties:");
+ }
+
+ /* * Load formats. */
+ formats = new SimpleProperties();
+ formats.loadFrom(PropertyDB.class.getResourceAsStream("/formats.sprop"), false);
+ if(LOGLOAD) {
+ formats.outputProperties();
+ System.out.println();
+ }
+ });
+ }
+
+ /**
+ * Retrieve a persisted regular expression.
+ *
+ * @param key
+ * The name of the regular expression.
+ *
+ * @return The regular expression with that name.
+ */
+ public static String getRegex(final String key) {
+ return loadLock.read(() -> {
+ if(!regexes.containsKey(key)) {
+ final String msg = String.format("No regular expression named '%s' found", key);
+
+ throw new NoSuchElementException(msg);
+ }
+
+ return regexes.get(key);
+ });
+ }
+
+ /**
+ * Retrieve a persisted regular expression, compiled into a regular
+ * expression.
+ *
+ * @param key
+ * The name of the regular expression.
+ *
+ * @return The regular expression with that name.
+ */
+ public static Pattern getCompiledRegex(final String key) {
+ return loadLock.read(() -> {
+ if(!regexes.containsKey(key)) {
+ final String msg = String.format("No regular expression named '%s' found", key);
+
+ throw new NoSuchElementException(msg);
+ }
+
+ /* * Get the regex, and cache a compiled version. */
+ return compiledRegexes.computeIfAbsent(key, strang -> {
+ return Pattern.compile(regexes.get(strang));
+ });
+ });
+ }
+
+ /**
+ * Retrieve a persisted format string.
+ *
+ * @param key
+ * The name of the format string.
+ *
+ * @return The format string with that name.
+ */
+ public static String getFormat(final String key) {
+ return loadLock.read(() -> {
+ if(!formats.containsKey(key)) {
+ final String msg = String.format("No format string named '%s' found", key);
+
+ throw new NoSuchElementException(msg);
+ }
+
+ return formats.get(key);
+ });
+ }
+
+ /**
+ * Retrieve a persisted format string, and apply it to a set of
+ * arguments.
+ *
+ * @param key
+ * The name of the format string.
+ *
+ * @param objects
+ * The parameters to the format string.
+ *
+ * @return The format string with that name.
+ */
+ public static String applyFormat(final String key, final Object... objects) {
+ return String.format(getFormat(key), objects);
+ }
+}
diff --git a/base/src/main/java/bjc/utils/misc/RelativeDirection.java b/base/src/main/java/bjc/utils/misc/RelativeDirection.java
new file mode 100644
index 0000000..d7ccf6e
--- /dev/null
+++ b/base/src/main/java/bjc/utils/misc/RelativeDirection.java
@@ -0,0 +1,123 @@
+package bjc.utils.misc;
+
+import java.util.Random;
+import java.util.function.Consumer;
+
+import bjc.utils.exceptions.InvalidDirectionException;
+import bjc.utils.funcdata.FunctionalList;
+import bjc.utils.funcdata.IList;
+
+/**
+ * Represents a direction that is relative to another direction
+ *
+ * @author ben
+ *
+ */
+public enum RelativeDirection {
+ /**
+ * Same as direction
+ */
+ BACKWARD,
+ /**
+ * Opposing direction
+ */
+ FORWARD,
+ /**
+ * Counterclockwise from direction
+ */
+ LEFT,
+ /**
+ * Clockwise from direction
+ */
+ RIGHT;
+
+ private static Random RNG = new Random();
+
+ /**
+ * Perform a specified action for a random number of relative
+ * directions.
+ *
+ * @param numDirections
+ * The number of cardinal directions to act on. Must be
+ * greater than 0 and less then 5
+ * @param action
+ * The action to perform for each of the relative directions
+ * @param ignoreBackwards
+ * Whether or not to not have a chance of one of the
+ * directions being backwards
+ */
+ public static void forRandomDirections(int numDirections,
+ Consumer<RelativeDirection> action, boolean ignoreBackwards) {
+ int maxNDirections;
+
+ if (ignoreBackwards) {
+ maxNDirections = 3;
+ } else {
+ maxNDirections = 4;
+ }
+
+ if (numDirections <= 0 || numDirections > maxNDirections) {
+ throw new IllegalArgumentException(
+ "Tried to do things with incorrect number of relative directions. Tried with "
+ + numDirections);
+ }
+
+ IList<RelativeDirection> relativeDirs =
+ new FunctionalList<>(values());
+
+ if (ignoreBackwards) {
+ relativeDirs.removeMatching(BACKWARD);
+ }
+
+ for (int i = 0; i <= maxNDirections - numDirections; i++) {
+ RelativeDirection relativeDir =
+ relativeDirs.randItem(RNG::nextInt);
+
+ relativeDirs.removeMatching(relativeDir);
+ }
+
+ relativeDirs.forEach(action);
+ }
+
+ /**
+ * Properly convert a string to a relative direction
+ *
+ * @param value
+ * The string to convert
+ * @return The relative direction represented by the string
+ */
+ public static RelativeDirection properValueOf(String value) {
+ return valueOf(value.toUpperCase());
+ }
+
+ /**
+ * Change another direction by turning the way this direction specifies
+ *
+ * @param dir
+ * The direction to change
+ * @return The direction after turning this way
+ */
+ public Direction makeAbsolute(Direction dir) {
+ // Only cardinal directions can be truly absolutized
+ if (dir.isCardinal()) {
+ switch (this) {
+ case BACKWARD:
+ return dir;
+ case FORWARD:
+ return dir.opposing();
+ case LEFT:
+ return dir.rotateCounterClockwise();
+ case RIGHT:
+ return dir.rotateClockwise();
+ default:
+ throw new InvalidDirectionException(
+ "Attempted to make absolute a direction in a unknown way "
+ + this);
+ }
+ }
+
+ // Since it isn't a cardinal direction, absolutize it against a
+ // random direction
+ return this.makeAbsolute(Direction.NORTH);
+ }
+}