From 16956fa927a08c137ab2cf95cb3b3da5ad81f054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Mon, 28 Jul 2014 14:27:38 +0200 Subject: [PATCH] Cleanup and minor javadoc fixes --- src/mightypork/utils/Convert.java | 76 +- src/mightypork/utils/MapSort.java | 18 +- src/mightypork/utils/Reflect.java | 54 +- src/mightypork/utils/Support.java | 37 +- src/mightypork/utils/annotations/Alias.java | 11 +- .../utils/annotations/FactoryMethod.java | 4 +- src/mightypork/utils/annotations/Stub.java | 2 +- src/mightypork/utils/config/SimpleConfig.java | 104 +-- .../utils/config/propmgr/Property.java | 28 +- .../utils/config/propmgr/PropertyManager.java | 138 ++-- .../utils/config/propmgr/PropertyStore.java | 44 +- .../propmgr/properties/BooleanProperty.java | 18 +- .../propmgr/properties/DoubleProperty.java | 18 +- .../propmgr/properties/IntegerProperty.java | 18 +- .../propmgr/properties/StringProperty.java | 18 +- .../config/propmgr/store/PropertyFile.java | 70 +- .../propmgr/store/SortedProperties.java | 114 +-- src/mightypork/utils/eventbus/BusEvent.java | 50 +- src/mightypork/utils/eventbus/EventBus.java | 215 +++--- .../utils/eventbus/EventChannel.java | 93 +-- .../utils/eventbus/clients/BusNode.java | 40 +- .../utils/eventbus/clients/ClientHub.java | 24 +- .../utils/eventbus/clients/ClientList.java | 7 +- .../eventbus/clients/DelegatingClient.java | 10 +- .../eventbus/clients/DelegatingList.java | 40 +- .../eventbus/clients/ToggleableClient.java | 6 +- .../utils/eventbus/events/DestroyEvent.java | 6 +- .../utils/eventbus/events/UpdateEvent.java | 15 +- .../eventbus/events/flags/DelayedEvent.java | 11 +- .../eventbus/events/flags/DirectEvent.java | 9 +- .../events/flags/NonConsumableEvent.java | 4 +- .../events/flags/NonRejectableEvent.java | 4 +- .../eventbus/events/flags/NotLoggedEvent.java | 9 +- .../events/flags/SingleReceiverEvent.java | 9 +- .../exceptions/CorruptDataException.java | 30 +- .../exceptions/IllegalValueException.java | 30 +- .../exceptions/KeyAlreadyExistsException.java | 30 +- .../utils/files/FileSuffixFilter.java | 25 +- src/mightypork/utils/files/FileTreeDiff.java | 96 +-- src/mightypork/utils/files/FileUtil.java | 64 +- src/mightypork/utils/files/InstanceLock.java | 16 +- src/mightypork/utils/files/OsUtils.java | 52 +- src/mightypork/utils/files/WorkDir.java | 96 +++ .../utils/files/zip/ZipBuilder.java | 65 +- src/mightypork/utils/files/zip/ZipUtils.java | 92 +-- .../utils/interfaces/Destroyable.java | 4 +- .../utils/interfaces/Enableable.java | 10 +- src/mightypork/utils/interfaces/Hideable.java | 8 +- .../utils/interfaces/Pauseable.java | 14 +- src/mightypork/utils/interfaces/Pollable.java | 4 +- .../utils/interfaces/Updateable.java | 6 +- src/mightypork/utils/ion/Ion.java | 243 ++++--- src/mightypork/utils/ion/IonBinary.java | 12 +- src/mightypork/utils/ion/IonBundled.java | 12 +- src/mightypork/utils/ion/IonDataBundle.java | 216 +++--- src/mightypork/utils/ion/IonInput.java | 247 ++++--- src/mightypork/utils/ion/IonMapWrapper.java | 34 +- src/mightypork/utils/ion/IonOutput.java | 225 +++--- .../utils/ion/IonSequenceWrapper.java | 34 +- src/mightypork/utils/ion/IonizerBinary.java | 18 +- src/mightypork/utils/ion/IonizerBundled.java | 18 +- src/mightypork/utils/logging/Log.java | 172 ++--- .../utils/logging/monitors/LogMonitor.java | 22 +- .../logging/monitors/LogMonitorStdout.java | 4 +- .../utils/logging/writers/ArchivingLog.java | 62 +- .../utils/logging/writers/LogWriter.java | 42 +- .../utils/logging/writers/SimpleLog.java | 81 +-- src/mightypork/utils/math/AlignX.java | 2 +- src/mightypork/utils/math/AlignY.java | 2 +- src/mightypork/utils/math/Calc.java | 181 ++--- src/mightypork/utils/math/Polar.java | 92 +-- src/mightypork/utils/math/Range.java | 129 ++-- src/mightypork/utils/math/algo/Coord.java | 93 +-- src/mightypork/utils/math/algo/Move.java | 37 +- src/mightypork/utils/math/algo/Moves.java | 62 +- .../utils/math/algo/floodfill/FloodFill.java | 48 +- .../math/algo/pathfinding/Heuristic.java | 4 +- .../math/algo/pathfinding/PathFinder.java | 133 ++-- .../algo/pathfinding/PathFinderProxy.java | 33 +- .../heuristics/DiagonalHeuristic.java | 2 +- .../heuristics/ManhattanHeuristic.java | 2 +- src/mightypork/utils/math/angles/Angles.java | 20 +- src/mightypork/utils/math/angles/Deg.java | 70 +- src/mightypork/utils/math/angles/Rad.java | 46 +- .../utils/math/animation/Animator.java | 90 +-- .../utils/math/animation/AnimatorBounce.java | 40 +- .../utils/math/animation/AnimatorRewind.java | 34 +- .../utils/math/animation/Easing.java | 156 ++-- .../utils/math/animation/NumAnimated.java | 228 +++--- .../utils/math/animation/NumAnimatedDeg.java | 31 +- .../utils/math/animation/NumAnimatedRad.java | 31 +- .../utils/math/animation/VectAnimated.java | 138 ++-- src/mightypork/utils/math/color/Color.java | 136 ++-- .../utils/math/color/ColorAlphaAdjuster.java | 27 +- src/mightypork/utils/math/color/ColorHsb.java | 33 +- src/mightypork/utils/math/color/ColorRgb.java | 27 +- src/mightypork/utils/math/color/Grad.java | 15 +- src/mightypork/utils/math/color/GradH.java | 9 +- src/mightypork/utils/math/color/GradV.java | 9 +- src/mightypork/utils/math/color/pal/CGA.java | 8 +- src/mightypork/utils/math/color/pal/CMDR.java | 4 +- .../utils/math/color/pal/PAL16.java | 12 +- src/mightypork/utils/math/color/pal/RGB.java | 14 +- src/mightypork/utils/math/color/pal/ZX.java | 8 +- .../math/constraints/CachedConstraint.java | 22 +- .../math/constraints/CachedDigestable.java | 16 +- .../utils/math/constraints/DigestCache.java | 30 +- .../utils/math/constraints/Digestable.java | 8 +- .../utils/math/constraints/num/Num.java | 458 ++++++------ .../utils/math/constraints/num/NumBound.java | 6 +- .../utils/math/constraints/num/NumConst.java | 156 ++-- .../constraints/num/PluggableNumBound.java | 6 +- .../math/constraints/num/batch/NumMul.java | 20 +- .../math/constraints/num/batch/NumSum.java | 20 +- .../num/caching/AbstractNumCache.java | 47 +- .../constraints/num/caching/NumCache.java | 21 +- .../constraints/num/caching/NumDigest.java | 13 +- .../constraints/num/proxy/NumAdapter.java | 8 +- .../math/constraints/num/proxy/NumProxy.java | 28 +- .../math/constraints/num/var/NumMutable.java | 18 +- .../math/constraints/num/var/NumVar.java | 28 +- .../constraints/rect/PluggableRectBound.java | 6 +- .../utils/math/constraints/rect/Rect.java | 612 ++++++++-------- .../math/constraints/rect/RectBound.java | 4 +- .../math/constraints/rect/RectConst.java | 271 +++---- .../constraints/rect/builders/TiledRect.java | 61 +- .../rect/caching/AbstractRectCache.java | 39 +- .../constraints/rect/caching/RectCache.java | 21 +- .../constraints/rect/caching/RectDigest.java | 22 +- .../constraints/rect/proxy/RectAdapter.java | 26 +- .../constraints/rect/proxy/RectProxy.java | 28 +- .../rect/proxy/RectVectAdapter.java | 21 +- .../constraints/rect/var/RectMutable.java | 44 +- .../math/constraints/rect/var/RectVar.java | 27 +- .../constraints/vect/PluggableVectBound.java | 6 +- .../utils/math/constraints/vect/Vect.java | 680 +++++++++--------- .../math/constraints/vect/VectBound.java | 4 +- .../math/constraints/vect/VectConst.java | 216 +++--- .../vect/caching/AbstractVectCache.java | 39 +- .../constraints/vect/caching/VectCache.java | 19 +- .../constraints/vect/caching/VectDigest.java | 13 +- .../constraints/vect/proxy/VectAdapter.java | 18 +- .../vect/proxy/VectNumAdapter.java | 32 +- .../constraints/vect/proxy/VectProxy.java | 28 +- .../constraints/vect/var/VectMutable.java | 40 +- .../math/constraints/vect/var/VectVar.java | 39 +- src/mightypork/utils/math/noise/NoiseGen.java | 58 +- .../math/noise/PerlinNoiseGenerator.java | 245 +++---- .../utils/math/timing/FpsMeter.java | 12 +- .../utils/math/timing/Profiler.java | 51 +- .../utils/math/timing/TaskRepeater.java | 27 +- .../utils/math/timing/TimedTask.java | 22 +- .../utils/math/timing/TimerDelta.java | 25 +- .../utils/math/timing/TimerFps.java | 49 +- .../utils/string/AlphanumComparator.java | 28 +- .../utils/string/StringProvider.java | 4 +- src/mightypork/utils/string/StringUtil.java | 38 +- .../utils/string/StringWrapper.java | 25 +- .../utils/string/validation/CharFilter.java | 2 +- .../string/validation/CharFilterRegex.java | 15 +- .../validation/CharFilterWhitelist.java | 15 +- .../utils/string/validation/StringFilter.java | 4 +- src/mightypork/utils/struct/Mutable.java | 37 +- src/mightypork/utils/struct/Pair.java | 37 +- src/mightypork/utils/struct/Triad.java | 45 +- 165 files changed, 4872 insertions(+), 4502 deletions(-) create mode 100644 src/mightypork/utils/files/WorkDir.java diff --git a/src/mightypork/utils/Convert.java b/src/mightypork/utils/Convert.java index d75a806..fa2c4ea 100644 --- a/src/mightypork/utils/Convert.java +++ b/src/mightypork/utils/Convert.java @@ -4,14 +4,14 @@ package mightypork.utils; /** * Utility for converting Object to data types; Can also convert strings to data * types. - * + * * @author Ondřej Hruška (MightyPork) */ public class Convert { - + /** * Get INTEGER - * + * * @param o object * @param def default value * @return integer @@ -26,11 +26,11 @@ public class Convert { } catch (final NumberFormatException e) {} return def; } - - + + /** * Get DOUBLE - * + * * @param o object * @param def default value * @return double @@ -45,11 +45,11 @@ public class Convert { } catch (final NumberFormatException e) {} return def; } - - + + /** * Get FLOAT - * + * * @param o object * @param def default value * @return float @@ -62,11 +62,11 @@ public class Convert { } catch (final NumberFormatException e) {} return def; } - - + + /** * Get BOOLEAN - * + * * @param o object * @param def default value * @return boolean @@ -76,7 +76,7 @@ public class Convert { if (o == null) return def; if (o instanceof Boolean) return ((Boolean) o).booleanValue(); if (o instanceof Number) return ((Number) o).intValue() != 0; - + if (o instanceof String) { final String s = ((String) o).trim().toLowerCase(); if (s.equals("0")) return false; @@ -85,26 +85,26 @@ public class Convert { final double n = Double.parseDouble(s); return n != 0; } catch (final NumberFormatException e) {} - + if (s.equals("true")) return true; if (s.equals("yes")) return true; if (s.equals("y")) return true; if (s.equals("a")) return true; if (s.equals("enabled")) return true; - + if (s.equals("false")) return false; if (s.equals("no")) return false; if (s.equals("n")) return false; if (s.equals("disabled")) return true; } - + return def; } - - + + /** * Get STRING - * + * * @param o object * @param def default value * @return String @@ -113,22 +113,22 @@ public class Convert { { if (o == null) return def; if (o instanceof String) return ((String) o); - + if (o instanceof Float) return Support.str((float) o); - + if (o instanceof Double) return Support.str((double) o); - + if (o instanceof Class) { return Support.str(o); } - + return o.toString(); } - - + + /** * Get INTEGER - * + * * @param o object * @return integer */ @@ -136,11 +136,11 @@ public class Convert { { return toInteger(o, 0); } - - + + /** * Get DOUBLE - * + * * @param o object * @return double */ @@ -148,11 +148,11 @@ public class Convert { { return toDouble(o, 0d); } - - + + /** * Get FLOAT - * + * * @param o object * @return float */ @@ -160,11 +160,11 @@ public class Convert { { return toFloat(o, 0f); } - - + + /** * Get BOOLEAN - * + * * @param o object * @return boolean */ @@ -172,11 +172,11 @@ public class Convert { { return toBoolean(o, false); } - - + + /** * Get STRING - * + * * @param o object * @return String */ diff --git a/src/mightypork/utils/MapSort.java b/src/mightypork/utils/MapSort.java index ca94859..55b9abe 100644 --- a/src/mightypork/utils/MapSort.java +++ b/src/mightypork/utils/MapSort.java @@ -1,20 +1,25 @@ package mightypork.utils; -import java.util.*; +import java.util.Collections; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; import java.util.Map.Entry; /** * Map sorting utils - * + * * @author Ondřej Hruška (MightyPork) */ public class MapSort { /** * Sort a map by keys, maintaining key-value pairs, using natural order. - * + * * @param map map to be sorted * @return linked hash map with sorted entries */ @@ -27,7 +32,7 @@ public class MapSort { /** * Sort a map by keys, maintaining key-value pairs. - * + * * @param map map to be sorted * @param comparator a comparator, or null for natural ordering * @return linked hash map with sorted entries @@ -61,7 +66,7 @@ public class MapSort { /** * Sort a map by values, maintaining key-value pairs, using natural order. - * + * * @param map map to be sorted * @return linked hash map with sorted entries */ @@ -74,7 +79,7 @@ public class MapSort { /** * Sort a map by values, maintaining key-value pairs. - * + * * @param map map to be sorted * @param comparator a comparator, or null for natural ordering * @return linked hash map with sorted entries @@ -85,6 +90,7 @@ public class MapSort { Collections.sort(entries, new Comparator>() { + @SuppressWarnings("unchecked") @Override public int compare(Entry o1, Entry o2) { diff --git a/src/mightypork/utils/Reflect.java b/src/mightypork/utils/Reflect.java index a16deca..4edd3e2 100644 --- a/src/mightypork/utils/Reflect.java +++ b/src/mightypork/utils/Reflect.java @@ -10,14 +10,14 @@ import java.lang.reflect.Type; /** * Miscelanous reflection-related utilities - * + * * @author Ondřej Hruška (MightyPork) */ public class Reflect { - + /** * Get annotation of given type from an object - * + * * @param tested the examined object * @param annotation annotation we want * @return the anotation on that object, or null @@ -26,11 +26,11 @@ public class Reflect { { return tested.getClass().getAnnotation(annotation); } - - + + /** * Check if an object has an annotation of given trype - * + * * @param tested the examined object * @param annotation annotation we want * @return true if the annotation is present on the object @@ -39,48 +39,58 @@ public class Reflect { { return tested.getClass().isAnnotationPresent(annotation); } - - + + /** * Get generic parameters of a class - * + * * @param clazz the examined class * @return parameter types */ public static Class[] getGenericParameters(Class clazz) { // BEHOLD, MAGIC! - + final Type evtc = clazz.getGenericSuperclass(); - + if (evtc instanceof ParameterizedType) { final Type[] types = ((ParameterizedType) evtc).getActualTypeArguments(); - + final Class[] classes = new Class[types.length]; - + for (int i = 0; i < types.length; i++) { classes[i] = (Class) types[i]; } - + return classes; } - + throw new RuntimeException(Support.str(clazz) + " is not generic."); } - - + + + /** + * Get value of a public static final field. If the modifiers don't match, + * an exception is thrown. + * + * @param objClass the class + * @param fieldName field to retrieve + * @return the field value + * @throws ReflectiveOperationException if the field is not constant, or if + * the value could not be retrieved. + */ public static Object getConstantFieldValue(Class objClass, String fieldName) throws ReflectiveOperationException { final Field fld = objClass.getDeclaredField(fieldName); - + final int modif = fld.getModifiers(); - + if (!Modifier.isFinal(modif) || !Modifier.isStatic(modif)) { - throw new RuntimeException("The " + fieldName + " field of " + Support.str(objClass) + " must be static and final!"); + throw new ReflectiveOperationException("The " + fieldName + " field of " + Support.str(objClass) + " must be static and final!"); } - + fld.setAccessible(true); return fld.get(null); } - + } diff --git a/src/mightypork/utils/Support.java b/src/mightypork/utils/Support.java index 8bf4b92..7923fd5 100644 --- a/src/mightypork/utils/Support.java +++ b/src/mightypork/utils/Support.java @@ -14,14 +14,14 @@ import mightypork.utils.annotations.Alias; /** * Miscelanous utilities - * + * * @author Ondřej Hruška (MightyPork) */ public final class Support { /** * Create a new thread of the runnable, and start it. - * + * * @param r runnable * @return the thread started */ @@ -35,7 +35,7 @@ public final class Support { /** * Pick first non-null option - * + * * @param options options * @return the selected option */ @@ -51,7 +51,7 @@ public final class Support { /** * Get current time/date for given format. - * + * * @param format format, according to {@link DateFormat}. * @return the formatted time/date */ @@ -64,7 +64,7 @@ public final class Support { /** * Parse array of vararg key, value pairs to a LinkedHashMap.
* Example: - * + * *
 	 * Object[] array = {
 	 *     "one", 1,
@@ -72,10 +72,10 @@ public final class Support {
 	 *     "three", 9,
 	 *     "four", 16
 	 * };
-	 * 
+	 *
 	 * Map<String, Integer> args = parseVarArgs(array);
 	 * 
- * + * * @param args varargs * @return LinkedHashMap * @throws ClassCastException in case of incompatible type in the array @@ -107,7 +107,7 @@ public final class Support { /** * Get if an Object is in array (using equals) - * + * * @param needle checked Object * @param haystack array of Objects * @return is in array @@ -123,7 +123,7 @@ public final class Support { /** * Get if string is in array - * + * * @param needle checked string * @param case_sensitive case sensitive comparision * @param haystack array of possible values @@ -144,7 +144,7 @@ public final class Support { /** * Make enumeration iterable - * + * * @param enumeration enumeration * @return iterable wrapper */ @@ -155,7 +155,7 @@ public final class Support { /** * Helper class for iterationg over an {@link Enumeration} - * + * * @author Ondřej Hruška (MightyPork) * @param target element type (will be cast) */ @@ -167,7 +167,8 @@ public final class Support { /** * @param enumeration the iterated enumeration */ - public IterableEnumerationWrapper(Enumeration enumeration) { + public IterableEnumerationWrapper(Enumeration enumeration) + { this.enumeration = enumeration; } @@ -205,9 +206,9 @@ public final class Support { /** * Convert a class to string, preserving name and outer class, but excluding * path. - * - * @param cls - * @return + * + * @param cls the class + * @return class name */ public static String str(Class cls) { @@ -236,7 +237,7 @@ public final class Support { /** * Convert double to string, remove the mess at the end. - * + * * @param d double * @return string */ @@ -253,7 +254,7 @@ public final class Support { /** * Convert float to string, remove the mess at the end. - * + * * @param f float * @return string */ @@ -270,7 +271,7 @@ public final class Support { /** * Convert object to string. If the object overrides toString(), it is * caled. Otherwise it's class name is converted to string. - * + * * @param o object * @return string representation */ diff --git a/src/mightypork/utils/annotations/Alias.java b/src/mightypork/utils/annotations/Alias.java index 7ffd1ad..e830233 100644 --- a/src/mightypork/utils/annotations/Alias.java +++ b/src/mightypork/utils/annotations/Alias.java @@ -1,13 +1,18 @@ package mightypork.utils.annotations; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Specify pretty name to be used when logging / converting class name to * string. - * + * * @author Ondřej Hruška (MightyPork) */ @Retention(RetentionPolicy.RUNTIME) @@ -15,6 +20,6 @@ import java.lang.annotation.*; @Documented @Target(ElementType.TYPE) public @interface Alias { - + String name(); } diff --git a/src/mightypork/utils/annotations/FactoryMethod.java b/src/mightypork/utils/annotations/FactoryMethod.java index a502e90..50cd51a 100644 --- a/src/mightypork/utils/annotations/FactoryMethod.java +++ b/src/mightypork/utils/annotations/FactoryMethod.java @@ -11,12 +11,12 @@ import java.lang.annotation.Target; /** * Marks a static factory method. This is a description annotation and has no * other function. - * + * * @author Ondřej Hruška (MightyPork) */ @Retention(RetentionPolicy.SOURCE) @Target(ElementType.METHOD) @Documented public @interface FactoryMethod { - + } diff --git a/src/mightypork/utils/annotations/Stub.java b/src/mightypork/utils/annotations/Stub.java index 6e9d7a2..f27eba6 100644 --- a/src/mightypork/utils/annotations/Stub.java +++ b/src/mightypork/utils/annotations/Stub.java @@ -12,7 +12,7 @@ import java.lang.annotation.Target; * Marked method can be safely overriden; it's left blank (or with default * implementation) as a convenience.
* This is a description annotation and has no other function. - * + * * @author Ondřej Hruška (MightyPork) */ @Documented diff --git a/src/mightypork/utils/config/SimpleConfig.java b/src/mightypork/utils/config/SimpleConfig.java index 29550ba..70f8f6f 100644 --- a/src/mightypork/utils/config/SimpleConfig.java +++ b/src/mightypork/utils/config/SimpleConfig.java @@ -19,14 +19,14 @@ import mightypork.utils.logging.Log; * empty lines and lines without "=" are ignored
* lines with "=" must have "key = value" format, or a warning is logged.
* use "NULL" to create empty value. - * + * * @author Ondřej Hruška (MightyPork) */ public class SimpleConfig { - + /** * Load list from file - * + * * @param file file * @return map of keys and values * @throws IOException @@ -34,14 +34,14 @@ public class SimpleConfig { public static List listFromFile(File file) throws IOException { final String fileText = FileUtil.fileToString(file); - + return listFromString(fileText); } - - + + /** * Load map from file - * + * * @param file file * @return map of keys and values * @throws IOException @@ -49,98 +49,98 @@ public class SimpleConfig { public static Map mapFromFile(File file) throws IOException { final String fileText = FileUtil.fileToString(file); - + return mapFromString(fileText); } - - + + /** * Load list from string - * + * * @param text text of the file * @return map of keys and values */ public static List listFromString(String text) { final List list = new ArrayList<>(); - + final String[] groupsLines = text.split("\n"); - + for (String s : groupsLines) { // ignore invalid lines if (s.length() == 0) continue; if (s.startsWith("#") || s.startsWith("//")) continue; - + // NULL value if (s.equalsIgnoreCase("NULL")) s = null; - + if (s != null) s = s.replace("\\n", "\n"); - + // save extracted key-value pair list.add(s); } - + return list; } - - + + /** * Load map from string - * + * * @param text text of the file * @return map of keys and values */ public static Map mapFromString(String text) { final LinkedHashMap pairs = new LinkedHashMap<>(); - + final String[] groupsLines = text.split("\n"); - + for (final String s : groupsLines) { // ignore invalid lines if (s.length() == 0) continue; if (s.startsWith("#") || s.startsWith("//")) continue; if (!s.contains("=")) continue; - + // split and trim String[] parts = s.split("="); for (int i = 0; i < parts.length; i++) { parts[i] = parts[i].trim(); } - + // check if both parts are valid if (parts.length == 0) { Log.w("Bad line in config file: " + s); continue; } - + if (parts.length == 1) { parts = new String[] { parts[0], "" }; } - + if (parts.length != 2) { Log.w("Bad line in config file: " + s); continue; } - + // NULL value if (parts[0].equalsIgnoreCase("NULL")) parts[0] = null; if (parts[1].equalsIgnoreCase("NULL")) parts[1] = null; - + if (parts[0] != null) parts[0] = parts[0].replace("\\n", "\n"); if (parts[1] != null) parts[1] = parts[1].replace("\\n", "\n"); - + // save extracted key-value pair pairs.put(parts[0], parts[1]); } - + return pairs; } - - + + /** * Save map to file - * + * * @param target * @param data * @param allowNulls allow nulls. @@ -149,38 +149,38 @@ public class SimpleConfig { public static void mapToFile(File target, Map data, boolean allowNulls) throws IOException { final List lines = new ArrayList<>(); - + for (final Entry e : data.entrySet()) { String key = e.getKey(); String value = e.getValue(); - + if (!allowNulls && (key == null || value == null || key.length() == 0 || value.length() == 0)) continue; - + if (key == null) key = "NULL"; if (value == null) value = "NULL"; - + key = key.replace("\n", "\\n"); value = value.replace("\n", "\\n"); - + lines.add(key + " = " + value); } - + String text = ""; // # File written by SimpleConfig - + for (final String s : lines) { if (text.length() > 0) text += "\n"; - + text += s; } - + FileUtil.stringToFile(target, text); - + } - - + + /** * Save list to file - * + * * @param target * @param data * @throws IOException @@ -188,18 +188,18 @@ public class SimpleConfig { public static void listToFile(File target, List data) throws IOException { String text = ""; // # File written by SimpleConfig - + for (String s : data) { if (text.length() > 0) text += "\n"; - + if (s == null) s = "NULL"; - + s = s.replace("\n", "\\n"); - + text += s; } - + FileUtil.stringToFile(target, text); - + } } diff --git a/src/mightypork/utils/config/propmgr/Property.java b/src/mightypork/utils/config/propmgr/Property.java index bea041a..f47a5ae 100644 --- a/src/mightypork/utils/config/propmgr/Property.java +++ b/src/mightypork/utils/config/propmgr/Property.java @@ -9,7 +9,7 @@ import mightypork.utils.annotations.Stub; * Property entry for the {@link PropertyManager}.
* Extending this class can be used to add custom property types that are not * supported by default. - * + * * @author Ondřej Hruška (MightyPork) * @param property type */ @@ -24,26 +24,28 @@ public abstract class Property { /** * Create a property without comment - * + * * @param key key in the config file * @param defaultValue defualt property value (used as fallback when * parsing) */ - public Property(String key, T defaultValue) { + public Property(String key, T defaultValue) + { this(key, defaultValue, null); } /** * Create a property with a comment - * + * * @param key key in the config file - * @param defaultValue defualt property value (used as fallback when - * parsing) + * @param defaultValue default property value, used as fallback when + * parsing. Initially the value is assigned to defaultValue. * @param comment optional property comment included above the property in * the config file. Can be null. */ - public Property(String key, T defaultValue, String comment) { + public Property(String key, T defaultValue, String comment) + { this.comment = comment; this.key = key; this.value = defaultValue; @@ -54,7 +56,7 @@ public abstract class Property { /** * Parse a string representation of the value into this property. If the * value cannot be decoded, use the default value instead. - * + * * @param string property value as string */ public abstract void fromString(String string); @@ -62,7 +64,7 @@ public abstract class Property { /** * Get property value as string (compatible with `fromString()) - * + * * @return property value as string */ @Override @@ -75,7 +77,7 @@ public abstract class Property { /** * Get the current property value - * + * * @return the value */ public T getValue() @@ -87,7 +89,7 @@ public abstract class Property { /** * Set property value.
* Uses Object to allow setValue(Object) method in {@link PropertyManager} - * + * * @param value value to set. * @throws ClassCastException in case of incompatible type. */ @@ -100,7 +102,7 @@ public abstract class Property { /** * Get property comment. - * + * * @return the comment text (can be null if no comment is defined) */ public String getComment() @@ -111,7 +113,7 @@ public abstract class Property { /** * Get property key - * + * * @return property key */ public String getKey() diff --git a/src/mightypork/utils/config/propmgr/PropertyManager.java b/src/mightypork/utils/config/propmgr/PropertyManager.java index 782e39e..a98e051 100644 --- a/src/mightypork/utils/config/propmgr/PropertyManager.java +++ b/src/mightypork/utils/config/propmgr/PropertyManager.java @@ -18,95 +18,97 @@ import mightypork.utils.logging.Log; /** * Property manager with advanced formatting and value checking. - * + * * @author Ondřej Hruška (MightyPork) */ public class PropertyManager { - + private final TreeMap> entries = new TreeMap<>(); private final TreeMap renameTable = new TreeMap<>(); - private PropertyStore props; - - + private final PropertyStore props; + + /** * Create property manager from file path and a header comment.
* This is the same as using a {@link PropertyFile} store. - * + * * @param file property file * @param comment header comment. */ - public PropertyManager(File file, String comment) { + public PropertyManager(File file, String comment) + { this(new PropertyFile(file, comment)); } - - + + /** * Create property manager based on provided {@link PropertyStore} - * + * * @param props a property store implementation backing this property * manager */ - public PropertyManager(PropertyStore props) { + public PropertyManager(PropertyStore props) + { this.props = props; } - - + + /** * Load from file */ public void load() { props.load(); - + // rename keys (useful if keys change but value is to be kept) for (final Entry entry : renameTable.entrySet()) { - + final String value = props.getProperty(entry.getKey()); - + if (value == null) continue; - + final String oldKey = entry.getKey(); final String newKey = entry.getValue(); - + props.removeProperty(oldKey); props.setProperty(newKey, value, entries.get(newKey).getComment()); } - + for (final Property entry : entries.values()) { entry.fromString(props.getProperty(entry.getKey())); } } - - + + public void save() { try { final ArrayList keyList = new ArrayList<>(); - + // validate entries one by one, replace with default when needed for (final Property entry : entries.values()) { keyList.add(entry.getKey()); - + props.setProperty(entry.getKey(), entry.toString(), entry.getComment()); } - + // removed unused props for (final String key : props.keys()) { if (!keyList.contains(key)) { props.removeProperty(key); } } - + props.save(); } catch (final IOException ioe) { ioe.printStackTrace(); } } - - + + /** * Get a property entry (rarely used) - * + * * @param k key * @return the entry */ @@ -119,11 +121,11 @@ public class PropertyManager { return null; } } - - + + /** * Get boolean property - * + * * @param k key * @return the boolean found, or false */ @@ -131,11 +133,11 @@ public class PropertyManager { { return Convert.toBoolean(getProperty(k).getValue()); } - - + + /** * Get numeric property - * + * * @param k key * @return the int found, or null */ @@ -143,11 +145,11 @@ public class PropertyManager { { return Convert.toInteger(getProperty(k).getValue()); } - - + + /** * Get numeric property as double - * + * * @param k key * @return the double found, or null */ @@ -155,11 +157,11 @@ public class PropertyManager { { return Convert.toDouble(getProperty(k).getValue()); } - - + + /** * Get string property - * + * * @param k key * @return the string found, or null */ @@ -167,11 +169,11 @@ public class PropertyManager { { return Convert.toString(getProperty(k).getValue()); } - - + + /** * Get arbitrary property. Make sure it's of the right type! - * + * * @param k key * @return the prioperty found */ @@ -184,11 +186,11 @@ public class PropertyManager { return null; } } - - + + /** * Add a boolean property - * + * * @param k key * @param d default value * @param comment the in-file comment @@ -197,11 +199,11 @@ public class PropertyManager { { addProperty(new BooleanProperty(k, d, comment)); } - - + + /** * Add a numeric property (double) - * + * * @param k key * @param d default value * @param comment the in-file comment @@ -210,11 +212,11 @@ public class PropertyManager { { addProperty(new DoubleProperty(k, d, comment)); } - - + + /** * Add a numeric property - * + * * @param k key * @param d default value * @param comment the in-file comment @@ -223,11 +225,11 @@ public class PropertyManager { { addProperty(new IntegerProperty(k, d, comment)); } - - + + /** * Add a string property - * + * * @param k key * @param d default value * @param comment the in-file comment @@ -236,22 +238,22 @@ public class PropertyManager { { addProperty(new StringProperty(k, d, comment)); } - - + + /** * Add a generic property (can be used with custom property types) - * + * * @param prop property to add */ public void addProperty(Property prop) { entries.put(prop.getKey(), prop); } - - + + /** * Rename key before loading; value is preserved - * + * * @param oldKey old key * @param newKey new key */ @@ -260,11 +262,11 @@ public class PropertyManager { renameTable.put(oldKey, newKey); return; } - - + + /** * Set value saved to certain key. - * + * * @param key key * @param value the saved value */ @@ -272,16 +274,16 @@ public class PropertyManager { { getProperty(key).setValue(value); } - - + + /** * Set heading comment of the property store. - * + * * @param fileComment comment text (can be multi-line) */ public void setFileComment(String fileComment) { props.setComment(fileComment); } - + } diff --git a/src/mightypork/utils/config/propmgr/PropertyStore.java b/src/mightypork/utils/config/propmgr/PropertyStore.java index be881af..e2cce83 100644 --- a/src/mightypork/utils/config/propmgr/PropertyStore.java +++ b/src/mightypork/utils/config/propmgr/PropertyStore.java @@ -9,70 +9,70 @@ import java.util.Collection; * Interface for a property store (used by {@link PropertyManager}).
* Due to this abstraction, different kind of property storage can be used, not * only a file. - * + * * @author Ondřej Hruška (MightyPork) */ public interface PropertyStore { - + /** * Set a header comment - * + * * @param comment the comment text (can be multi-line) */ void setComment(String comment); - - + + /** * Load properties from the file / store. If the file does not exist or is * inaccessible, nothing is loaded. */ void load(); - - + + /** * Save properties to the file / store. - * + * * @throws IOException if the file cannot be created or written. */ void save() throws IOException; - - + + /** * Get a property value - * + * * @param key property key * @return value retrieved from the file, or null if none found. */ String getProperty(String key); - - + + /** * Set a property value - * + * * @param key property key * @param value property value to set * @param comment property comment. Can be null. */ void setProperty(String key, String value, String comment); - - + + /** * Remove a property from the list. - * + * * @param key property key to remove */ void removeProperty(String key); - - + + /** * Clear the property list */ void clear(); - - + + /** * Get keys collection (can be used for iterating) - * + * * @return keys collection */ public Collection keys(); diff --git a/src/mightypork/utils/config/propmgr/properties/BooleanProperty.java b/src/mightypork/utils/config/propmgr/properties/BooleanProperty.java index 15bf83b..bf3cfd4 100644 --- a/src/mightypork/utils/config/propmgr/properties/BooleanProperty.java +++ b/src/mightypork/utils/config/propmgr/properties/BooleanProperty.java @@ -7,21 +7,23 @@ import mightypork.utils.config.propmgr.Property; /** * Boolean property - * + * * @author Ondřej Hruška (MightyPork) */ public class BooleanProperty extends Property { - - public BooleanProperty(String key, Boolean defaultValue) { + + public BooleanProperty(String key, Boolean defaultValue) + { super(key, defaultValue); } - - - public BooleanProperty(String key, Boolean defaultValue, String comment) { + + + public BooleanProperty(String key, Boolean defaultValue, String comment) + { super(key, defaultValue, comment); } - - + + @Override public void fromString(String string) { diff --git a/src/mightypork/utils/config/propmgr/properties/DoubleProperty.java b/src/mightypork/utils/config/propmgr/properties/DoubleProperty.java index 97f6d66..71d2f71 100644 --- a/src/mightypork/utils/config/propmgr/properties/DoubleProperty.java +++ b/src/mightypork/utils/config/propmgr/properties/DoubleProperty.java @@ -7,21 +7,23 @@ import mightypork.utils.config.propmgr.Property; /** * Double property - * + * * @author Ondřej Hruška (MightyPork) */ public class DoubleProperty extends Property { - - public DoubleProperty(String key, Double defaultValue) { + + public DoubleProperty(String key, Double defaultValue) + { super(key, defaultValue); } - - - public DoubleProperty(String key, Double defaultValue, String comment) { + + + public DoubleProperty(String key, Double defaultValue, String comment) + { super(key, defaultValue, comment); } - - + + @Override public void fromString(String string) { diff --git a/src/mightypork/utils/config/propmgr/properties/IntegerProperty.java b/src/mightypork/utils/config/propmgr/properties/IntegerProperty.java index 6ad0913..fc9fe7e 100644 --- a/src/mightypork/utils/config/propmgr/properties/IntegerProperty.java +++ b/src/mightypork/utils/config/propmgr/properties/IntegerProperty.java @@ -7,21 +7,23 @@ import mightypork.utils.config.propmgr.Property; /** * Integer property - * + * * @author Ondřej Hruška (MightyPork) */ public class IntegerProperty extends Property { - - public IntegerProperty(String key, Integer defaultValue) { + + public IntegerProperty(String key, Integer defaultValue) + { super(key, defaultValue); } - - - public IntegerProperty(String key, Integer defaultValue, String comment) { + + + public IntegerProperty(String key, Integer defaultValue, String comment) + { super(key, defaultValue, comment); } - - + + @Override public void fromString(String string) { diff --git a/src/mightypork/utils/config/propmgr/properties/StringProperty.java b/src/mightypork/utils/config/propmgr/properties/StringProperty.java index 6032ba1..316693c 100644 --- a/src/mightypork/utils/config/propmgr/properties/StringProperty.java +++ b/src/mightypork/utils/config/propmgr/properties/StringProperty.java @@ -7,21 +7,23 @@ import mightypork.utils.config.propmgr.Property; /** * String property - * + * * @author Ondřej Hruška (MightyPork) */ public class StringProperty extends Property { - - public StringProperty(String key, String defaultValue) { + + public StringProperty(String key, String defaultValue) + { super(key, defaultValue); } - - - public StringProperty(String key, String defaultValue, String comment) { + + + public StringProperty(String key, String defaultValue, String comment) + { super(key, defaultValue, comment); } - - + + @Override public void fromString(String string) { diff --git a/src/mightypork/utils/config/propmgr/store/PropertyFile.java b/src/mightypork/utils/config/propmgr/store/PropertyFile.java index 9bc8360..8fcb4e7 100644 --- a/src/mightypork/utils/config/propmgr/store/PropertyFile.java +++ b/src/mightypork/utils/config/propmgr/store/PropertyFile.java @@ -13,50 +13,52 @@ import mightypork.utils.config.propmgr.PropertyStore; /** * File based implementation utilizing {@link java.util.Properties}, hacked to * support UTF-8. - * + * * @author Ondřej Hruška (MightyPork) */ public class PropertyFile implements PropertyStore { - + private String comment; - private File file; - private SortedProperties props; - - - public PropertyFile(File file) { + private final File file; + private final SortedProperties props; + + + public PropertyFile(File file) + { this.file = file; this.comment = null; this.props = new SortedProperties(); } - - - public PropertyFile(File file, String comment) { + + + public PropertyFile(File file, String comment) + { this.file = file; this.comment = comment; this.props = new SortedProperties(); } - - + + @Override public void setComment(String comment) { this.comment = comment; } - - + + @Override public void load() { if (!file.exists()) return; - - try (FileInputStream in = new FileInputStream(file)) { + + try(FileInputStream in = new FileInputStream(file)) { props.load(in); - } catch (IOException e) { + } catch (final IOException e) { // ignore } } - - + + @Override public void save() throws IOException { @@ -65,55 +67,55 @@ public class PropertyFile implements PropertyStore { throw new IOException("Cound not create config file."); } } - - try (FileOutputStream out = new FileOutputStream(file)) { + + try(FileOutputStream out = new FileOutputStream(file)) { props.store(out, comment); } } - - + + @Override public String getProperty(String key) { return props.getProperty(key); } - - + + @Override public void setProperty(String key, String value, String comment) { props.setProperty(key, value); props.setKeyComment(key, comment); } - - + + @Override public void removeProperty(String key) { props.remove(key); } - - + + @Override public void clear() { props.clear(); } - - + + @SuppressWarnings("unchecked") @Override public Collection keys() { - + // Set keys = new HashSet<>(); // for (Object o : props.keySet()) { // keys.add((String) o); // } // return keys; - + // we know it is strings. return (Collection) (Collection) props.keySet(); } - + } diff --git a/src/mightypork/utils/config/propmgr/store/SortedProperties.java b/src/mightypork/utils/config/propmgr/store/SortedProperties.java index bdd085a..093eeb1 100644 --- a/src/mightypork/utils/config/propmgr/store/SortedProperties.java +++ b/src/mightypork/utils/config/propmgr/store/SortedProperties.java @@ -1,7 +1,13 @@ package mightypork.utils.config.propmgr.store; -import java.io.*; +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.util.Collections; import java.util.Enumeration; import java.util.Hashtable; @@ -13,19 +19,19 @@ import java.util.Vector; * Uses UTF-8 encoding and each property can have it's own comment.
* FIXME The quality of this class is dubious. It would probably be a good idea * to rewrite it without using {@link java.util.Properties} at all. - * + * * @author Ondřej Hruška (MightyPork) */ class SortedProperties extends java.util.Properties { - + /** Comments for individual keys */ private final Hashtable keyComments = new Hashtable<>(); - - + + private static void writeComments(BufferedWriter bw, String comm) throws IOException { final String comments = comm.replace("\n\n", "\n \n"); - + final int len = comments.length(); int current = 0; int last = 0; @@ -38,7 +44,7 @@ class SortedProperties extends java.util.Properties { if (last != current) { bw.write("# " + comments.substring(last, current)); } - + if (c > '\u00ff') { uu[2] = hexDigit(c, 12); uu[3] = hexDigit(c, 8); @@ -58,13 +64,13 @@ class SortedProperties extends java.util.Properties { if (last != current) { bw.write("# " + comments.substring(last, current)); } - + bw.newLine(); bw.newLine(); bw.newLine(); } - - + + @SuppressWarnings({ "unchecked", "rawtypes" }) @Override public synchronized Enumeration keys() @@ -77,8 +83,8 @@ class SortedProperties extends java.util.Properties { Collections.sort(keyList); //sort! return keyList.elements(); } - - + + private static String saveConvert(String theString, boolean escapeSpace, boolean escapeUnicode) { final int len = theString.length(); @@ -87,10 +93,10 @@ class SortedProperties extends java.util.Properties { bufLen = Integer.MAX_VALUE; } final StringBuffer result = new StringBuffer(bufLen); - + for (int x = 0; x < len; x++) { final char ch = theString.charAt(x); - + // Handle common case first, selecting largest block that // avoids the specials below if ((ch > 61) && (ch < 127)) { @@ -102,7 +108,7 @@ class SortedProperties extends java.util.Properties { result.append(ch); continue; } - + switch (ch) { case ' ': if (x == 0 || escapeSpace) { @@ -110,27 +116,27 @@ class SortedProperties extends java.util.Properties { } result.append(' '); break; - + case '\t': result.append('\\'); result.append('t'); break; - + case '\n': result.append('\\'); result.append('n'); break; - + case '\r': result.append('\\'); result.append('r'); break; - + case '\f': result.append('\\'); result.append('f'); break; - + case '=': // Fall through case ':': // Fall through case '#': // Fall through @@ -138,7 +144,7 @@ class SortedProperties extends java.util.Properties { result.append('\\'); result.append(ch); break; - + default: if (((ch < 0x0020) || (ch > 0x007e)) & escapeUnicode) { result.append('\\'); @@ -152,14 +158,14 @@ class SortedProperties extends java.util.Properties { } } } - + return result.toString(); } - - + + /** * Set additional comment to a key - * + * * @param key key for comment * @param comment the comment */ @@ -167,75 +173,75 @@ class SortedProperties extends java.util.Properties { { keyComments.put(key, comment); } - - + + @SuppressWarnings("rawtypes") @Override public void store(OutputStream out, String comments) throws IOException { final BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out, "UTF-8")); - + final boolean escUnicode = false; boolean firstEntry = true; String lastSectionBeginning = ""; - + if (comments != null) { writeComments(bw, comments); } - + synchronized (this) { for (final Enumeration e = keys(); e.hasMoreElements();) { boolean wasNewLine = false; - + String key = (String) e.nextElement(); String val = (String) get(key); key = saveConvert(key, true, escUnicode); val = saveConvert(val, false, escUnicode); - + // separate sections if (!lastSectionBeginning.equals(key.split("[.]")[0])) { if (!firstEntry) { bw.newLine(); bw.newLine(); } - + wasNewLine = true; lastSectionBeginning = key.split("[.]")[0]; } - + if (keyComments.containsKey(key)) { String cm = keyComments.get(key); cm = cm.replace("\r", "\n"); cm = cm.replace("\r\n", "\n"); cm = cm.replace("\n\n", "\n \n"); - + final String[] cmlines = cm.split("\n"); - + // newline before comments if (!wasNewLine && !firstEntry) { bw.newLine(); } - + for (final String cmline : cmlines) { bw.write("# " + cmline); bw.newLine(); } } - + bw.write(key + " = " + val); bw.newLine(); - + firstEntry = false; } } bw.flush(); } - - + + private static String escapifyStr(String str) { final StringBuilder result = new StringBuilder(); - + final int len = str.length(); for (int x = 0; x < len; x++) { final char ch = str.charAt(x); @@ -243,7 +249,7 @@ class SortedProperties extends java.util.Properties { result.append(ch); continue; } - + result.append('\\'); result.append('u'); result.append(hexDigit(ch, 12)); @@ -253,26 +259,26 @@ class SortedProperties extends java.util.Properties { } return result.toString(); } - - + + private static char hexDigit(char ch, int offset) { final int val = (ch >> offset) & 0xF; if (val <= 9) { return (char) ('0' + val); } - + return (char) ('A' + val - 10); } - - + + @Override public synchronized void load(InputStream is) throws IOException { load(is, "utf-8"); } - - + + public void load(InputStream is, String encoding) throws IOException { final StringBuilder sb = new StringBuilder(); @@ -282,18 +288,18 @@ class SortedProperties extends java.util.Properties { if (temp < 0) { break; } - + final char c = (char) temp; sb.append(c); } - + // discard comments final String read = sb.toString().replaceAll("(#|;|//|--)[^\n]*\n", "\n"); - + final String inputString = escapifyStr(read); final byte[] bs = inputString.getBytes("ISO-8859-1"); final ByteArrayInputStream bais = new ByteArrayInputStream(bs); - + super.load(bais); } } diff --git a/src/mightypork/utils/eventbus/BusEvent.java b/src/mightypork/utils/eventbus/BusEvent.java index 4ccf5f1..aba4f5e 100644 --- a/src/mightypork/utils/eventbus/BusEvent.java +++ b/src/mightypork/utils/eventbus/BusEvent.java @@ -26,73 +26,73 @@ import mightypork.utils.eventbus.events.flags.SingleReceiverEvent; * Default sending mode (if not changed by annotations) is queued with * zero delay. *

- * + * * @author Ondřej Hruška (MightyPork) * @param handler type */ public abstract class BusEvent { - + private boolean consumed; private boolean served; - - + + /** * Ask handler to handle this message. - * + * * @param handler handler instance */ protected abstract void handleBy(HANDLER handler); - - + + /** * Consume the event, so no other clients will receive it. - * + * * @throws UnsupportedOperationException if the {@link NonConsumableEvent} * annotation is present. */ public final void consume() { if (consumed) throw new IllegalStateException("Already consumed."); - + if (getClass().isAnnotationPresent(NonConsumableEvent.class)) { throw new UnsupportedOperationException("Not consumable."); } - + consumed = true; } - - + + /** * Deliver to a handler using the handleBy method. - * + * * @param handler handler instance */ final void deliverTo(HANDLER handler) { handleBy(handler); - + if (!served) { if (getClass().isAnnotationPresent(SingleReceiverEvent.class)) { consumed = true; } - + served = true; } } - - + + /** * Check if the event is consumed. When an event is consumed, no other * clients will receive it. - * + * * @return true if consumed */ public final boolean isConsumed() { return consumed; } - - + + /** * @return true if the event was served to at least 1 client */ @@ -100,8 +100,8 @@ public abstract class BusEvent { { return served; } - - + + /** * Clear "served" and "consumed" flags before dispatching. */ @@ -110,11 +110,11 @@ public abstract class BusEvent { served = false; consumed = false; } - - + + /** * Called after all clients have received the event. - * + * * @param bus event bus instance */ public void onDispatchComplete(EventBus bus) diff --git a/src/mightypork/utils/eventbus/EventBus.java b/src/mightypork/utils/eventbus/EventBus.java index 53a5ca1..366d3fa 100644 --- a/src/mightypork/utils/eventbus/EventBus.java +++ b/src/mightypork/utils/eventbus/EventBus.java @@ -22,75 +22,77 @@ import mightypork.utils.logging.Log; /** * An event bus, accommodating multiple EventChannels.
* Channel will be created when an event of type is first encountered. - * + * * @author Ondřej Hruška (MightyPork) */ final public class EventBus implements Destroyable { - + /** * Queued event holder */ private class DelayQueueEntry implements Delayed { - + private final long due; private final BusEvent evt; - - - public DelayQueueEntry(double seconds, BusEvent event) { + + + public DelayQueueEntry(double seconds, BusEvent event) + { super(); this.due = System.currentTimeMillis() + (long) (seconds * 1000); this.evt = event; } - - + + @Override public int compareTo(Delayed o) { return Long.valueOf(getDelay(TimeUnit.MILLISECONDS)).compareTo(o.getDelay(TimeUnit.MILLISECONDS)); } - - + + @Override public long getDelay(TimeUnit unit) { return unit.convert(due - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } - - + + public BusEvent getEvent() { return evt; } - + } - + /** * Thread handling queued events */ private class QueuePollingThread extends Thread { - + public volatile boolean stopped = false; - - - public QueuePollingThread() { + + + public QueuePollingThread() + { super("Queue Polling Thread"); } - - + + @Override public void run() { DelayQueueEntry evt; - + while (!stopped) { evt = null; - + try { evt = sendQueue.take(); } catch (final InterruptedException ignored) { // } - + if (evt != null) { try { dispatch(evt.getEvent()); @@ -100,46 +102,47 @@ final public class EventBus implements Destroyable { } } } - + } - + static final String logMark = "(bus) "; - - + + private static Class getEventListenerClass(BusEvent event) { return Reflect.getGenericParameters(event.getClass())[0]; } - + /** Log detailed messages (debug) */ public boolean detailedLogging = false; - + /** Queue polling thread */ private final QueuePollingThread busThread; - + /** Registered clients */ private final Set clients = Collections.newSetFromMap(new ConcurrentHashMap()); - + /** Whether the bus was destroyed */ private boolean dead = false; - + /** Message channels */ private final Set> channels = Collections.newSetFromMap(new ConcurrentHashMap, Boolean>()); - + /** Messages queued for delivery */ private final DelayQueue sendQueue = new DelayQueue<>(); - - + + /** * Make a new bus and start it's queue thread. */ - public EventBus() { + public EventBus() + { busThread = new QueuePollingThread(); busThread.setDaemon(true); busThread.start(); } - - + + /** * Halt bus thread and reject any future events. */ @@ -147,129 +150,129 @@ final public class EventBus implements Destroyable { public void destroy() { assertLive(); - + busThread.stopped = true; dead = true; } - - + + /** * Send based on annotation - * + * * @param event event */ public void send(BusEvent event) { assertLive(); - + final DelayedEvent adelay = Reflect.getAnnotation(event, DelayedEvent.class); if (adelay != null) { sendDelayed(event, adelay.delay()); return; } - + if (Reflect.hasAnnotation(event, DirectEvent.class)) { sendDirect(event); return; } - + sendQueued(event); } - - + + /** * Add event to a queue - * + * * @param event event */ public void sendQueued(BusEvent event) { assertLive(); - + sendDelayed(event, 0); } - - + + /** * Add event to a queue, scheduled for given time. - * + * * @param event event * @param delay delay before event is dispatched */ public void sendDelayed(BusEvent event, double delay) { assertLive(); - + final DelayQueueEntry dm = new DelayQueueEntry(delay, event); - + if (shallLog(event)) { Log.f3(logMark + "Qu [" + Support.str(event) + "]" + (delay == 0 ? "" : (", delay: " + delay + "s"))); } - + sendQueue.add(dm); } - - + + /** * Send immediately.
* Should be used for real-time events that require immediate response, such * as timing events. - * + * * @param event event */ public void sendDirect(BusEvent event) { assertLive(); - + if (shallLog(event)) Log.f3(logMark + "Di [" + Support.str(event) + "]"); - + dispatch(event); } - - + + public void sendDirectToChildren(DelegatingClient delegatingClient, BusEvent event) { assertLive(); - + if (shallLog(event)) Log.f3(logMark + "Di->sub [" + Support.str(event) + "]"); - + doDispatch(delegatingClient.getChildClients(), event); } - - + + /** * Connect a client to the bus. The client will be connected to all current * and future channels, until removed from the bus. - * + * * @param client the client */ public void subscribe(Object client) { assertLive(); - + if (client == null) return; - + clients.add(client); - + if (detailedLogging) Log.f3(logMark + "Client joined: " + Support.str(client)); } - - + + /** * Disconnect a client from the bus. - * + * * @param client the client */ public void unsubscribe(Object client) { assertLive(); - + clients.remove(client); - + if (detailedLogging) Log.f3(logMark + "Client left: " + Support.str(client)); } - - + + @SuppressWarnings("unchecked") private boolean addChannelForEvent(BusEvent event) { @@ -277,99 +280,99 @@ final public class EventBus implements Destroyable { if (detailedLogging) { Log.f3(logMark + "Setting up channel for new event type: " + Support.str(event.getClass())); } - + final Class listener = getEventListenerClass(event); final EventChannel ch = EventChannel.create(event.getClass(), listener); - + if (ch.canBroadcast(event)) { - + channels.add(ch); //channels.flush(); - + if (detailedLogging) { Log.f3(logMark + "Created new channel: " + Support.str(event.getClass()) + " -> " + Support.str(listener)); } - + return true; - + } else { Log.w(logMark + "Could not create channel for event " + Support.str(event.getClass())); } - + } catch (final Throwable t) { Log.w(logMark + "Error while trying to add channel for event.", t); } - + return false; } - - + + /** * Make sure the bus is not destroyed. - * + * * @throws IllegalStateException if the bus is dead. */ private void assertLive() throws IllegalStateException { if (dead) throw new IllegalStateException("EventBus is dead."); } - - + + /** * Send immediately.
* Should be used for real-time events that require immediate response, such * as timing events. - * + * * @param event event */ private synchronized void dispatch(BusEvent event) { assertLive(); - + doDispatch(clients, event); event.onDispatchComplete(this); } - - + + /** * Send to a set of clients - * + * * @param clients clients * @param event event */ private synchronized void doDispatch(Collection clients, BusEvent event) { boolean accepted = false; - + event.clearFlags(); - + for (int i = 0; i < 2; i++) { // two tries. - + for (final EventChannel b : channels) { if (b.canBroadcast(event)) { accepted = true; b.broadcast(event, clients); } - + if (event.isConsumed()) break; } - + if (!accepted) if (addChannelForEvent(event)) continue; - + break; } - + if (!accepted) Log.e(logMark + "Not accepted by any channel: " + Support.str(event)); if (!event.wasServed() && shallLog(event)) Log.w(logMark + "Not delivered: " + Support.str(event)); } - - + + private boolean shallLog(BusEvent event) { if (!detailedLogging) return false; if (Reflect.hasAnnotation(event, NotLoggedEvent.class)) return false; - + return true; } - + } diff --git a/src/mightypork/utils/eventbus/EventChannel.java b/src/mightypork/utils/eventbus/EventChannel.java index 911615f..b16016b 100644 --- a/src/mightypork/utils/eventbus/EventChannel.java +++ b/src/mightypork/utils/eventbus/EventChannel.java @@ -14,52 +14,53 @@ import mightypork.utils.logging.Log; /** * Event delivery channel, module of {@link EventBus} - * + * * @author Ondřej Hruška (MightyPork) * @param event type * @param client (subscriber) type */ class EventChannel, CLIENT> { - + private final Class clientClass; private final Class eventClass; - - + + /** * Create a channel - * + * * @param eventClass event class * @param clientClass client class */ - public EventChannel(Class eventClass, Class clientClass) { - + public EventChannel(Class eventClass, Class clientClass) + { + if (eventClass == null || clientClass == null) { throw new NullPointerException("Null Event or Client class."); } - + this.clientClass = clientClass; this.eventClass = eventClass; } - - + + /** * Try to broadcast a event.
* If event is of wrong type, false is returned. - * + * * @param event a event to be sent * @param clients collection of clients */ public void broadcast(BusEvent event, Collection clients) { if (!canBroadcast(event)) return; - + doBroadcast(eventClass.cast(event), clients, new HashSet<>()); } - - + + /** * Send the event - * + * * @param event sent event * @param clients subscribing clients * @param processed clients already processed @@ -67,49 +68,49 @@ class EventChannel, CLIENT> { private void doBroadcast(final EVENT event, final Collection clients, final Collection processed) { for (final Object client : clients) { - + // exclude obvious non-clients if (!isClientValid(client)) { continue; } - + // avoid executing more times if (processed.contains(client)) { Log.w(EventBus.logMark + "Client already served: " + Support.str(client)); continue; } processed.add(client); - + final boolean must_deliver = Reflect.hasAnnotation(event, NonRejectableEvent.class); - + // opt-out if (client instanceof ToggleableClient) { if (!must_deliver && !((ToggleableClient) client).isListening()) continue; } - + sendTo(client, event); - + if (event.isConsumed()) return; - + // pass on to delegated clients if (client instanceof DelegatingClient) { if (must_deliver || ((DelegatingClient) client).doesDelegate()) { - + final Collection children = ((DelegatingClient) client).getChildClients(); - + if (children != null && children.size() > 0) { doBroadcast(event, children, processed); } - + } } } } - - + + /** * Send an event to a client. - * + * * @param client target client * @param event event to send */ @@ -120,11 +121,11 @@ class EventChannel, CLIENT> { ((BusEvent) event).deliverTo((CLIENT) client); } } - - + + /** * Check if the given event can be broadcasted by this channel - * + * * @param event event object * @return can be broadcasted */ @@ -132,11 +133,11 @@ class EventChannel, CLIENT> { { return event != null && eventClass.isInstance(event); } - - + + /** * Create an instance for given types - * + * * @param eventClass event class * @param clientClass client class * @return the broadcaster @@ -145,11 +146,11 @@ class EventChannel, CLIENT> { { return new EventChannel<>(eventClass, clientClass); } - - + + /** * Check if client is of channel type - * + * * @param client client * @return is of type */ @@ -157,11 +158,11 @@ class EventChannel, CLIENT> { { return clientClass.isInstance(client); } - - + + /** * Check if the channel is compatible with given - * + * * @param client client * @return is supported */ @@ -169,8 +170,8 @@ class EventChannel, CLIENT> { { return isClientOfChannelType(client) || (client instanceof DelegatingClient); } - - + + @Override public int hashCode() { @@ -180,8 +181,8 @@ class EventChannel, CLIENT> { result = prime * result + ((eventClass == null) ? 0 : eventClass.hashCode()); return result; } - - + + @Override public boolean equals(Object obj) { @@ -197,8 +198,8 @@ class EventChannel, CLIENT> { } else if (!eventClass.equals(other.eventClass)) return false; return true; } - - + + @Override public String toString() { diff --git a/src/mightypork/utils/eventbus/clients/BusNode.java b/src/mightypork/utils/eventbus/clients/BusNode.java index 6ebf8ce..0e9eae5 100644 --- a/src/mightypork/utils/eventbus/clients/BusNode.java +++ b/src/mightypork/utils/eventbus/clients/BusNode.java @@ -11,40 +11,40 @@ import mightypork.utils.eventbus.EventBus; /** * Client that can be attached to the {@link EventBus}, or added as a child * client to another {@link DelegatingClient} - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class BusNode implements ClientHub { - + private final Set clients = new LinkedHashSet<>(); private boolean listening = true; private boolean delegating = true; - - + + @Override public Collection getChildClients() { return clients; } - - + + @Override public boolean doesDelegate() { return delegating; } - - + + @Override public boolean isListening() { return listening; } - - + + /** * Add a child subscriber to the {@link EventBus}.
- * + * * @param client */ @Override @@ -52,11 +52,11 @@ public abstract class BusNode implements ClientHub { { clients.add(client); } - - + + /** * Remove a child subscriber - * + * * @param client subscriber to remove */ @Override @@ -66,22 +66,22 @@ public abstract class BusNode implements ClientHub { clients.remove(client); } } - - + + /** * Set whether events should be received. - * + * * @param listening receive events */ public void setListening(boolean listening) { this.listening = listening; } - - + + /** * Set whether events should be passed on to child nodes - * + * * @param delegating */ public void setDelegating(boolean delegating) diff --git a/src/mightypork/utils/eventbus/clients/ClientHub.java b/src/mightypork/utils/eventbus/clients/ClientHub.java index 81011c3..14f2be3 100644 --- a/src/mightypork/utils/eventbus/clients/ClientHub.java +++ b/src/mightypork/utils/eventbus/clients/ClientHub.java @@ -8,34 +8,34 @@ import mightypork.utils.eventbus.EventBus; /** * Common methods for client hubs (ie delegating vlient implementations) - * + * * @author Ondřej Hruška (MightyPork) */ public interface ClientHub extends DelegatingClient, ToggleableClient { - + @Override public boolean doesDelegate(); - - + + @Override public Collection getChildClients(); - - + + @Override public boolean isListening(); - - + + /** * Add a child subscriber to the {@link EventBus}.
- * + * * @param client */ public void addChildClient(Object client); - - + + /** * Remove a child subscriber - * + * * @param client subscriber to remove */ void removeChildClient(Object client); diff --git a/src/mightypork/utils/eventbus/clients/ClientList.java b/src/mightypork/utils/eventbus/clients/ClientList.java index f0bdae5..e4a873d 100644 --- a/src/mightypork/utils/eventbus/clients/ClientList.java +++ b/src/mightypork/utils/eventbus/clients/ClientList.java @@ -7,12 +7,13 @@ import java.util.ArrayList; /** * Array-list with varargs constructor, intended to wrap fre clients for * delegating client. - * + * * @author Ondřej Hruška (MightyPork) */ public class ClientList extends ArrayList { - - public ClientList(Object... clients) { + + public ClientList(Object... clients) + { for (final Object c : clients) { super.add(c); } diff --git a/src/mightypork/utils/eventbus/clients/DelegatingClient.java b/src/mightypork/utils/eventbus/clients/DelegatingClient.java index 5d202d3..2fad9fb 100644 --- a/src/mightypork/utils/eventbus/clients/DelegatingClient.java +++ b/src/mightypork/utils/eventbus/clients/DelegatingClient.java @@ -8,20 +8,20 @@ import java.util.Collection; * Client containing child clients. According to the contract, if the collection * of clients is ordered, the clients will be served in that order. In any case, * the {@link DelegatingClient} itself will be served beforehand. - * + * * @author Ondřej Hruška (MightyPork) */ public interface DelegatingClient { - + /** * @return collection of child clients. Can not be null. */ public Collection getChildClients(); - - + + /** * @return true if delegating is active */ public boolean doesDelegate(); - + } diff --git a/src/mightypork/utils/eventbus/clients/DelegatingList.java b/src/mightypork/utils/eventbus/clients/DelegatingList.java index 29b94ff..4c2029d 100644 --- a/src/mightypork/utils/eventbus/clients/DelegatingList.java +++ b/src/mightypork/utils/eventbus/clients/DelegatingList.java @@ -8,59 +8,61 @@ import mightypork.utils.interfaces.Enableable; /** * List of clients, that can be used as a delegating client. - * + * * @author Ondřej Hruška (MightyPork) */ public class DelegatingList extends ClientList implements DelegatingClient, Enableable, ToggleableClient { - + private boolean enabled = true; - - + + /** * Delegating list with initial clients - * + * * @param clients initial list members (clients) */ - public DelegatingList(Object... clients) { + public DelegatingList(Object... clients) + { super(clients); } - - + + /** * Empty delegating list. */ - public DelegatingList() { + public DelegatingList() + { } - - + + @Override public Collection getChildClients() { return this; } - - + + @Override public boolean doesDelegate() { return isEnabled(); } - - + + @Override public boolean isListening() { return isEnabled(); } - - + + @Override public void setEnabled(boolean yes) { enabled = yes; } - - + + @Override public boolean isEnabled() { diff --git a/src/mightypork/utils/eventbus/clients/ToggleableClient.java b/src/mightypork/utils/eventbus/clients/ToggleableClient.java index 52b0d41..98eee44 100644 --- a/src/mightypork/utils/eventbus/clients/ToggleableClient.java +++ b/src/mightypork/utils/eventbus/clients/ToggleableClient.java @@ -3,14 +3,14 @@ package mightypork.utils.eventbus.clients; /** * Client that can toggle receiving messages. - * + * * @author Ondřej Hruška (MightyPork) */ public interface ToggleableClient { - + /** * @return true if the client wants to receive messages */ public boolean isListening(); - + } diff --git a/src/mightypork/utils/eventbus/events/DestroyEvent.java b/src/mightypork/utils/eventbus/events/DestroyEvent.java index d07fe96..ceb345f 100644 --- a/src/mightypork/utils/eventbus/events/DestroyEvent.java +++ b/src/mightypork/utils/eventbus/events/DestroyEvent.java @@ -9,17 +9,17 @@ import mightypork.utils.interfaces.Destroyable; /** * Invoke destroy() method of all subscribers. Used to deinit a system. - * + * * @author Ondřej Hruška (MightyPork) */ @DirectEvent @NonConsumableEvent public class DestroyEvent extends BusEvent { - + @Override public void handleBy(Destroyable handler) { handler.destroy(); } - + } diff --git a/src/mightypork/utils/eventbus/events/UpdateEvent.java b/src/mightypork/utils/eventbus/events/UpdateEvent.java index d053f64..dfd78c6 100644 --- a/src/mightypork/utils/eventbus/events/UpdateEvent.java +++ b/src/mightypork/utils/eventbus/events/UpdateEvent.java @@ -10,25 +10,26 @@ import mightypork.utils.interfaces.Updateable; /** * Delta timing update event. Not logged. - * + * * @author Ondřej Hruška (MightyPork) */ @NotLoggedEvent @DirectEvent @NonConsumableEvent public class UpdateEvent extends BusEvent { - + private final double deltaTime; - - + + /** * @param deltaTime time since last update (sec) */ - public UpdateEvent(double deltaTime) { + public UpdateEvent(double deltaTime) + { this.deltaTime = deltaTime; } - - + + @Override public void handleBy(Updateable handler) { diff --git a/src/mightypork/utils/eventbus/events/flags/DelayedEvent.java b/src/mightypork/utils/eventbus/events/flags/DelayedEvent.java index 11bf9d0..39340f2 100644 --- a/src/mightypork/utils/eventbus/events/flags/DelayedEvent.java +++ b/src/mightypork/utils/eventbus/events/flags/DelayedEvent.java @@ -1,12 +1,17 @@ package mightypork.utils.eventbus.events.flags; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Event that should be queued with given delay (default: 0); - * + * * @author Ondřej Hruška (MightyPork) */ @Retention(RetentionPolicy.RUNTIME) @@ -14,7 +19,7 @@ import java.lang.annotation.*; @Inherited @Documented public @interface DelayedEvent { - + /** * @return event dispatch delay [seconds] */ diff --git a/src/mightypork/utils/eventbus/events/flags/DirectEvent.java b/src/mightypork/utils/eventbus/events/flags/DirectEvent.java index fdfd138..d7ae285 100644 --- a/src/mightypork/utils/eventbus/events/flags/DirectEvent.java +++ b/src/mightypork/utils/eventbus/events/flags/DirectEvent.java @@ -1,12 +1,17 @@ package mightypork.utils.eventbus.events.flags; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Event that should not be queued. - * + * * @author Ondřej Hruška (MightyPork) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/src/mightypork/utils/eventbus/events/flags/NonConsumableEvent.java b/src/mightypork/utils/eventbus/events/flags/NonConsumableEvent.java index 873afdc..c6257ed 100644 --- a/src/mightypork/utils/eventbus/events/flags/NonConsumableEvent.java +++ b/src/mightypork/utils/eventbus/events/flags/NonConsumableEvent.java @@ -10,12 +10,12 @@ import java.lang.annotation.Target; /** * Event that cannot be consumed - * + * * @author Ondřej Hruška (MightyPork) */ @Retention(RetentionPolicy.RUNTIME) @Documented @Target(ElementType.TYPE) public @interface NonConsumableEvent { - + } diff --git a/src/mightypork/utils/eventbus/events/flags/NonRejectableEvent.java b/src/mightypork/utils/eventbus/events/flags/NonRejectableEvent.java index 164bf4a..d152a00 100644 --- a/src/mightypork/utils/eventbus/events/flags/NonRejectableEvent.java +++ b/src/mightypork/utils/eventbus/events/flags/NonRejectableEvent.java @@ -10,12 +10,12 @@ import java.lang.annotation.Target; /** * Event that is forcibly delivered to all clients (bypass Toggleable etc) - * + * * @author Ondřej Hruška (MightyPork) */ @Retention(RetentionPolicy.RUNTIME) @Documented @Target(ElementType.TYPE) public @interface NonRejectableEvent { - + } diff --git a/src/mightypork/utils/eventbus/events/flags/NotLoggedEvent.java b/src/mightypork/utils/eventbus/events/flags/NotLoggedEvent.java index aad9872..b7d9005 100644 --- a/src/mightypork/utils/eventbus/events/flags/NotLoggedEvent.java +++ b/src/mightypork/utils/eventbus/events/flags/NotLoggedEvent.java @@ -1,13 +1,18 @@ package mightypork.utils.eventbus.events.flags; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Event that's not worth logging, unless there was an error with it.
* Useful for common events that would otherwise clutter the log. - * + * * @author Ondřej Hruška (MightyPork) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/src/mightypork/utils/eventbus/events/flags/SingleReceiverEvent.java b/src/mightypork/utils/eventbus/events/flags/SingleReceiverEvent.java index a166ef2..405e03e 100644 --- a/src/mightypork/utils/eventbus/events/flags/SingleReceiverEvent.java +++ b/src/mightypork/utils/eventbus/events/flags/SingleReceiverEvent.java @@ -1,12 +1,17 @@ package mightypork.utils.eventbus.events.flags; -import java.lang.annotation.*; +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * Handled only by the first client, then discarded. - * + * * @author Ondřej Hruška (MightyPork) */ @Retention(RetentionPolicy.RUNTIME) diff --git a/src/mightypork/utils/exceptions/CorruptDataException.java b/src/mightypork/utils/exceptions/CorruptDataException.java index 9b43778..65aca35 100644 --- a/src/mightypork/utils/exceptions/CorruptDataException.java +++ b/src/mightypork/utils/exceptions/CorruptDataException.java @@ -6,28 +6,32 @@ import java.io.IOException; /** * Thrown when data could not be read successfully. - * + * * @author Ondřej Hruška (MightyPork) */ public class CorruptDataException extends IOException { - - public CorruptDataException() { + + public CorruptDataException() + { super(); } - - - public CorruptDataException(String message, Throwable cause) { + + + public CorruptDataException(String message, Throwable cause) + { super(message, cause); } - - - public CorruptDataException(String message) { + + + public CorruptDataException(String message) + { super(message); } - - - public CorruptDataException(Throwable cause) { + + + public CorruptDataException(Throwable cause) + { super(cause); } - + } diff --git a/src/mightypork/utils/exceptions/IllegalValueException.java b/src/mightypork/utils/exceptions/IllegalValueException.java index f7c1f48..40fdeb4 100644 --- a/src/mightypork/utils/exceptions/IllegalValueException.java +++ b/src/mightypork/utils/exceptions/IllegalValueException.java @@ -4,27 +4,31 @@ package mightypork.utils.exceptions; /** * Thrown when a invalid value is given to a method, or found in a data object / * file etc - * + * * @author Ondřej Hruška (MightyPork) */ public class IllegalValueException extends RuntimeException { - - public IllegalValueException() { + + public IllegalValueException() + { } - - - public IllegalValueException(String message) { + + + public IllegalValueException(String message) + { super(message); } - - - public IllegalValueException(Throwable cause) { + + + public IllegalValueException(Throwable cause) + { super(cause); } - - - public IllegalValueException(String message, Throwable cause) { + + + public IllegalValueException(String message, Throwable cause) + { super(message, cause); } - + } diff --git a/src/mightypork/utils/exceptions/KeyAlreadyExistsException.java b/src/mightypork/utils/exceptions/KeyAlreadyExistsException.java index 8e73c7f..a72b864 100644 --- a/src/mightypork/utils/exceptions/KeyAlreadyExistsException.java +++ b/src/mightypork/utils/exceptions/KeyAlreadyExistsException.java @@ -3,28 +3,32 @@ package mightypork.utils.exceptions; /** * Thrown by a map-like class when the key specified is already taken. - * + * * @author Ondřej Hruška (MightyPork) */ public class KeyAlreadyExistsException extends RuntimeException { - - public KeyAlreadyExistsException() { + + public KeyAlreadyExistsException() + { super(); } - - - public KeyAlreadyExistsException(String message, Throwable cause) { + + + public KeyAlreadyExistsException(String message, Throwable cause) + { super(message, cause); } - - - public KeyAlreadyExistsException(String message) { + + + public KeyAlreadyExistsException(String message) + { super(message); } - - - public KeyAlreadyExistsException(Throwable cause) { + + + public KeyAlreadyExistsException(Throwable cause) + { super(cause); } - + } diff --git a/src/mightypork/utils/files/FileSuffixFilter.java b/src/mightypork/utils/files/FileSuffixFilter.java index ee0f87c..cc37235 100644 --- a/src/mightypork/utils/files/FileSuffixFilter.java +++ b/src/mightypork/utils/files/FileSuffixFilter.java @@ -7,39 +7,40 @@ import java.io.FileFilter; /** * File filter for certain suffixes - * + * * @author Ondřej Hruška (MightyPork) */ public class FileSuffixFilter implements FileFilter { - + /** Array of allowed suffixes */ private String[] suffixes = null; - - + + /** * Suffix filter - * + * * @param suffixes var-args allowed suffixes, case insensitive */ - public FileSuffixFilter(String... suffixes) { + public FileSuffixFilter(String... suffixes) + { this.suffixes = suffixes; } - - + + @Override public boolean accept(File pathname) { if (!pathname.isFile()) return false; - + final String fname = pathname.getName().toLowerCase().trim(); - + for (final String suffix : suffixes) { if (fname.endsWith(suffix.toLowerCase().trim())) { return true; } } - + return false; } - + } diff --git a/src/mightypork/utils/files/FileTreeDiff.java b/src/mightypork/utils/files/FileTreeDiff.java index 6573e1d..19efc70 100644 --- a/src/mightypork/utils/files/FileTreeDiff.java +++ b/src/mightypork/utils/files/FileTreeDiff.java @@ -16,134 +16,138 @@ import mightypork.utils.logging.Log; public class FileTreeDiff { - + private static final byte[] BUFFER = new byte[2048]; private final Checksum ck1 = new Adler32(); private final Checksum ck2 = new Adler32(); - + private boolean logging = true; - + private final List> compared = new ArrayList<>(); private final Comparator fileFirstSorter = new Comparator() { - + @Override public int compare(File o1, File o2) { if (!o1.isDirectory() && o2.isDirectory()) return -1; if (o1.isDirectory() && !o2.isDirectory()) return 1; - + return o1.getName().compareTo(o2.getName()); } }; - - + + public void enableLogging(boolean state) { logging = state; } - - + + public boolean areEqual(File dir1, File dir2) { if (logging) Log.f3("Comparing directory trees:\n 1. " + dir1 + "\n 2. " + dir2); - + try { compared.clear(); buildList(dir1, dir2); - + calcChecksum(); - + if (logging) Log.f3("No difference found."); - + return true; - + } catch (final NotEqualException e) { if (logging) Log.f3("Difference found:\n" + e.getMessage()); - + return false; } } - - + + private void calcChecksum() throws NotEqualException { - + for (final Tuple pair : compared) { ck1.reset(); ck2.reset(); - - try (FileInputStream in1 = new FileInputStream(pair.a); FileInputStream in2 = new FileInputStream(pair.b)) { - - try (CheckedInputStream cin1 = new CheckedInputStream(in1, ck1); CheckedInputStream cin2 = new CheckedInputStream(in2, ck2)) { - + + try(FileInputStream in1 = new FileInputStream(pair.a); + FileInputStream in2 = new FileInputStream(pair.b)) { + + try(CheckedInputStream cin1 = new CheckedInputStream(in1, ck1); + CheckedInputStream cin2 = new CheckedInputStream(in2, ck2)) { + while (true) { final int read1 = cin1.read(BUFFER); final int read2 = cin2.read(BUFFER); - + if (read1 != read2 || ck1.getValue() != ck2.getValue()) { throw new NotEqualException("Bytes differ:\n" + pair.a + "\n" + pair.b); } - + if (read1 == -1) break; } } - + } catch (final IOException e) { // ignore } } } - - + + private void buildList(File f1, File f2) throws NotEqualException { if (f1.isDirectory() != f2.isDirectory()) throw new NotEqualException("isDirectory differs:\n" + f1 + "\n" + f2); - + if (f1.isFile() && f2.isFile()) { if (f1.length() != f2.length()) throw new NotEqualException("Sizes differ:\n" + f1 + "\n" + f2); } - + if (f1.isDirectory()) { final File[] children1 = f1.listFiles(); final File[] children2 = f2.listFiles(); - + Arrays.sort(children1, fileFirstSorter); Arrays.sort(children2, fileFirstSorter); - + if (children1.length != children2.length) throw new NotEqualException("Child counts differ:\n" + f1 + "\n" + f2); - + for (int i = 0; i < children1.length; i++) { final File ch1 = children1[i]; final File ch2 = children2[i]; - + if (!ch1.getName().equals(ch2.getName())) throw new NotEqualException("Filenames differ:\n" + ch1 + "\n" + ch2); - + buildList(ch1, ch2); } - + } else { compared.add(new Tuple<>(f1, f2)); } } - + private class NotEqualException extends Exception { - - public NotEqualException(String msg) { + + public NotEqualException(String msg) + { super(msg); } - + } - + private class Tuple { - + public T a; public T b; - - - public Tuple(T a, T b) { + + + public Tuple(T a, T b) + { this.a = a; this.b = b; } } - + } diff --git a/src/mightypork/utils/files/FileUtil.java b/src/mightypork/utils/files/FileUtil.java index e8e9c3c..e8b2acc 100644 --- a/src/mightypork/utils/files/FileUtil.java +++ b/src/mightypork/utils/files/FileUtil.java @@ -1,7 +1,19 @@ package mightypork.utils.files; -import java.io.*; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; @@ -12,9 +24,10 @@ import mightypork.utils.string.validation.StringFilter; public class FileUtil { + /** * Copy directory recursively. - * + * * @param source source file * @param target target file * @throws IOException on error @@ -27,7 +40,7 @@ public class FileUtil { /** * Copy directory recursively - advanced variant. - * + * * @param source source file * @param target target file * @param filter filter accepting only files and dirs to be copied @@ -61,7 +74,7 @@ public class FileUtil { /** * List directory recursively - * + * * @param source source file * @param filter filter accepting only files and dirs to be copied (or null) * @param files list of the found files @@ -87,7 +100,7 @@ public class FileUtil { /** * Copy file using streams. Make sure target directory exists! - * + * * @param source source file * @param target target file * @throws IOException on error @@ -95,7 +108,8 @@ public class FileUtil { public static void copyFile(File source, File target) throws IOException { - try (InputStream in = new FileInputStream(source); OutputStream out = new FileOutputStream(target)) { + try(InputStream in = new FileInputStream(source); + OutputStream out = new FileOutputStream(target)) { copyStream(in, out); } @@ -104,7 +118,7 @@ public class FileUtil { /** * Copy bytes from input to output stream, leaving out stream open - * + * * @param in input stream * @param out output stream * @throws IOException on error @@ -129,7 +143,7 @@ public class FileUtil { /** * Improved delete - * + * * @param path deleted path * @param recursive recursive delete * @return success @@ -153,14 +167,14 @@ public class FileUtil { /** * Read entire file to a string. - * + * * @param file file * @return file contents * @throws IOException */ public static String fileToString(File file) throws IOException { - try (FileInputStream fin = new FileInputStream(file)) { + try(FileInputStream fin = new FileInputStream(file)) { return streamToString(fin); } @@ -169,7 +183,7 @@ public class FileUtil { /** * Get files in a folder (create folder if needed) - * + * * @param dir folder * @return list of files */ @@ -181,7 +195,7 @@ public class FileUtil { /** * Get files in a folder (create folder if needed) - * + * * @param dir folder * @param filter file filter * @return list of files @@ -202,7 +216,7 @@ public class FileUtil { /** * Remove extension. - * + * * @param file file * @return filename without extension */ @@ -226,7 +240,7 @@ public class FileUtil { /** * Remove extension. - * + * * @param filename * @return filename and extension */ @@ -253,7 +267,7 @@ public class FileUtil { /** * Read entire input stream to a string, and close it. - * + * * @param in input stream * @return file contents */ @@ -265,7 +279,7 @@ public class FileUtil { /** * Read input stream to a string, and close it. - * + * * @param in input stream * @param lines max number of lines (-1 to disable limit) * @return file contents @@ -327,9 +341,8 @@ public class FileUtil { if (in != null) return in; try { - return new FileInputStream(new File(".", path)); + return new FileInputStream(WorkDir.getFile(path)); } catch (final FileNotFoundException e) { - // error Log.w("Could not open resource stream: " + path); return null; } @@ -339,20 +352,20 @@ public class FileUtil { public static String getResourceAsString(String path) { - return streamToString(FileUtil.class.getResourceAsStream(path)); + return streamToString(getResource(path)); } /** * Save string to file - * + * * @param file file * @param text string * @throws IOException on error */ public static void stringToFile(File file, String text) throws IOException { - try (PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) { + try(PrintStream out = new PrintStream(new FileOutputStream(file), false, "UTF-8")) { out.print(text); @@ -393,14 +406,15 @@ public class FileUtil { /** * Copy resource to file - * + * * @param resname resource name * @param file out file * @throws IOException */ public static void resourceToFile(String resname, File file) throws IOException { - try (InputStream in = FileUtil.getResource(resname); OutputStream out = new FileOutputStream(file)) { + try(InputStream in = FileUtil.getResource(resname); + OutputStream out = new FileOutputStream(file)) { FileUtil.copyStream(in, out); } @@ -410,14 +424,14 @@ public class FileUtil { /** * Get resource as string, safely closing streams. - * + * * @param resname resource name * @return resource as string, empty string on failure * @throws IOException on fail */ public static String resourceToString(String resname) throws IOException { - try (InputStream in = FileUtil.getResource(resname)) { + try(InputStream in = FileUtil.getResource(resname)) { return streamToString(in); } } diff --git a/src/mightypork/utils/files/InstanceLock.java b/src/mightypork/utils/files/InstanceLock.java index 1ceff14..3355800 100644 --- a/src/mightypork/utils/files/InstanceLock.java +++ b/src/mightypork/utils/files/InstanceLock.java @@ -9,23 +9,23 @@ import java.nio.channels.FileLock; /** * Instance lock (avoid running twice) - * + * * @author Ondřej Hruška (MightyPork) */ public class InstanceLock { - + @SuppressWarnings("resource") public static boolean onFile(final File lockFile) { try { lockFile.getParentFile().mkdirs(); final RandomAccessFile randomAccessFile = new RandomAccessFile(lockFile, "rw"); - + final FileLock fileLock = randomAccessFile.getChannel().tryLock(); if (fileLock != null) { - + Runtime.getRuntime().addShutdownHook(new Thread() { - + @Override public void run() { @@ -39,10 +39,10 @@ public class InstanceLock { } } }); - + return true; } - + return false; } catch (final IOException e) { System.err.println("IO error while obtaining lock."); @@ -50,5 +50,5 @@ public class InstanceLock { return false; } } - + } diff --git a/src/mightypork/utils/files/OsUtils.java b/src/mightypork/utils/files/OsUtils.java index 5caf312..f0bc59f 100644 --- a/src/mightypork/utils/files/OsUtils.java +++ b/src/mightypork/utils/files/OsUtils.java @@ -5,90 +5,90 @@ import java.io.File; public class OsUtils { - + public static enum EnumOS { linux, macos, solaris, unknown, windows; - + public boolean isLinux() { return this == linux || this == solaris; } - - + + public boolean isMac() { return this == macos; } - - + + public boolean isWindows() { return this == windows; } } - + private static EnumOS cachedOs; - - + + public static File getHomeWorkDir(String dirname) { final String userhome = System.getProperty("user.home", "."); File file; - + switch (getOs()) { case linux: case solaris: file = new File(userhome, dirname + '/'); break; - + case windows: final String appdata = System.getenv("APPDATA"); - + if (appdata != null) { file = new File(appdata, dirname + '/'); } else { file = new File(userhome, dirname + '/'); } - + break; - + case macos: file = new File(userhome, "Library/Application Support/" + dirname); break; - + default: file = new File(userhome, dirname + "/"); break; } - + return file; } - - + + public static EnumOS getOs() { if (cachedOs != null) return cachedOs; - + final String s = System.getProperty("os.name").toLowerCase(); - + if (s.contains("win")) { cachedOs = EnumOS.windows; - + } else if (s.contains("mac")) { cachedOs = EnumOS.macos; - + } else if (s.contains("linux") || s.contains("unix")) { cachedOs = EnumOS.linux; - + } else if (s.contains("solaris") || s.contains("sunos")) { cachedOs = EnumOS.solaris; - + } else { cachedOs = EnumOS.unknown; } - + return cachedOs; } - + } diff --git a/src/mightypork/utils/files/WorkDir.java b/src/mightypork/utils/files/WorkDir.java new file mode 100644 index 0000000..f45e5de --- /dev/null +++ b/src/mightypork/utils/files/WorkDir.java @@ -0,0 +1,96 @@ +package mightypork.utils.files; + + +import java.io.File; +import java.util.HashMap; +import java.util.Map; + +import mightypork.utils.logging.Log; + + +/** + * Working directory helper. + * + * @author Ondřej Hruška (MightyPork) + */ +public class WorkDir { + + private static File baseDir = new File("."); + private static Map namedPaths = new HashMap<>(); + + + /** + * Initialize the workdir for the given root path + * + * @param workdir workdir root path + */ + public static void setBaseDir(File workdir) + { + WorkDir.baseDir = workdir; + } + + + /** + * Add a path alias (dir or file), relative to the workdir. + * + * @param alias path alias + * @param path path relative to workdir + */ + public static void addPath(String alias, String path) + { + namedPaths.put(alias, path); + } + + + /** + * Get workdir folder, create if not exists. + * + * @param path dir path relative to workdir + * @return dir file + */ + public static File getDir(String path) + { + if (namedPaths.containsKey(path)) path = namedPaths.get(path); + + final File f = new File(baseDir, path); + if (!f.exists()) { + if (!f.mkdirs()) { + Log.w("Could not create a directory: " + f + " (path: " + path + ")"); + } + } + + return f; + } + + + /** + * Get workdir file, create parent if not exists. + * + * @param path dir path relative to workdir + * @return dir file + */ + public static File getFile(String path) + { + if (namedPaths.containsKey(path)) path = namedPaths.get(path); + + final File f = new File(baseDir, path); + + // create the parent dir + if (!f.getParent().equals(baseDir)) { + f.getParentFile().mkdirs(); + } + + return f; + + } + + + /** + * @return the workdir File + */ + public static File getBaseDir() + { + return baseDir; + } + +} diff --git a/src/mightypork/utils/files/zip/ZipBuilder.java b/src/mightypork/utils/files/zip/ZipBuilder.java index 39044aa..82ad8b9 100644 --- a/src/mightypork/utils/files/zip/ZipBuilder.java +++ b/src/mightypork/utils/files/zip/ZipBuilder.java @@ -16,31 +16,32 @@ import mightypork.utils.logging.Log; /** * Class for building a zip file - * + * * @author Ondřej Hruška (MightyPork) */ public class ZipBuilder { - + private final ZipOutputStream out; private final HashSet included = new HashSet<>(); - - + + /** * @param target target zip file * @throws IOException if the file is directory or cannot be created */ - public ZipBuilder(File target) throws IOException { - + public ZipBuilder(File target) throws IOException + { + if (!target.getParentFile().mkdirs()) throw new IOException("Could not create output directory."); - + final FileOutputStream dest = new FileOutputStream(target); out = new ZipOutputStream(new BufferedOutputStream(dest)); } - - + + /** * Add stream to a path - * + * * @param path path * @param in stream * @throws IOException @@ -53,16 +54,16 @@ public class ZipBuilder { return; // ignore } included.add(path); - + out.putNextEntry(new ZipEntry(path)); - + FileUtil.copyStream(in, out); } - - + + /** * Add string as a file - * + * * @param path path * @param text text to write * @throws IOException @@ -72,18 +73,18 @@ public class ZipBuilder { path = preparePath(path); if (included.contains(path)) return; // ignore included.add(path); - + out.putNextEntry(new ZipEntry(path)); - - try (InputStream in = FileUtil.stringToStream(text)) { + + try(InputStream in = FileUtil.stringToStream(text)) { FileUtil.copyStream(in, out); } } - - + + /** * Add resource obtained via FileUtils.getResource() - * + * * @param path path * @param resPath resource path * @throws IOException @@ -93,34 +94,34 @@ public class ZipBuilder { path = preparePath(path); if (included.contains(path)) return; // ignore included.add(path); - + out.putNextEntry(new ZipEntry(path)); - - try (InputStream in = FileUtil.getResource(resPath)) { + + try(InputStream in = FileUtil.getResource(resPath)) { FileUtil.copyStream(in, out); } } - - + + /** * Normalize path - * + * * @param path original path * @return normalized path */ private static String preparePath(String path) { path = path.replace("\\", "/"); - + if (path.charAt(0) == '/') path = path.substring(1); - + return path; } - - + + /** * Close the zip stream - * + * * @throws IOException */ public void close() throws IOException diff --git a/src/mightypork/utils/files/zip/ZipUtils.java b/src/mightypork/utils/files/zip/ZipUtils.java index 7ab4f42..7b2dfe5 100644 --- a/src/mightypork/utils/files/zip/ZipUtils.java +++ b/src/mightypork/utils/files/zip/ZipUtils.java @@ -1,7 +1,12 @@ package mightypork.utils.files.zip; -import java.io.*; +import java.io.BufferedInputStream; +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Enumeration; import java.util.List; @@ -15,17 +20,17 @@ import mightypork.utils.string.validation.StringFilter; /** * Utilities for manipulating zip files - * + * * @author Ondřej Hruška (MightyPork) */ public class ZipUtils { - + private static final int BUFFER_SIZE = 2048; - - + + /** * Extract zip file to target directory - * + * * @param file zip file * @param outputDir target directory * @param filter string filter (will be used to test entry names (paths)) @@ -34,15 +39,15 @@ public class ZipUtils { */ public static List extractZip(File file, File outputDir, StringFilter filter) throws IOException { - try (ZipFile zip = new ZipFile(file)) { + try(ZipFile zip = new ZipFile(file)) { return extractZip(zip, outputDir, filter); } } - - + + /** * Extract zip file to target directory - * + * * @param zip open zip file * @param outputDir target directory * @param filter string filter (will be used to test entry names (paths)) @@ -52,53 +57,53 @@ public class ZipUtils { public static List extractZip(ZipFile zip, File outputDir, StringFilter filter) throws IOException { final ArrayList files = new ArrayList<>(); - + if (!outputDir.mkdirs()) throw new IOException("Could not create output directory."); - + final Enumeration zipFileEntries = zip.entries(); - + // process each entry while (zipFileEntries.hasMoreElements()) { final ZipEntry entry = zipFileEntries.nextElement(); - + // parse filename and path final String entryPath = entry.getName(); final File destFile = new File(outputDir, entryPath); final File destinationParent = destFile.getParentFile(); - + if (entry.isDirectory() || (filter != null && !filter.isValid(entryPath))) continue; - + // make sure directories exist if (!destinationParent.mkdirs()) throw new IOException("Could not create directory."); - + if (!entry.isDirectory()) { extractZipEntry(zip, entry, destFile); files.add(entryPath); } } - + return files; } - - + + /** * Read zip entries and add their paths to a list - * + * * @param zipFile open zip file * @return list of entry names * @throws IOException on error */ public static List listZip(File zipFile) throws IOException { - try (ZipFile zip = new ZipFile(zipFile)) { + try(ZipFile zip = new ZipFile(zipFile)) { return listZip(zip); } } - - + + /** * Read zip entries and add their paths to a list - * + * * @param zip open zip file * @return list of entry names * @throws IOException on error @@ -106,25 +111,25 @@ public class ZipUtils { public static List listZip(ZipFile zip) throws IOException { final ArrayList files = new ArrayList<>(); - + final Enumeration zipFileEntries = zip.entries(); - + // process each entry while (zipFileEntries.hasMoreElements()) { final ZipEntry entry = zipFileEntries.nextElement(); - + if (!entry.isDirectory()) { files.add(entry.getName()); } } - + return files; } - - + + /** * Extract one zip entry to target file - * + * * @param zip open zip file * @param entry entry from the zip file * @param destFile destination file ((NOT directory!) @@ -133,17 +138,20 @@ public class ZipUtils { public static void extractZipEntry(ZipFile zip, ZipEntry entry, File destFile) throws IOException { if (!destFile.getParentFile().mkdirs()) throw new IOException("Could not create output directory."); - - try (InputStream in = zip.getInputStream(entry); BufferedInputStream is = new BufferedInputStream(in); FileOutputStream fos = new FileOutputStream(destFile); BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) { - + + try(InputStream in = zip.getInputStream(entry); + BufferedInputStream is = new BufferedInputStream(in); + FileOutputStream fos = new FileOutputStream(destFile); + BufferedOutputStream dest = new BufferedOutputStream(fos, BUFFER_SIZE)) { + FileUtil.copyStream(is, dest); } } - - + + /** * Load zip entry to String - * + * * @param zip open zip file * @param entry entry from the zip file * @return loaded string @@ -164,16 +172,16 @@ public class ZipUtils { } } } - - + + public static boolean entryExists(File selectedFile, String string) { - try (ZipFile zf = new ZipFile(selectedFile)) { + try(ZipFile zf = new ZipFile(selectedFile)) { return zf.getEntry(string) != null; } catch (final IOException | RuntimeException e) { Log.w("Error reading zip.", e); return false; } - + } } diff --git a/src/mightypork/utils/interfaces/Destroyable.java b/src/mightypork/utils/interfaces/Destroyable.java index d8cd13c..ae5991e 100644 --- a/src/mightypork/utils/interfaces/Destroyable.java +++ b/src/mightypork/utils/interfaces/Destroyable.java @@ -3,11 +3,11 @@ package mightypork.utils.interfaces; /** * Object that can be destroyed (free resources etc) - * + * * @author Ondřej Hruška (MightyPork) */ public interface Destroyable { - + /** * Destroy this object */ diff --git a/src/mightypork/utils/interfaces/Enableable.java b/src/mightypork/utils/interfaces/Enableable.java index fbdbf19..7b04629 100644 --- a/src/mightypork/utils/interfaces/Enableable.java +++ b/src/mightypork/utils/interfaces/Enableable.java @@ -5,19 +5,19 @@ package mightypork.utils.interfaces; * Can be enabled or disabled.
* Implementations should take appropriate action (ie. stop listening to events, * updating etc.) - * + * * @author Ondřej Hruška (MightyPork) */ public interface Enableable { - + /** * Change enabled state - * + * * @param yes enabled */ public void setEnabled(boolean yes); - - + + /** * @return true if enabled */ diff --git a/src/mightypork/utils/interfaces/Hideable.java b/src/mightypork/utils/interfaces/Hideable.java index 32b3fc2..d34f15c 100644 --- a/src/mightypork/utils/interfaces/Hideable.java +++ b/src/mightypork/utils/interfaces/Hideable.java @@ -3,13 +3,13 @@ package mightypork.utils.interfaces; /** * Element that can be hidden or visible - * + * * @author Ondřej Hruška (MightyPork) */ public interface Hideable { - + void setVisible(boolean yes); - - + + boolean isVisible(); } diff --git a/src/mightypork/utils/interfaces/Pauseable.java b/src/mightypork/utils/interfaces/Pauseable.java index 662e870..c241200 100644 --- a/src/mightypork/utils/interfaces/Pauseable.java +++ b/src/mightypork/utils/interfaces/Pauseable.java @@ -3,26 +3,26 @@ package mightypork.utils.interfaces; /** * Can be paused & resumed - * + * * @author Ondřej Hruška (MightyPork) */ public interface Pauseable { - + /** * Pause operation */ public void pause(); - - + + /** * Resume operation */ public void resume(); - - + + /** * @return paused state */ public boolean isPaused(); - + } diff --git a/src/mightypork/utils/interfaces/Pollable.java b/src/mightypork/utils/interfaces/Pollable.java index bc10bd6..2a04d3d 100644 --- a/src/mightypork/utils/interfaces/Pollable.java +++ b/src/mightypork/utils/interfaces/Pollable.java @@ -3,11 +3,11 @@ package mightypork.utils.interfaces; /** * Can be asked to update it's state - * + * * @author Ondřej Hruška (MightyPork) */ public interface Pollable { - + /** * Update internal state */ diff --git a/src/mightypork/utils/interfaces/Updateable.java b/src/mightypork/utils/interfaces/Updateable.java index dfd1310..59dca74 100644 --- a/src/mightypork/utils/interfaces/Updateable.java +++ b/src/mightypork/utils/interfaces/Updateable.java @@ -3,14 +3,14 @@ package mightypork.utils.interfaces; /** * Uses delta timing - * + * * @author Ondřej Hruška (MightyPork) */ public interface Updateable { - + /** * Update item state based on elapsed time - * + * * @param delta time elapsed since last update, in seconds */ public void update(double delta); diff --git a/src/mightypork/utils/ion/Ion.java b/src/mightypork/utils/ion/Ion.java index c5184fb..961962c 100644 --- a/src/mightypork/utils/ion/Ion.java +++ b/src/mightypork/utils/ion/Ion.java @@ -1,7 +1,12 @@ package mightypork.utils.ion; -import java.io.*; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -13,17 +18,17 @@ import mightypork.utils.Support; /** * Universal data storage system (main API class) - * + * * @author Ondřej Hruška (MightyPork) */ public class Ion { - + private static final int RESERVED_LOW = 0; private static final int RESERVED_HIGH = 49; - + private static final int RANGE_LOW = 0; private static final int RANGE_HIGH = 255; - + // marks for object saving /** Null mark */ static final int NULL = 0; @@ -79,31 +84,31 @@ public class Ion { public static final int MAP = 25; /** Array of arbitrary objects */ public static final int OBJECT_ARRAY = 26; - + /** Ionizables */ private static Map> markToClass = new HashMap<>(); private static Map, Integer> classToMark = new HashMap<>(); - + private static Map, IonizerBinary> ionizersBinary = new HashMap<>(); private static Map, IonizerBundled> ionizersBundled = new HashMap<>(); - + private static boolean reservedMarkChecking; - + static { reservedMarkChecking = false; - + // register built-ins register(ION_BUNDLE, IonDataBundle.class); register(SEQUENCE_WRAPPER, IonSequenceWrapper.class); register(MAP_WRAPPER, IonMapWrapper.class); - + reservedMarkChecking = true; } - - + + /** * Register a type for writing/loading. - * + * * @param mark binary ION mark * @param objClass class of the registered object */ @@ -114,16 +119,16 @@ public class Ion { throw new IllegalArgumentException("Cannot register directly: " + Support.str(objClass)); } } - + assertHasImplicitConstructor(objClass); - + registerUsingMark(mark, objClass); } - - + + /** * Try to register a type using a static final ION_MARK int field. - * + * * @param objClass type class */ public static void register(Class objClass) @@ -133,66 +138,66 @@ public class Ion { throw new IllegalArgumentException("Cannot register directly: " + Support.str(objClass)); } } - + assertHasImplicitConstructor(objClass); registerUsingConstant(objClass); } - - + + private static void registerUsingMark(int mark, Class objClass) { assertMarkAvailable(mark, objClass); - + markToClass.put(mark, objClass); classToMark.put(objClass, mark); } - - + + public static void registerUsingConstant(Class objClass) { try { final int mark = ((Number) Reflect.getConstantFieldValue(objClass, "ION_MARK")).intValue(); - + registerUsingMark(mark, objClass); - + } catch (final Exception e) { throw new RuntimeException("Could not register " + Support.str(objClass) + " using an ION_MARK field.", e); } } - - + + /** * Register new binary ionizer. - * + * * @param mark binary ION mark * @param ionizer ionizer */ public static void registerIndirect(int mark, IonizerBinary ionizer) { final Class objClass = Reflect.getGenericParameters(ionizer.getClass())[0]; - + registerUsingMark(mark, objClass); - + ionizersBinary.put(objClass, ionizer); } - - + + /** * Register new bundled ionizer. - * + * * @param mark binary ION mark * @param ionizer ionizer */ public static void registerIndirect(int mark, IonizerBundled ionizer) { final Class objClass = Reflect.getGenericParameters(ionizer.getClass())[0]; - + registerUsingMark(mark, objClass); - + ionizersBundled.put(objClass, ionizer); } - - + + private static void assertHasImplicitConstructor(Class objClass) { try { @@ -201,28 +206,28 @@ public class Ion { throw new RuntimeException("Class " + objClass + " doesn't have an implicit constructor."); } } - - + + private static void assertMarkAvailable(int mark, Class objClass) { // negative marks are allowed. if (mark > RANGE_HIGH) throw new IllegalArgumentException("Mark must be < 256."); if (mark < RANGE_LOW) throw new IllegalArgumentException("Mark must be positive."); - + if (reservedMarkChecking && isMarkReserved(mark)) { throw new IllegalArgumentException("Marks " + RESERVED_LOW + ".." + RESERVED_HIGH + " are reserved."); } - + if (markToClass.containsKey(mark)) { throw new IllegalArgumentException("Mark " + mark + " is already in use."); } - + if (classToMark.containsKey(objClass)) { throw new IllegalArgumentException(Support.str(objClass) + " is already registered."); } } - - + + /** * Load binary from file and cast. */ @@ -230,19 +235,19 @@ public class Ion { { return fromFile(new File(path)); } - - + + /** * Load binary from file and cast. */ public static T fromFile(File file) throws IOException { - try (InputStream in = new FileInputStream(file)) { + try(InputStream in = new FileInputStream(file)) { return fromStream(in); } } - - + + /** * Write binary to file with mark. */ @@ -250,49 +255,49 @@ public class Ion { { toFile(new File(path), obj); } - - + + /** * Write binary to file with mark. */ public static void toFile(File file, Object obj) throws IOException { - try (OutputStream out = new FileOutputStream(file)) { - + try(OutputStream out = new FileOutputStream(file)) { + toStream(out, obj); - + out.flush(); } catch (final Exception e) { throw new IOException("Error writing to ION file.", e); } } - - + + /** * Load object from stream based on mark, try to cast. */ public static T fromStream(InputStream in) throws IOException { - try (final IonInput inp = new IonInput(in)) { + try(final IonInput inp = new IonInput(in)) { return (T) inp.readObject(); } } - - + + /** * Write object to output with a mark. */ public static void toStream(OutputStream out, Object obj) throws IOException { - try (IonOutput iout = new IonOutput(out)) { + try(IonOutput iout = new IonOutput(out)) { iout.writeObject(obj); } } - - + + /** * Get ion input - * + * * @param path file path to read * @return input * @throws IOException @@ -301,11 +306,11 @@ public class Ion { { return getInput(new File(path)); } - - + + /** * Get ion input - * + * * @param file file to read * @return input * @throws IOException @@ -315,11 +320,11 @@ public class Ion { { return new IonInput(new FileInputStream(file)); } - - + + /** * Get ion output - * + * * @param path file path to write * @return output * @throws IOException @@ -328,11 +333,11 @@ public class Ion { { return getOutput(new File(path)); } - - + + /** * Get ion output - * + * * @param file file to write * @return output * @throws IOException @@ -342,8 +347,8 @@ public class Ion { { return new IonOutput(new FileOutputStream(file)); } - - + + /** * Create new bundle and write the object to it. */ @@ -353,12 +358,12 @@ public class Ion { content.save(ib); return ib; } - - + + /** * Try to unwrap an object from bundle. The object class must have implicit * accessible constructor. - * + * * @param bundle unwrapped bundle * @param objClass class of desired object * @return the object unwrapped @@ -374,56 +379,56 @@ public class Ion { throw new IOException("Could not instantiate " + Support.str(objClass) + "."); } } - - + + static Class getClassForMark(int mark) { return markToClass.get(mark); } - - + + static IonizerBinary getIonizerBinaryForClass(Class clz) { return ionizersBinary.get(clz); } - - + + static IonizerBundled getIonizerBundledForClass(Class clz) { return ionizersBundled.get(clz); } - - + + public static int getMark(Object object) { assertRegistered(object); - + return classToMark.get(object.getClass()); } - - + + /** * @return true if the mark is for a registered {@link IonBinary} object */ static boolean isMarkForBinary(int mark) { if (!markToClass.containsKey(mark)) return false; - + return IonBinary.class.isAssignableFrom(markToClass.get(mark)); } - - + + /** * @return true if the mark is for a registered {@link IonBinary} object */ static boolean isMarkForBundled(int mark) { if (!markToClass.containsKey(mark)) return false; - + return IonBundled.class.isAssignableFrom(markToClass.get(mark)); } - - + + /** * @return true if the mark is for a registered indirectly saved binary * object @@ -431,11 +436,11 @@ public class Ion { static boolean isMarkForIndirectBinary(int mark) { if (!markToClass.containsKey(mark)) return false; - + return ionizersBinary.containsKey(markToClass.get(mark)); } - - + + /** * @return true if the mark is for a registered indirectly saved bundled * object @@ -443,11 +448,11 @@ public class Ion { static boolean isMarkForIndirectBundled(int mark) { if (!markToClass.containsKey(mark)) return false; - + return ionizersBundled.containsKey(markToClass.get(mark)); } - - + + /** * @return true if the mark is reserved for internal use */ @@ -455,8 +460,8 @@ public class Ion { { return mark >= RESERVED_LOW && mark <= RESERVED_HIGH; } - - + + /** * @return true if the mark is for a registered {@link IonBinary} object */ @@ -464,14 +469,14 @@ public class Ion { { final Class clazz = object.getClass(); if (classToMark.containsKey(clazz)) return true; - + return false; } - - + + /** * Make sure object is registered in the table. - * + * * @throws IOException if not registered or class mismatch */ static void assertRegistered(Object obj) @@ -480,8 +485,8 @@ public class Ion { throw new RuntimeException("Type not registered: " + Support.str(obj.getClass())); } } - - + + /** * For get all external registered types - just like if the class was * freshly loaded. Can be used for unit tests. @@ -489,31 +494,31 @@ public class Ion { public static void reset() { final List toRemove = new ArrayList<>(); - - // remove direct + + // remove direct for (final Integer mark : markToClass.keySet()) { if (!isMarkReserved(mark)) { toRemove.add(mark); } } - + for (final int i : toRemove) { - + final Class clz = markToClass.remove(i); - + classToMark.remove(clz); ionizersBinary.remove(clz); ionizersBundled.remove(clz); } } - - + + public static boolean isObjectIndirectBundled(Object obj) { return ionizersBundled.containsKey(obj.getClass()); } - - + + public static boolean isObjectIndirectBinary(Object obj) { return ionizersBinary.containsKey(obj.getClass()); diff --git a/src/mightypork/utils/ion/IonBinary.java b/src/mightypork/utils/ion/IonBinary.java index 0b5bf1e..2499da1 100644 --- a/src/mightypork/utils/ion/IonBinary.java +++ b/src/mightypork/utils/ion/IonBinary.java @@ -7,24 +7,24 @@ import java.io.IOException; /** * Binary ion object. If a class implements both binary and bundled, then binary * will be preferred by both IonInput and IonOutput. - * + * * @author Ondřej Hruška (MightyPork) */ public interface IonBinary { - + /** * Load data from the input stream. - * + * * @param in input stream * @throws IOException */ void load(IonInput in) throws IOException; - - + + /** * Store data to output stream (in such way that the load method will later * be able to read it). - * + * * @param out Output stream * @throws IOException */ diff --git a/src/mightypork/utils/ion/IonBundled.java b/src/mightypork/utils/ion/IonBundled.java index e74d9aa..ec0a1de 100644 --- a/src/mightypork/utils/ion/IonBundled.java +++ b/src/mightypork/utils/ion/IonBundled.java @@ -4,22 +4,22 @@ package mightypork.utils.ion; /** * Bundled ion object. If a class implements both binary and bundled, then * binary will be preferred by both IonInput and IonOutput. - * + * * @author Ondřej Hruška (MightyPork) */ public interface IonBundled { - + /** * Load this object from the data bundle - * + * * @param in bundle to load from */ void load(IonDataBundle in); - - + + /** * Save this object to the data bundle - * + * * @param out bundle to save into */ void save(IonDataBundle out); diff --git a/src/mightypork/utils/ion/IonDataBundle.java b/src/mightypork/utils/ion/IonDataBundle.java index e6cfdb7..4b34666 100644 --- a/src/mightypork/utils/ion/IonDataBundle.java +++ b/src/mightypork/utils/ion/IonDataBundle.java @@ -12,34 +12,34 @@ import java.util.Map; /** * Ion data bundle - simplified Map with facilities for storing maps and * sequences. - * + * * @author Ondřej Hruška (MightyPork) */ public class IonDataBundle implements IonBinary { - + private final Map backingMap = new HashMap<>(); - - + + /** * Clear & fill a provided bundle with elements from a bundle value - * + * * @param key key * @param filled bundle to fill */ public void loadBundle(String key, IonDataBundle filled) { if (!containsKey(key)) return; - + final IonDataBundle ib = get(key, new IonDataBundle()); - + filled.clear(); filled.putAll(ib); } - - + + /** * Check if a key is used in the bundle - * + * * @param key key to check * @return true if this key is used in the bundle */ @@ -47,11 +47,11 @@ public class IonDataBundle implements IonBinary { { return backingMap.containsKey(key); } - - + + /** * Check if a value is contained in the bundle - * + * * @param value value to check * @return true if this value is contained in the bundle */ @@ -59,11 +59,11 @@ public class IonDataBundle implements IonBinary { { return backingMap.containsValue(value); } - - + + /** * Get a map value - * + * * @param key key * @return a new Map with elements from that value */ @@ -71,11 +71,11 @@ public class IonDataBundle implements IonBinary { { return loadMap(key, new LinkedHashMap()); } - - + + /** * Clear & fill the provided map with elements from a map value - * + * * @param key key * @param filled Map to fill */ @@ -87,11 +87,11 @@ public class IonDataBundle implements IonBinary { imw.fill(filled); return filled; } - - + + /** * Get a sequence value - * + * * @param key key * @return a new Collection with elements from that value */ @@ -99,11 +99,11 @@ public class IonDataBundle implements IonBinary { { return loadSequence(key, new ArrayList()); } - - + + /** * Clear & fill the provided Collection with elements from a sequence value - * + * * @param key key * @param filled Collection to fill * @return the filled collection @@ -114,15 +114,15 @@ public class IonDataBundle implements IonBinary { if (isw == null) throw new RuntimeException("No such key: " + key); filled.clear(); isw.fill(filled); - + return filled; } - - + + /** * Load a bundled object from a bundle value.
* The object does not have to be registered. - * + * * @param key key * @param loaded loaded object * @return the loaded object @@ -131,17 +131,17 @@ public class IonDataBundle implements IonBinary { { final IonDataBundle bu = get(key, null); if (bu == null) throw new RuntimeException("No such key: " + key); - + loaded.load(bu); - + return loaded; } - - + + /** * Save a bundled object to a bundle value.
* The object does not have to be registered. - * + * * @param key key * @param saved saved object */ @@ -151,11 +151,11 @@ public class IonDataBundle implements IonBinary { saved.save(bu); put(key, bu); } - - + + /** * Get value, or fallback (if none found of with bad type). - * + * * @param key * @param fallback value * @return value @@ -170,11 +170,11 @@ public class IonDataBundle implements IonBinary { return fallback; } } - - + + /** * Get value, or null (if none found of with bad type). - * + * * @param key * @return value */ @@ -182,127 +182,127 @@ public class IonDataBundle implements IonBinary { { return get(key, (T) null); } - - + + public void put(String key, Object value) { if (key == null || value == null) return; if (!Ion.isRegistered(value)) throw new IllegalArgumentException("Cannot add to bundle, not registered: " + value); backingMap.put(key, value); } - - + + public void put(String key, boolean value) { backingMap.put(key, value); } - - + + public void put(String key, byte value) { backingMap.put(key, value); } - - + + public void put(String key, char value) { backingMap.put(key, value); } - - + + public void put(String key, short value) { backingMap.put(key, value); } - - + + public void put(String key, int value) { backingMap.put(key, value); } - - + + public void put(String key, long value) { backingMap.put(key, value); } - - + + public void put(String key, double value) { backingMap.put(key, value); } - - + + public void put(String key, float value) { backingMap.put(key, value); } - - + + public void put(String key, String value) { backingMap.put(key, value); } - - + + public void put(String key, boolean[] value) { backingMap.put(key, value); } - - + + public void put(String key, char[] value) { backingMap.put(key, value); } - - + + public void put(String key, short[] value) { backingMap.put(key, value); } - - + + public void put(String key, int[] value) { backingMap.put(key, value); } - - + + public void put(String key, long[] value) { backingMap.put(key, value); } - - + + public void put(String key, double[] value) { backingMap.put(key, value); } - - + + public void put(String key, float[] value) { backingMap.put(key, value); } - - + + public void put(String key, String[] value) { backingMap.put(key, value); } - - + + public void put(String key, Object[] value) { backingMap.put(key, value); } - - + + /** * Put a sequence to the bundle. - * + * * @param key key * @param c value (Collection) */ @@ -311,11 +311,11 @@ public class IonDataBundle implements IonBinary { { backingMap.put(key, new IonSequenceWrapper(c)); } - - + + /** * Put a map to the bundle. - * + * * @param key key * @param m value (Map) */ @@ -324,44 +324,44 @@ public class IonDataBundle implements IonBinary { { backingMap.put(key, new IonMapWrapper(m)); } - - + + @Override public void load(IonInput in) throws IOException { in.readMap(backingMap); } - - + + @Override public void save(IonOutput out) throws IOException { out.writeMap(backingMap); } - - + + /** * Get number of elements in the bundle - * + * * @return size */ public int size() { return backingMap.size(); } - - + + /** * Check whether the bundle is empty - * + * * @return true if empty */ public boolean isEmpty() { return backingMap.isEmpty(); } - - + + /** * Remove all elements */ @@ -369,11 +369,11 @@ public class IonDataBundle implements IonBinary { { backingMap.clear(); } - - + + /** * Remove a value by key - * + * * @param key key to remove * @return the removed object */ @@ -381,26 +381,26 @@ public class IonDataBundle implements IonBinary { { return backingMap.remove(key); } - - + + /** * Put all from another bundle - * + * * @param anotherBundle another bundle */ public void putAll(IonDataBundle anotherBundle) { backingMap.putAll(anotherBundle.backingMap); } - - + + @Override public String toString() { return backingMap.toString(); } - - + + @Override public int hashCode() { @@ -409,8 +409,8 @@ public class IonDataBundle implements IonBinary { result = prime * result + ((backingMap == null) ? 0 : backingMap.hashCode()); return result; } - - + + @Override public boolean equals(Object obj) { diff --git a/src/mightypork/utils/ion/IonInput.java b/src/mightypork/utils/ion/IonInput.java index 33a0092..87e2ef9 100644 --- a/src/mightypork/utils/ion/IonInput.java +++ b/src/mightypork/utils/ion/IonInput.java @@ -1,7 +1,14 @@ package mightypork.utils.ion; -import java.io.*; +import java.io.Closeable; +import java.io.DataInput; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -12,31 +19,33 @@ import mightypork.utils.exceptions.CorruptDataException; /** * Ion input stream - * + * * @author Ondřej Hruška (MightyPork) */ public class IonInput implements Closeable { - + private final DataInput in; private final InputStream stream; - - + + @SuppressWarnings("resource") - public IonInput(File inFile) throws FileNotFoundException { + public IonInput(File inFile) throws FileNotFoundException + { this(new FileInputStream(inFile)); } - - - public IonInput(InputStream in) { + + + public IonInput(InputStream in) + { this.stream = in; this.in = new DataInputStream(in); } - - + + /** * Read int 0-255. Suitable when the int was written using * writeIntByte() method. - * + * * @return int * @throws IOException */ @@ -44,12 +53,12 @@ public class IonInput implements Closeable { { return in.readUnsignedByte(); } - - + + /** * Read an int 0-65535. Suitable when the int was written using * writeIntShort() method. - * + * * @return int * @throws IOException */ @@ -57,62 +66,62 @@ public class IonInput implements Closeable { { return in.readUnsignedShort(); } - - + + public boolean readBoolean() throws IOException { return in.readBoolean(); } - - + + public byte readByte() throws IOException { return in.readByte(); } - - + + public short readShort() throws IOException { return in.readShort(); } - - + + public char readChar() throws IOException { return in.readChar(); } - - + + public int readInt() throws IOException { return in.readInt(); } - - + + public long readLong() throws IOException { return in.readLong(); } - - + + public float readFloat() throws IOException { return in.readFloat(); } - - + + public double readDouble() throws IOException { return in.readDouble(); } - - + + public String readString() throws IOException { return in.readUTF(); } - - + + public boolean[] readBooleans() throws IOException { final int length = readLength(); @@ -122,8 +131,8 @@ public class IonInput implements Closeable { } return arr; } - - + + public byte[] readBytes() throws IOException { final int length = readLength(); @@ -133,8 +142,8 @@ public class IonInput implements Closeable { } return arr; } - - + + public char[] readChars() throws IOException { final int length = readLength(); @@ -144,8 +153,8 @@ public class IonInput implements Closeable { } return arr; } - - + + public short[] readShorts() throws IOException { final int length = readLength(); @@ -155,8 +164,8 @@ public class IonInput implements Closeable { } return arr; } - - + + public int[] readInts() throws IOException { final int length = readLength(); @@ -166,8 +175,8 @@ public class IonInput implements Closeable { } return arr; } - - + + public long[] readLongs() throws IOException { final int length = readLength(); @@ -177,8 +186,8 @@ public class IonInput implements Closeable { } return arr; } - - + + public float[] readFloats() throws IOException { final int length = readLength(); @@ -188,8 +197,8 @@ public class IonInput implements Closeable { } return arr; } - - + + public double[] readDoubles() throws IOException { final int length = readLength(); @@ -199,8 +208,8 @@ public class IonInput implements Closeable { } return arr; } - - + + public String[] readStrings() throws IOException { final int length = readLength(); @@ -210,8 +219,8 @@ public class IonInput implements Closeable { } return arr; } - - + + public Object[] readObjects() throws IOException { final int length = readLength(); @@ -221,8 +230,8 @@ public class IonInput implements Closeable { } return arr; } - - + + /** * Read bundle without a mark */ @@ -232,8 +241,8 @@ public class IonInput implements Closeable { ib.load(this); return ib; } - - + + /** * Read bundle without a mark, load into a provided one */ @@ -242,20 +251,20 @@ public class IonInput implements Closeable { filled.clear(); filled.load(this); } - - + + private int readMark() throws IOException { return readIntByte(); } - - + + private int readLength() throws IOException { return readInt(); } - - + + /** *

* Read object based on mark; if null mark is found, returns default value. @@ -264,7 +273,7 @@ public class IonInput implements Closeable { * If, however, an object of invalid or different type is found, an * exception will be thrown. *

- * + * * @param def default value. * @return the loaded object * @throws CorruptDataException @@ -279,130 +288,130 @@ public class IonInput implements Closeable { throw new CorruptDataException("Could not load object.", e); } } - - + + /** * Read single object, preceded by a mark. - * + * * @return the loaded object * @throws IOException */ public Object readObject() throws IOException { final int mark = readMark(); - + try { - + if (Ion.isMarkForBinary(mark)) { IonBinary loaded; - + loaded = (IonBinary) Ion.getClassForMark(mark).newInstance(); - + loaded.load(this); return loaded; } - + if (Ion.isMarkForBundled(mark)) { IonBundled loaded; - + loaded = (IonBundled) Ion.getClassForMark(mark).newInstance(); - + final IonDataBundle ib = readBundle(); loaded.load(ib); return loaded; } - + if (Ion.isMarkForIndirectBundled(mark)) { final IonizerBundled ionizer = Ion.getIonizerBundledForClass(Ion.getClassForMark(mark)); return ionizer.load(readBundle()); } - + if (Ion.isMarkForIndirectBinary(mark)) { final IonizerBinary ionizer = Ion.getIonizerBinaryForClass(Ion.getClassForMark(mark)); return ionizer.load(this); } - + } catch (final Exception e) { throw new RuntimeException("Could not load object for mark: " + mark, e); } - + switch (mark) { case Ion.NULL: return null; - + case Ion.BOOLEAN: return readBoolean(); - + case Ion.BYTE: return readByte(); - + case Ion.CHAR: return readChar(); - + case Ion.SHORT: return readShort(); - + case Ion.INT: return readInt(); - + case Ion.LONG: return readLong(); - + case Ion.FLOAT: return readFloat(); - + case Ion.DOUBLE: return readDouble(); - + case Ion.STRING: return readString(); - + case Ion.BOOLEAN_ARRAY: return readBooleans(); - + case Ion.BYTE_ARRAY: return readBytes(); - + case Ion.CHAR_ARRAY: return readChars(); - + case Ion.SHORT_ARRAY: return readShorts(); - + case Ion.INT_ARRAY: return readInts(); - + case Ion.LONG_ARRAY: return readLongs(); - + case Ion.FLOAT_ARRAY: return readFloats(); - + case Ion.DOUBLE_ARRAY: return readDoubles(); - + case Ion.STRING_ARRAY: return readStrings(); - + case Ion.OBJECT_ARRAY: return readObjects(); - + case Ion.MAP: return readMap(); - + case Ion.SEQUENCE: return readSequence(); - + default: throw new CorruptDataException("Invalid mark: " + mark); } } - - + + /** * Reads mark and returns true if the mark is ENTRY, false if the mark is * END. Throws an exception otherwise. - * + * * @return mark was ENTRY * @throws IOException when the mark is neither ENTRY or END. */ @@ -411,14 +420,14 @@ public class IonInput implements Closeable { final int mark = readMark(); if (mark == Ion.ENTRY) return true; if (mark == Ion.END) return false; - + throw new CorruptDataException("Unexpected mark in sequence: " + mark); } - - + + /** * Read a sequence of elements into an ArrayList - * + * * @return the collection * @throws IOException */ @@ -426,11 +435,11 @@ public class IonInput implements Closeable { { return readSequence(new ArrayList()); } - - + + /** * Load entries into a collection. The collection is cleaned first. - * + * * @param filled collection to populate * @return the collection * @throws IOException @@ -448,11 +457,11 @@ public class IonInput implements Closeable { throw new CorruptDataException("Unexpected element type in sequence.", e); } } - - + + /** * Read element pairs into a HashMap - * + * * @return the map * @throws IOException */ @@ -460,11 +469,11 @@ public class IonInput implements Closeable { { return readMap(new HashMap()); } - - + + /** * Load data into a map. The map is cleaned first. - * + * * @param filled filled map * @return the map * @throws IOException @@ -477,7 +486,7 @@ public class IonInput implements Closeable { while (hasNextEntry()) { final K key = (K) readObject(); final V value = (V) readObject(); - + filled.put(key, value); } return filled; @@ -485,8 +494,8 @@ public class IonInput implements Closeable { throw new CorruptDataException("Unexpected element type in map.", e); } } - - + + @Override public void close() throws IOException { diff --git a/src/mightypork/utils/ion/IonMapWrapper.java b/src/mightypork/utils/ion/IonMapWrapper.java index 765944d..6c90980 100644 --- a/src/mightypork/utils/ion/IonMapWrapper.java +++ b/src/mightypork/utils/ion/IonMapWrapper.java @@ -8,45 +8,47 @@ import java.util.Map; @SuppressWarnings({ "rawtypes", "unchecked" }) class IonMapWrapper implements IonBinary { - + private final Map map; - - - public IonMapWrapper() { + + + public IonMapWrapper() + { map = new LinkedHashMap<>(); } - - - public IonMapWrapper(Map saved) { + + + public IonMapWrapper(Map saved) + { map = saved; } - - + + @Override public void load(IonInput in) throws IOException { map.clear(); in.readMap(map); } - - + + @Override public void save(IonOutput out) throws IOException { out.writeMap(map); } - - + + public void fill(Map o) { o.clear(); o.putAll(map); } - - + + public Map getMap() { return map; } - + } diff --git a/src/mightypork/utils/ion/IonOutput.java b/src/mightypork/utils/ion/IonOutput.java index 863ddf8..c82a9e4 100644 --- a/src/mightypork/utils/ion/IonOutput.java +++ b/src/mightypork/utils/ion/IonOutput.java @@ -1,7 +1,14 @@ package mightypork.utils.ion; -import java.io.*; +import java.io.Closeable; +import java.io.DataOutput; +import java.io.DataOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStream; import java.util.Collection; import java.util.Map; import java.util.Map.Entry; @@ -9,99 +16,101 @@ import java.util.Map.Entry; /** * Ion output stream - * + * * @author Ondřej Hruška (MightyPork) */ public class IonOutput implements Closeable { - + private final DataOutput out; private final OutputStream stream; - - + + @SuppressWarnings("resource") - public IonOutput(File outFile) throws FileNotFoundException { + public IonOutput(File outFile) throws FileNotFoundException + { this(new FileOutputStream(outFile)); } - - - public IonOutput(OutputStream out) { + + + public IonOutput(OutputStream out) + { this.stream = out; this.out = new DataOutputStream(out); } - - + + public void writeBoolean(boolean a) throws IOException { out.writeBoolean(a); } - - + + public void writeByte(int a) throws IOException { out.writeByte(a); } - - + + public void writeShort(int a) throws IOException { out.writeShort(a); } - - + + public void writeChar(int a) throws IOException { out.writeChar(a); } - - + + public void writeInt(int a) throws IOException { out.writeInt(a); } - - + + public void writeIntShort(int a) throws IOException { out.writeShort(a); } - - + + public void writeIntByte(int a) throws IOException { out.writeByte(a); } - - + + public void writeLong(long a) throws IOException { out.writeLong(a); } - - + + public void writeFloat(float a) throws IOException { out.writeFloat(a); } - - + + public void writeDouble(double a) throws IOException { out.writeDouble(a); } - - + + public void writeBytes(String a) throws IOException { out.writeBytes(a); } - - + + public void writeString(String a) throws IOException { out.writeUTF(a); } - - + + public void writeBooleans(boolean[] arr) throws IOException { writeLength(arr.length); @@ -109,8 +118,8 @@ public class IonOutput implements Closeable { out.writeBoolean(a); } } - - + + public void writeBytes(byte[] arr) throws IOException { writeLength(arr.length); @@ -118,8 +127,8 @@ public class IonOutput implements Closeable { out.writeByte(a); } } - - + + public void writeChars(char[] arr) throws IOException { writeLength(arr.length); @@ -127,8 +136,8 @@ public class IonOutput implements Closeable { out.writeChar(a); } } - - + + public void writeShorts(short[] arr) throws IOException { writeLength(arr.length); @@ -136,8 +145,8 @@ public class IonOutput implements Closeable { out.writeShort(a); } } - - + + public void writeInts(int[] arr) throws IOException { writeLength(arr.length); @@ -145,8 +154,8 @@ public class IonOutput implements Closeable { out.writeInt(a); } } - - + + public void writeLongs(long[] arr) throws IOException { writeLength(arr.length); @@ -154,8 +163,8 @@ public class IonOutput implements Closeable { out.writeLong(a); } } - - + + public void writeFloats(float[] arr) throws IOException { writeLength(arr.length); @@ -163,8 +172,8 @@ public class IonOutput implements Closeable { out.writeFloat(a); } } - - + + public void writeDoubles(double[] arr) throws IOException { writeLength(arr.length); @@ -172,8 +181,8 @@ public class IonOutput implements Closeable { out.writeDouble(a); } } - - + + public void writeStrings(String[] arr) throws IOException { writeLength(arr.length); @@ -181,8 +190,8 @@ public class IonOutput implements Closeable { out.writeUTF(a); } } - - + + /** * Write a bundle without a mark */ @@ -190,11 +199,11 @@ public class IonOutput implements Closeable { { bundle.save(this); } - - + + /** * Write array of objects. Works with all that is supported by writeObject() - * + * * @param arr array to write * @throws IOException on IO error or on invalid object type. */ @@ -205,8 +214,8 @@ public class IonOutput implements Closeable { writeObject(a); } } - - + + public void writeSequence(Collection sequence) throws IOException { for (final T element : sequence) { @@ -215,51 +224,51 @@ public class IonOutput implements Closeable { } endSequence(); } - - + + public void writeMap(Map map) throws IOException { for (final Entry e : map.entrySet()) { if (e.getValue() == null) { continue; } - + startEntry(); writeObject(e.getKey()); writeObject(e.getValue()); } endSequence(); } - - + + public void endSequence() throws IOException { writeMark(Ion.END); } - - + + public void startEntry() throws IOException { writeMark(Ion.ENTRY); } - - + + private void writeMark(int mark) throws IOException { writeIntByte(mark); } - - + + private void writeLength(int length) throws IOException { writeInt(length); } - - + + /** * Write an object. Supported are built-in types and types registered to * Ion. - * + * * @param obj obj to write * @throws IOException on IO error or invalid object type. */ @@ -269,177 +278,177 @@ public class IonOutput implements Closeable { writeMark(Ion.NULL); return; } - + if (obj instanceof IonBinary) { final IonBinary iObj = (IonBinary) obj; - + writeMark(Ion.getMark(obj)); iObj.save(this); return; } - + if (obj instanceof IonBundled) { final IonBundled iObj = (IonBundled) obj; - + writeMark(Ion.getMark(obj)); - + final IonDataBundle bundle = new IonDataBundle(); iObj.save(bundle); writeBundle(bundle); - + return; } - + if (Ion.isObjectIndirectBundled(obj)) { final IonizerBundled ionizer = Ion.getIonizerBundledForClass(obj.getClass()); - + writeMark(Ion.getMark(obj)); - + final IonDataBundle bundle = new IonDataBundle(); ionizer._save(obj, bundle); writeBundle(bundle); return; } - + if (Ion.isObjectIndirectBinary(obj)) { final IonizerBinary ionizer = Ion.getIonizerBinaryForClass(obj.getClass()); - + writeMark(Ion.getMark(obj)); - + ionizer._save(obj, this); return; } - + if (obj instanceof Map) { writeMark(Ion.MAP); writeMap((Map) obj); return; } - + if (obj instanceof Collection) { writeMark(Ion.SEQUENCE); writeSequence((Collection) obj); return; } - + if (obj instanceof Boolean) { writeMark(Ion.BOOLEAN); writeBoolean((Boolean) obj); return; } - + if (obj instanceof Byte) { writeMark(Ion.BYTE); writeByte((Byte) obj); return; } - + if (obj instanceof Character) { writeMark(Ion.CHAR); writeChar((Character) obj); return; } - + if (obj instanceof Short) { writeMark(Ion.SHORT); writeShort((Short) obj); return; } - + if (obj instanceof Integer) { writeMark(Ion.INT); writeInt((Integer) obj); return; } - + if (obj instanceof Long) { writeMark(Ion.LONG); writeLong((Long) obj); return; } - + if (obj instanceof Float) { writeMark(Ion.FLOAT); writeFloat((Float) obj); return; } - + if (obj instanceof Double) { writeMark(Ion.DOUBLE); writeDouble((Double) obj); return; } - + if (obj instanceof String) { writeMark(Ion.STRING); writeString((String) obj); return; } - + if (obj instanceof boolean[]) { writeMark(Ion.BOOLEAN_ARRAY); writeBooleans((boolean[]) obj); return; } - + if (obj instanceof byte[]) { writeMark(Ion.BYTE_ARRAY); writeBytes((byte[]) obj); return; } - + if (obj instanceof char[]) { writeMark(Ion.CHAR_ARRAY); writeChars((char[]) obj); return; } - + if (obj instanceof short[]) { writeMark(Ion.SHORT_ARRAY); writeShorts((short[]) obj); return; } - + if (obj instanceof int[]) { writeMark(Ion.INT_ARRAY); writeInts((int[]) obj); return; } - + if (obj instanceof long[]) { writeMark(Ion.LONG_ARRAY); writeLongs((long[]) obj); return; } - + if (obj instanceof float[]) { writeMark(Ion.FLOAT_ARRAY); writeFloats((float[]) obj); return; } - + if (obj instanceof double[]) { writeMark(Ion.DOUBLE_ARRAY); writeDoubles((double[]) obj); return; } - + if (obj instanceof String[]) { writeMark(Ion.STRING_ARRAY); writeStrings((String[]) obj); return; } - + if (obj instanceof Object[]) { writeMark(Ion.OBJECT_ARRAY); writeObjects((Object[]) obj); return; } - + throw new IOException("Object " + obj + " could not be be written to stream."); } - - + + @Override public void close() throws IOException { diff --git a/src/mightypork/utils/ion/IonSequenceWrapper.java b/src/mightypork/utils/ion/IonSequenceWrapper.java index 54fdefd..0b98fa7 100644 --- a/src/mightypork/utils/ion/IonSequenceWrapper.java +++ b/src/mightypork/utils/ion/IonSequenceWrapper.java @@ -8,45 +8,47 @@ import java.util.Collection; @SuppressWarnings({ "rawtypes", "unchecked" }) class IonSequenceWrapper implements IonBinary { - + private Collection collection = new ArrayList(); - - - public IonSequenceWrapper() { + + + public IonSequenceWrapper() + { collection = new ArrayList(); } - - - public IonSequenceWrapper(Collection saved) { + + + public IonSequenceWrapper(Collection saved) + { collection = saved; } - - + + @Override public void load(IonInput in) throws IOException { collection.clear(); in.readSequence(collection); } - - + + @Override public void save(IonOutput out) throws IOException { out.writeSequence(collection); } - - + + public void fill(Collection o) { o.clear(); o.addAll(collection); } - - + + public Collection getSequence() { return collection; } - + } diff --git a/src/mightypork/utils/ion/IonizerBinary.java b/src/mightypork/utils/ion/IonizerBinary.java index 6471ef6..f12da43 100644 --- a/src/mightypork/utils/ion/IonizerBinary.java +++ b/src/mightypork/utils/ion/IonizerBinary.java @@ -7,35 +7,35 @@ import java.io.IOException; /** * External ionizer using a IonOutput / IonInput - can be used if the data type * cannot be modified to implement the proper interface - * + * * @author Ondřej Hruška (MightyPork) * @param */ public abstract class IonizerBinary { - + @SuppressWarnings("unchecked") final void _save(Object object, IonOutput out) throws IOException { save((T) object, out); } - - + + /** * Save an object to ion output - * + * * @param object object to save * @param out ion output * @throws IOException */ public abstract void save(T object, IonOutput out) throws IOException; - - + + /** * Load an object from ion input - * + * * @param in ion input * @return the loaded object */ public abstract T load(IonInput in) throws IOException; - + } diff --git a/src/mightypork/utils/ion/IonizerBundled.java b/src/mightypork/utils/ion/IonizerBundled.java index 63a657f..14731ff 100644 --- a/src/mightypork/utils/ion/IonizerBundled.java +++ b/src/mightypork/utils/ion/IonizerBundled.java @@ -4,34 +4,34 @@ package mightypork.utils.ion; /** * External ionizer using a data bundle - can be used if the data type cannot be * modified to implement the proper interface - * + * * @author Ondřej Hruška (MightyPork) * @param */ public abstract class IonizerBundled { - + @SuppressWarnings("unchecked") final void _save(Object object, IonDataBundle out) { save((T) object, out); } - - + + /** * Save an object to data bundle - * + * * @param object object to save * @param out bundle to save to */ public abstract void save(T object, IonDataBundle out); - - + + /** * Load an object from a bundle - * + * * @param in bundle to load from * @return the loaded object */ public abstract T load(IonDataBundle in); - + } diff --git a/src/mightypork/utils/logging/Log.java b/src/mightypork/utils/logging/Log.java index 152e67f..b61123e 100644 --- a/src/mightypork/utils/logging/Log.java +++ b/src/mightypork/utils/logging/Log.java @@ -18,23 +18,23 @@ import mightypork.utils.string.StringUtil; /** * A log. - * + * * @author Ondřej Hruška (MightyPork) */ public class Log { - + private static LogWriter main = null; private static boolean enabled = true; private static final LogMonitorStdout sysoMonitor = new LogMonitorStdout(); private static final long start_ms = System.currentTimeMillis(); - + private static HashMap logs = new HashMap<>(); - - + + /** * Create a logger. If another with the name already exists, it'll be * retrieved instead of creating a new one. - * + * * @param logName log name (used for filename, should be application-unique) * @param logFile log file; old logs will be kept here too. * @param oldLogsCount number of old logs to keep, -1 infinite, 0 none. @@ -44,20 +44,20 @@ public class Log { public static synchronized LogWriter create(String logName, File logFile, int oldLogsCount) { if (logs.containsKey(logName)) return logs.get(logName); - + final ArchivingLog log = new ArchivingLog(logName, logFile, oldLogsCount); log.init(); - + logs.put(logName, log); - + return log; } - - + + /** * Create a logger. If another with the name already exists, it'll be * retrieved instead of creating a new one. - * + * * @param logName log name (used for filename, must be application-unique) * @param logFile log file; old logs will be kept here too. * @return the created Log instance @@ -66,53 +66,53 @@ public class Log { public static synchronized LogWriter create(String logName, File logFile) { if (logs.containsKey(logName)) return logs.get(logName); - + final SimpleLog log = new SimpleLog(logName, logFile); log.init(); - + logs.put(logName, log); - + return log; } - - + + public static void setMainLogger(LogWriter log) { main = log; } - - + + public static LogWriter getMainLogger() { return main; } - - + + public static void addMonitor(LogMonitor mon) { assertInited(); - + main.addMonitor(mon); } - - + + public static void removeMonitor(LogMonitor mon) { assertInited(); - + main.removeMonitor(mon); } - - + + private static void assertInited() { if (main == null) throw new IllegalStateException("Main logger not initialized."); } - - + + /** * Log a message - * + * * @param level message level * @param msg message text */ @@ -120,17 +120,17 @@ public class Log { { if (enabled) { sysoMonitor.onMessageLogged(level, formatMessage(level, msg, null, start_ms)); - + if (main != null) { main.log(level, msg); } } } - - + + /** * Log a message - * + * * @param level message level * @param msg message text * @param t thrown exception @@ -139,83 +139,83 @@ public class Log { { if (enabled) { sysoMonitor.onMessageLogged(level, formatMessage(level, msg, t, start_ms)); - + if (main != null) { main.log(level, msg, t); } } } - - + + /** * Log FINE message - * + * * @param msg message */ public static void f1(String msg) { log(Level.FINE, msg); } - - + + /** * Log FINER message - * + * * @param msg message */ public static void f2(String msg) { log(Level.FINER, msg); } - - + + /** * Log FINEST message - * + * * @param msg message */ public static void f3(String msg) { log(Level.FINEST, msg); } - - + + /** * Log INFO message - * + * * @param msg message */ public static void i(String msg) { log(Level.INFO, msg); } - - + + /** * Log WARNING message (less severe than ERROR) - * + * * @param msg message */ public static void w(String msg) { log(Level.WARNING, msg); } - - + + /** * Log ERROR message - * + * * @param msg message */ public static void e(String msg) { log(Level.SEVERE, msg); } - - + + /** * Log warning message with exception - * + * * @param msg message * @param thrown thrown exception */ @@ -223,22 +223,22 @@ public class Log { { log(Level.WARNING, msg, thrown); } - - + + /** * Log exception thrown as warning - * + * * @param thrown thrown exception */ public static void w(Throwable thrown) { log(Level.WARNING, null, thrown); } - - + + /** * Log error message - * + * * @param msg message * @param thrown thrown exception */ @@ -246,42 +246,42 @@ public class Log { { log(Level.SEVERE, msg, thrown); } - - + + /** * Log exception thrown as error - * + * * @param thrown thrown exception */ public static void e(Throwable thrown) { log(Level.SEVERE, null, thrown); } - - + + public static void enable(boolean flag) { enabled = flag; } - - + + public static void setSysoutLevel(Level level) { sysoMonitor.setLevel(level); } - - + + public static void setLevel(Level level) { assertInited(); - + main.setLevel(level); } - - + + /** * Get stack trace from throwable - * + * * @param t * @return trace */ @@ -294,31 +294,31 @@ public class Log { sw.flush(); return sw.toString(); } - - + + public static String formatMessage(Level level, String message, Throwable throwable, long start_ms) { if (message == null) message = ""; - + final String nl = System.getProperty("line.separator"); - + if (message.length() > 0) { if (message.equals("\n")) { return nl; } - + if (message.charAt(0) == '\n') { message = nl + message.substring(1); } } - + final long time_ms = (System.currentTimeMillis() - start_ms); final double time_s = time_ms / 1000D; final String time = String.format("%6.2f ", time_s); final String time_blank = StringUtil.repeat(" ", time.length()); - + String prefix = "[ ? ]"; - + if (level == Level.FINE) { prefix = "[ # ] "; } else if (level == Level.FINER) { @@ -332,13 +332,13 @@ public class Log { } else if (level == Level.WARNING) { prefix = "[!W!] "; } - + message = time + prefix + message.replaceAll("\n", nl + time_blank + prefix) + nl; - + if (throwable != null) { message += getStackTrace(throwable); } - + return message; } } diff --git a/src/mightypork/utils/logging/monitors/LogMonitor.java b/src/mightypork/utils/logging/monitors/LogMonitor.java index aaef36e..50552d6 100644 --- a/src/mightypork/utils/logging/monitors/LogMonitor.java +++ b/src/mightypork/utils/logging/monitors/LogMonitor.java @@ -5,32 +5,32 @@ import java.util.logging.Level; public abstract class LogMonitor { - + private boolean enabled = true; private Level accepted = Level.ALL; - - + + public void onMessageLogged(Level level, String message) { if (!enabled) return; if (accepted.intValue() > level.intValue()) return; - + logMessage(level, message); } - - + + protected abstract void logMessage(Level level, String message); - - + + public void setLevel(Level level) { this.accepted = level; } - - + + public void enable(boolean flag) { this.enabled = flag; } - + } diff --git a/src/mightypork/utils/logging/monitors/LogMonitorStdout.java b/src/mightypork/utils/logging/monitors/LogMonitorStdout.java index 964f6b5..c87dc59 100644 --- a/src/mightypork/utils/logging/monitors/LogMonitorStdout.java +++ b/src/mightypork/utils/logging/monitors/LogMonitorStdout.java @@ -5,7 +5,7 @@ import java.util.logging.Level; public class LogMonitorStdout extends LogMonitor { - + @Override protected void logMessage(Level level, String message) { @@ -15,5 +15,5 @@ public class LogMonitorStdout extends LogMonitor { System.out.print(message); } } - + } diff --git a/src/mightypork/utils/logging/writers/ArchivingLog.java b/src/mightypork/utils/logging/writers/ArchivingLog.java index c5f2cb8..a6a9f62 100644 --- a/src/mightypork/utils/logging/writers/ArchivingLog.java +++ b/src/mightypork/utils/logging/writers/ArchivingLog.java @@ -15,100 +15,102 @@ import mightypork.utils.string.StringUtil; /** * Logger that cleans directory & archives old logs - * + * * @author Ondřej Hruška (MightyPork) * @copy (c) 2014 */ public class ArchivingLog extends SimpleLog { - + /** Number of old logs to keep */ private final int logs_to_keep; - - + + /** * Log - * + * * @param name log name * @param file log file (in log directory) * @param oldLogCount number of old log files to keep: -1 all, 0 none. */ - public ArchivingLog(String name, File file, int oldLogCount) { + public ArchivingLog(String name, File file, int oldLogCount) + { super(name, file); this.logs_to_keep = oldLogCount; } - - + + /** * Log, not keeping 5 last log files (default); - * + * * @param name log name * @param file log file (in log directory) */ - public ArchivingLog(String name, File file) { + public ArchivingLog(String name, File file) + { super(name, file); this.logs_to_keep = 5; } - - + + @Override public void init() { cleanLoggingDirectory(); - + super.init(); } - - + + private void cleanLoggingDirectory() { if (logs_to_keep == 0) return; // overwrite - + final File log_file = getFile(); final File log_dir = log_file.getParentFile(); final String fname = FileUtil.getBasename(log_file.toString()); - + // move old file for (final File f : FileUtil.listDirectory(log_dir)) { if (!f.isFile()) continue; if (f.equals(getFile())) { - + final Date d = new Date(f.lastModified()); final String fbase = fname + '_' + (new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss")).format(d); final String suff = "." + getSuffix(); String cntStr = ""; File f2; - + for (int cnt = 0; (f2 = new File(log_dir, fbase + cntStr + suff)).exists(); cntStr = "_" + (++cnt)) {} - + if (!f.renameTo(f2)) throw new RuntimeException("Could not move log file."); } } - + if (logs_to_keep == -1) return; // keep all - + final List oldLogs = FileUtil.listDirectory(log_dir, new FileFilter() { - + @Override public boolean accept(File f) { if (f.isDirectory()) return false; if (!f.getName().endsWith(getSuffix())) return false; if (!f.getName().startsWith(fname)) return false; - + return true; } - + }); - + Collections.sort(oldLogs, new Comparator() { - + @Override public int compare(File o1, File o2) { return o1.getName().compareTo(o2.getName()); } }); - + // playing with fireee for (int i = 0; i < oldLogs.size() - logs_to_keep; i++) { if (!oldLogs.get(i).delete()) { @@ -116,8 +118,8 @@ public class ArchivingLog extends SimpleLog { } } } - - + + /** * @return log filename suffix */ diff --git a/src/mightypork/utils/logging/writers/LogWriter.java b/src/mightypork/utils/logging/writers/LogWriter.java index fc52f5b..cfbd7d5 100644 --- a/src/mightypork/utils/logging/writers/LogWriter.java +++ b/src/mightypork/utils/logging/writers/LogWriter.java @@ -8,65 +8,65 @@ import mightypork.utils.logging.monitors.LogMonitor; /** * Log interface - * + * * @author Ondřej Hruška (MightyPork) */ public interface LogWriter { - + /** * Prepare logs for logging */ void init(); - - + + /** * Add log monitor - * + * * @param mon monitor */ void addMonitor(LogMonitor mon); - - + + /** * Remove a monitor - * + * * @param removed monitor to remove */ void removeMonitor(LogMonitor removed); - - + + /** * Set logging level - * + * * @param level */ void setLevel(Level level); - - + + /** * Enable logging. - * + * * @param flag do enable logging */ void enable(boolean flag); - - + + /** * Log a message - * + * * @param level message level * @param msg message text */ void log(Level level, String msg); - - + + /** * Log a message - * + * * @param level message level * @param msg message text * @param t thrown exception */ void log(Level level, String msg, Throwable t); - + } diff --git a/src/mightypork/utils/logging/writers/SimpleLog.java b/src/mightypork/utils/logging/writers/SimpleLog.java index cd3b4bc..0c0ad6b 100644 --- a/src/mightypork/utils/logging/writers/SimpleLog.java +++ b/src/mightypork/utils/logging/writers/SimpleLog.java @@ -17,75 +17,76 @@ import mightypork.utils.logging.monitors.LogMonitor; /** * Basic logger - * + * * @author Ondřej Hruška (MightyPork) */ public class SimpleLog implements LogWriter { - + /** * Log file formatter. */ class LogFormatter extends Formatter { - + @Override public String format(LogRecord record) { return Log.formatMessage(record.getLevel(), record.getMessage(), record.getThrown(), started_ms); } } - + /** Log file */ private final File file; - + /** Log name */ private final String name; - + /** Logger instance. */ private Logger logger; - + private boolean enabled = true; private final HashSet monitors = new HashSet<>(); private final long started_ms; - - - public SimpleLog(String name, File file) { + + + public SimpleLog(String name, File file) + { this.name = name; this.file = file; this.started_ms = System.currentTimeMillis(); } - - + + @Override public void init() { logger = Logger.getLogger(getName()); - + FileHandler handler = null; try { handler = new FileHandler(getFile().getPath()); } catch (final Throwable t) { throw new RuntimeException("Failed to init log.", t); } - + handler.setFormatter(new LogFormatter()); logger.addHandler(handler); logger.setUseParentHandlers(false); logger.setLevel(Level.ALL); - + printHeader(); } - - + + protected void printHeader() { final String stamp = (new SimpleDateFormat("yyyy/MM/dd HH:mm:ss")).format(new Date()); log(Level.INFO, "Logger \"" + getName() + "\" initialized.\n" + stamp); } - - + + /** * Add log monitor - * + * * @param mon monitor */ @Override @@ -93,11 +94,11 @@ public class SimpleLog implements LogWriter { { monitors.add(mon); } - - + + /** * Remove a monitor - * + * * @param removed monitor to remove */ @Override @@ -105,61 +106,61 @@ public class SimpleLog implements LogWriter { { monitors.remove(removed); } - - + + @Override public void setLevel(Level level) { logger.setLevel(level); } - - + + @Override public void enable(boolean flag) { enabled = flag; } - - + + public File getFile() { return file; } - - + + public String getName() { return name; } - - + + @Override public void log(Level level, String msg) { if (enabled) { logger.log(level, msg); - + final String fmt = Log.formatMessage(level, msg, null, started_ms); - + for (final LogMonitor mon : monitors) { mon.onMessageLogged(level, fmt); } } } - - + + @Override public void log(Level level, String msg, Throwable t) { if (enabled) { logger.log(level, msg, t); - + final String fmt = Log.formatMessage(level, msg, t, started_ms); - + for (final LogMonitor mon : monitors) { mon.onMessageLogged(level, fmt); } } } - + } diff --git a/src/mightypork/utils/math/AlignX.java b/src/mightypork/utils/math/AlignX.java index a52cbc8..baa0c65 100644 --- a/src/mightypork/utils/math/AlignX.java +++ b/src/mightypork/utils/math/AlignX.java @@ -3,7 +3,7 @@ package mightypork.utils.math; /** * Horizontal align sides - * + * * @author Ondřej Hruška (MightyPork) */ public enum AlignX diff --git a/src/mightypork/utils/math/AlignY.java b/src/mightypork/utils/math/AlignY.java index 24f5faa..3c5aff4 100644 --- a/src/mightypork/utils/math/AlignY.java +++ b/src/mightypork/utils/math/AlignY.java @@ -3,7 +3,7 @@ package mightypork.utils.math; /** * Vertical align sides - * + * * @author Ondřej Hruška (MightyPork) */ public enum AlignY diff --git a/src/mightypork/utils/math/Calc.java b/src/mightypork/utils/math/Calc.java index e0d4bdd..134886a 100644 --- a/src/mightypork/utils/math/Calc.java +++ b/src/mightypork/utils/math/Calc.java @@ -13,22 +13,23 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Math utils - * + * * @author Ondřej Hruška (MightyPork) */ public final class Calc { - - private Calc() { + + private Calc() + { // not instantiable } - + /** Square root of two */ public static final double SQ2 = 1.41421356237; - - + + /** * Get distance from 2D line to 2D point [X,Y] - * + * * @param lineDirVec line directional vector * @param linePoint point of line * @param point point coordinate @@ -39,56 +40,56 @@ public final class Calc { // line point L[lx,ly] final double lx = linePoint.x(); final double ly = linePoint.y(); - + // line equation ax+by+c=0 final double a = -lineDirVec.y(); final double b = lineDirVec.x(); final double c = -a * lx - b * ly; - + // checked point P[x,y] final double x = point.x(); final double y = point.y(); - + // distance return Math.abs(a * x + b * y + c) / Math.sqrt(a * a + b * b); } - + public static final Random rand = new Random(); - - + + public static double sphereSurface(double radius) { return 4D * Math.PI * square(radius); } - - + + public static double sphereVolume(double radius) { return (4D / 3D) * Math.PI * cube(radius); } - - + + public static double sphereRadius(double volume) { return Math.cbrt((3D * volume) / (4 * Math.PI)); } - - + + public static double circleSurface(double radius) { return Math.PI * square(radius); } - - + + public static double circleRadius(double surface) { return Math.sqrt(surface / Math.PI); } - - + + /** * Safe equals that works with nulls - * + * * @param a * @param b * @return are equal @@ -97,11 +98,11 @@ public final class Calc { { return a == null ? b == null : a.equals(b); } - - + + /** * Clamp integer - * + * * @param number * @param min * @param max @@ -111,11 +112,11 @@ public final class Calc { { return number < min ? min : number > max ? max : number; } - - + + /** * Clamp double - * + * * @param number * @param min * @param max @@ -125,17 +126,17 @@ public final class Calc { { return number < min ? min : number > max ? max : number; } - - + + public static boolean isInRange(double number, double left, double right) { return number >= left && number <= right; } - - + + /** * Get number from A to B at delta time (A -> B) - * + * * @param from * @param to * @param elapsed progress ratio 0..1 @@ -146,11 +147,11 @@ public final class Calc { { return from + (to - from) * easing.get(elapsed); } - - + + /** * Get angle [degrees] from A to B at delta time (tween A to B) - * + * * @param from * @param to * @param elapsed progress ratio 0..1 @@ -161,11 +162,11 @@ public final class Calc { { return Deg.norm(from - Deg.delta(to, from) * easing.get(elapsed)); } - - + + /** * Get angle [radians] from A to B at delta time (tween A to B) - * + * * @param from * @param to * @param elapsed progress ratio 0..1 @@ -176,8 +177,8 @@ public final class Calc { { return Rad.norm(from - Rad.delta(to, from) * easing.get(elapsed)); } - - + + public static double max(double... numbers) { double highest = numbers[0]; @@ -186,8 +187,8 @@ public final class Calc { } return highest; } - - + + public static int max(int... numbers) { int highest = numbers[0]; @@ -196,8 +197,8 @@ public final class Calc { } return highest; } - - + + public static double min(double... numbers) { double lowest = numbers[0]; @@ -206,8 +207,8 @@ public final class Calc { } return lowest; } - - + + public static int min(int... numbers) { int lowest = numbers[0]; @@ -216,11 +217,11 @@ public final class Calc { } return lowest; } - - + + /** * Split comma separated list of integers. - * + * * @param list String containing the list. * @param delimiter delimiter character * @return array of integers or null. @@ -230,24 +231,24 @@ public final class Calc { if (list == null) { return null; } - + final String[] parts = list.split(Character.toString(delimiter)); - + final ArrayList intList = new ArrayList<>(); - + for (final String part : parts) { try { intList.add(Integer.parseInt(part.trim())); } catch (final NumberFormatException e) {} } - + return intList; } - - + + /** * Pick random element from a given list. - * + * * @param list list of choices * @return picked element */ @@ -255,11 +256,11 @@ public final class Calc { { return pick(rand, list); } - - + + /** * Pick random element from a given list. - * + * * @param rand RNG * @param list list of choices * @return picked element @@ -269,11 +270,11 @@ public final class Calc { if (list.size() == 0) return null; return list.get(rand.nextInt(list.size())); } - - + + /** * Take a square - * + * * @param a value * @return value squared */ @@ -281,11 +282,11 @@ public final class Calc { { return a * a; } - - + + /** * Take a cube - * + * * @param a value * @return value cubed */ @@ -293,8 +294,8 @@ public final class Calc { { return a * a * a; } - - + + /** * @param d number * @return fractional part @@ -303,11 +304,11 @@ public final class Calc { { return d - Math.floor(d); } - - + + /** * Make sure value is within array length. - * + * * @param index tested index * @param length array length * @throws IndexOutOfBoundsException if the index is not in range. @@ -318,11 +319,11 @@ public final class Calc { throw new IndexOutOfBoundsException(); } } - - + + /** * Get distance of two coordinates in 2D plane - * + * * @param x1 first coordinate X * @param y1 first coordinate y * @param x2 second coordinate X @@ -333,24 +334,24 @@ public final class Calc { { return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2)); } - - + + public static int randInt(Random rand, int low, int high) { final int range = Math.abs(high - low) + 1; return low + rand.nextInt(range); } - - + + public static int randInt(int low, int high) { return randInt(rand, low, high); } - - + + /** * Get ordinal version of numbers (1 = 1st, 5 = 5th etc.) - * + * * @param number number * @return ordinal, string */ @@ -363,11 +364,11 @@ public final class Calc { } return number + "th"; } - - + + /** * Format number with thousands separated. - * + * * @param number number * @param thousandSep * @return string @@ -377,18 +378,18 @@ public final class Calc { final String num = String.valueOf(number); final String dot = String.valueOf(thousandSep); String out = ""; - + int cnt = 1; for (int i = num.length() - 1; i >= 0; i--) { out = num.charAt(i) + out; if (cnt % 3 == 0 && i > 0) out = dot + out; cnt++; } - + return out; } - - + + public static int countBits(byte b) { int c = 0; diff --git a/src/mightypork/utils/math/Polar.java b/src/mightypork/utils/math/Polar.java index 8f32e73..b455303 100644 --- a/src/mightypork/utils/math/Polar.java +++ b/src/mightypork/utils/math/Polar.java @@ -6,44 +6,46 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Polar coordinate - * + * * @author Ondřej Hruška (MightyPork) */ public class Polar { - + /** angle in radians */ private double angle = 0; - + /** distance in units */ private double radius = 0; - + private Vect coord = null; - - + + /** * Create a polar - * + * * @param angle angle in RAD * @param distance distance from origin */ - public Polar(double angle, double distance) { + public Polar(double angle, double distance) + { this(angle, false, distance); } - - + + /** * Create a polar - * + * * @param angle angle * @param deg angle is in DEG * @param distance radius */ - public Polar(double angle, boolean deg, double distance) { + public Polar(double angle, boolean deg, double distance) + { this.radius = distance; this.angle = deg ? Math.toRadians(angle) : angle; } - - + + /** * @return angle in RAD */ @@ -51,8 +53,8 @@ public class Polar { { return angle; } - - + + /** * @return angle in DEG */ @@ -60,8 +62,8 @@ public class Polar { { return Math.toDegrees(angle); } - - + + /** * @param angle angle in RAD */ @@ -69,8 +71,8 @@ public class Polar { { this.angle = angle; } - - + + /** * @param angle angle in DEG */ @@ -78,8 +80,8 @@ public class Polar { { this.angle = Math.toRadians(angle); } - - + + /** * @return radius */ @@ -87,8 +89,8 @@ public class Polar { { return radius; } - - + + /** * @param r radius */ @@ -96,24 +98,24 @@ public class Polar { { this.radius = r; } - - + + /** * Make polar from coord - * + * * @param coord coord * @return polar */ public static Polar fromCoord(Vect coord) { return Polar.fromCoord(coord.x(), coord.y()); - + } - - + + /** * Make polar from coords - * + * * @param x x coord * @param y y coord * @return polar @@ -122,46 +124,46 @@ public class Polar { { final double a = Math.atan2(y, x); final double r = Math.sqrt(x * x + y * y); - + return new Polar(a, r); } - - + + /** * Get coord from polar - * + * * @return coord */ public Vect toCoord() { // lazy init if (coord == null) coord = new Vect() { - + @Override public double x() { return radius * Math.cos(angle); } - - + + @Override public double y() { return radius * Math.sin(angle); } }; - + return coord; } - - + + @Override public String toString() { return "Polar(" + angle + "rad, " + radius + ")"; } - - + + @Override public int hashCode() { @@ -174,8 +176,8 @@ public class Polar { result = prime * result + (int) (temp ^ (temp >>> 32)); return result; } - - + + @Override public boolean equals(Object obj) { diff --git a/src/mightypork/utils/math/Range.java b/src/mightypork/utils/math/Range.java index 63f9db4..53f0675 100644 --- a/src/mightypork/utils/math/Range.java +++ b/src/mightypork/utils/math/Range.java @@ -6,82 +6,85 @@ import java.util.Random; /** * Numeric range, able to generate random numbers and give min/max values. - * + * * @author Ondřej Hruška (MightyPork) */ public class Range { - + public static Range make(double low, double high) { return new Range(low, high); } - + private double min = 0; private double max = 1; - - + + /** * Implicit range constructor 0-1 */ - public Range() { + public Range() + { } - - + + /** * Create new range - * + * * @param min min number * @param max max number */ - public Range(double min, double max) { + public Range(double min, double max) + { this.min = min; this.max = max; norm(); } - - + + /** * Create new range - * + * * @param minmax min = max number */ - public Range(double minmax) { + public Range(double minmax) + { this.min = minmax; this.max = minmax; } - - + + public static Range fromString(String string) { try { String s = string.trim(); - + // drop whitespace s = s.replaceAll("\\s", ""); - + // drop brackets s = s.replaceAll("[\\(\\[\\{\\)\\]\\}]", ""); - + // norm separators s = s.replaceAll("[:;]", "|").replace("..", "|"); - + // norm floating point s = s.replaceAll("[,]", "."); - + // dash to pipe, if not a minus sign s = s.replaceAll("([0-9])\\s?[\\-]", "$1|"); - + final String[] parts = s.split("[|]"); - + if (parts.length >= 1) { - + final double low = Double.parseDouble(parts[0].trim()); - + if (parts.length == 2) { final double high = Double.parseDouble(parts[1].trim()); return Range.make(low, high); } - + return Range.make(low, low); } } catch (final RuntimeException e) { @@ -89,15 +92,15 @@ public class Range { } return null; } - - + + @Override public String toString() { return String.format("(%f : %f)", getMin(), getMax()); } - - + + /** * Make sure min is <= max */ @@ -109,33 +112,33 @@ public class Range { max = t; } } - - + + /** * Get random integer from range - * + * * @return random int */ public int randInt() { return randInt(Calc.rand); } - - + + /** * Get random double from this range - * + * * @return random double */ public double randDouble() { return randDouble(Calc.rand); } - - + + /** * Get random integer from range - * + * * @param rand RNG * @return random int */ @@ -143,11 +146,11 @@ public class Range { { return Calc.randInt(rand, (int) Math.round(min), (int) Math.round(min)); } - - + + /** * Get random double from this range - * + * * @param rand RNG * @return random double */ @@ -155,33 +158,33 @@ public class Range { { return min + rand.nextDouble() * (max - min); } - - + + /** * Get min - * + * * @return min number */ public double getMin() { return min; } - - + + /** * Get max - * + * * @return max number */ public double getMax() { return max; } - - + + /** * Set min - * + * * @param min min value */ public void setMin(double min) @@ -189,11 +192,11 @@ public class Range { this.min = min; norm(); } - - + + /** * Set max - * + * * @param max max value */ public void setMax(double max) @@ -201,22 +204,22 @@ public class Range { this.max = max; norm(); } - - + + /** * Get identical copy - * + * * @return copy */ public Range copy() { return new Range(min, max); } - - + + /** * Set to value of other range - * + * * @param other copied range */ public void setTo(Range other) @@ -226,11 +229,11 @@ public class Range { max = other.max; norm(); } - - + + /** * Set to min-max values - * + * * @param min min value * @param max max value */ diff --git a/src/mightypork/utils/math/algo/Coord.java b/src/mightypork/utils/math/algo/Coord.java index 8e7ad2b..df74a2c 100644 --- a/src/mightypork/utils/math/algo/Coord.java +++ b/src/mightypork/utils/math/algo/Coord.java @@ -9,63 +9,66 @@ import mightypork.utils.math.constraints.vect.VectConst; /** * Very simple integer coordinate - * + * * @author Ondřej Hruška (MightyPork) */ public class Coord { - + public int x; public int y; - - + + @FactoryMethod public static Coord make(int x, int y) { return new Coord(x, y); } - - + + @FactoryMethod public static Coord make(Coord other) { return new Coord(other); } - - + + @FactoryMethod public static Coord zero() { return make(0, 0); } - - - public Coord() { + + + public Coord() + { // for ion } - - - public Coord(int x, int y) { + + + public Coord(int x, int y) + { super(); this.x = x; this.y = y; } - - - public Coord(Coord other) { + + + public Coord(Coord other) + { this.x = other.x; this.y = other.y; } - - + + public Coord add(int addX, int addY) { return new Coord(x + addX, y + addY); } - - + + /** * Add other coord in a copy - * + * * @param added * @return changed copy */ @@ -73,36 +76,36 @@ public class Coord { { return add(added.x, added.y); } - - + + public Coord add(Move added) { return add(added.x(), added.y()); } - - + + public Coord copy() { return make(this); } - - + + public void setTo(int x, int y) { this.x = x; this.y = y; } - - + + public void setTo(Coord pos) { setTo(pos.x, pos.y); } - - + + /** * Check if coord is in a range (inclusive) - * + * * @param x0 range min x * @param y0 range min y * @param x1 range max x @@ -113,27 +116,27 @@ public class Coord { { return !(x < x0 || x > x1 || y < y0 || y > y1); } - - + + public double dist(Coord coord) { return Calc.dist(x, y, coord.x, coord.y); } - - + + public VectConst toVect() { return Vect.make(x, y); } - - + + @Override public String toString() { return "Coord(" + x + "," + y + ")"; } - - + + @Override public int hashCode() { @@ -143,8 +146,8 @@ public class Coord { result = prime * result + y; return result; } - - + + @Override public boolean equals(Object obj) { @@ -156,8 +159,8 @@ public class Coord { if (y != other.y) return false; return true; } - - + + public static Coord fromVect(Vect vect) { return make((int) Math.floor(vect.x()), (int) Math.floor(vect.y())); diff --git a/src/mightypork/utils/math/algo/Move.java b/src/mightypork/utils/math/algo/Move.java index c9f7fbe..f97d7cf 100644 --- a/src/mightypork/utils/math/algo/Move.java +++ b/src/mightypork/utils/math/algo/Move.java @@ -4,60 +4,61 @@ package mightypork.utils.math.algo; /** * Path step.
* Must be binary in order to be saveable in lists. - * + * * @author Ondřej Hruška (MightyPork) */ public class Move { - + public static final Move NORTH = new Move(0, -1); public static final Move SOUTH = new Move(0, 1); public static final Move EAST = new Move(1, 0); public static final Move WEST = new Move(-1, 0); public static final Move NONE = new Move(0, 0); - - + + public static Move make(int x, int y) { x = x < 0 ? -1 : x > 0 ? 1 : 0; y = y < 0 ? -1 : y > 0 ? 1 : 0; - + if (y == -1 && x == 0) return NORTH; if (y == 1 && x == 0) return SOUTH; if (x == -1 && y == 0) return WEST; if (x == 1 && y == 0) return EAST; if (x == 0 && y == 0) return NONE; - + return new Move(x, y); } - + private final byte x; private final byte y; - - - public Move(int x, int y) { + + + public Move(int x, int y) + { this.x = (byte) (x < 0 ? -1 : x > 0 ? 1 : 0); this.y = (byte) (y < 0 ? -1 : y > 0 ? 1 : 0); } - - + + public int x() { return x; } - - + + public int y() { return y; } - - + + public Coord toCoord() { return Coord.make(x, y); } - - + + @Override public String toString() { diff --git a/src/mightypork/utils/math/algo/Moves.java b/src/mightypork/utils/math/algo/Moves.java index 7c466ad..8877a23 100644 --- a/src/mightypork/utils/math/algo/Moves.java +++ b/src/mightypork/utils/math/algo/Moves.java @@ -11,11 +11,11 @@ import mightypork.utils.math.Calc; /** * Move lists, bit masks and other utilities - * + * * @author Ondřej Hruška (MightyPork) */ public class Moves { - + public static final byte BIT_NW = (byte) 0b10000000; public static final byte BIT_N = (byte) 0b01000000; public static final byte BIT_NE = (byte) 0b00100000; @@ -24,15 +24,15 @@ public class Moves { public static final byte BIT_S = (byte) 0b00000100; public static final byte BIT_SW = (byte) 0b00000010; public static final byte BIT_W = (byte) 0b00000001; - + public static final byte BITS_CARDINAL = BIT_N | BIT_S | BIT_E | BIT_W; public static final byte BITS_DIAGONAL = BIT_NE | BIT_NW | BIT_SE | BIT_SW; - + public static final byte BITS_NW_CORNER = BIT_W | BIT_NW | BIT_N; public static final byte BITS_NE_CORNER = BIT_E | BIT_NE | BIT_N; public static final byte BITS_SW_CORNER = BIT_W | BIT_SW | BIT_S; public static final byte BITS_SE_CORNER = BIT_E | BIT_SE | BIT_S; - + public static final Move NW = Move.make(-1, -1); public static final Move N = Move.make(0, -1); public static final Move NE = Move.make(1, -1); @@ -41,32 +41,32 @@ public class Moves { public static final Move S = Move.make(0, 1); public static final Move SW = Move.make(-1, 1); public static final Move W = Move.make(-1, 0); - - //@formatter:off + + //@formatter:off /** All sides, in the order of bits. */ public final static List ALL_SIDES = Collections.unmodifiableList(Arrays.asList( - NW, - N, - NE, - E, - SE, - S, - SW, - W - )); - + NW, + N, + NE, + E, + SE, + S, + SW, + W + )); + public final static List CARDINAL_SIDES = Collections.unmodifiableList(Arrays.asList( - N, - E, - S, - W - )); - + N, + E, + S, + W + )); + //@formatter:on - + /** * Get element from all sides - * + * * @param i side index * @return the side coord */ @@ -74,20 +74,20 @@ public class Moves { { return ALL_SIDES.get(i); } - - + + public static byte getBit(int i) { return (byte) (1 << (7 - i)); } - - + + public static Move randomCardinal() { return Calc.pick(CARDINAL_SIDES); } - - + + public static Move randomCardinal(Random rand) { return Calc.pick(rand, CARDINAL_SIDES); diff --git a/src/mightypork/utils/math/algo/floodfill/FloodFill.java b/src/mightypork/utils/math/algo/floodfill/FloodFill.java index a9a8198..2e12bc8 100644 --- a/src/mightypork/utils/math/algo/floodfill/FloodFill.java +++ b/src/mightypork/utils/math/algo/floodfill/FloodFill.java @@ -11,33 +11,33 @@ import mightypork.utils.math.algo.Move; public abstract class FloodFill { - + public abstract boolean canEnter(Coord pos); - - + + public abstract boolean canSpreadFrom(Coord pos); - - + + public abstract List getSpreadSides(); - - + + /** * Get the max distance filled form start point. Use -1 for unlimited range. - * + * * @return max distance */ public abstract double getMaxDistance(); - - + + /** * @return true if start should be spread no matter what */ public abstract boolean forceSpreadStart(); - - + + /** * Fill an area - * + * * @param start start point * @param foundNodes collection to put filled coords in * @return true if fill was successful; false if max range was reached. @@ -45,32 +45,32 @@ public abstract class FloodFill { public final boolean fill(Coord start, Collection foundNodes) { final Queue activeNodes = new LinkedList<>(); - + final double maxDist = getMaxDistance(); - + activeNodes.add(start); - + boolean forceSpreadNext = forceSpreadStart(); - + boolean limitReached = false; - + while (!activeNodes.isEmpty()) { final Coord current = activeNodes.poll(); foundNodes.add(current); - + if (!canSpreadFrom(current) && !forceSpreadNext) continue; - + forceSpreadNext = false; - + for (final Move spr : getSpreadSides()) { final Coord next = current.add(spr); if (activeNodes.contains(next) || foundNodes.contains(next)) continue; - + if (next.dist(start) > maxDist) { limitReached = true; continue; } - + if (canEnter(next)) { activeNodes.add(next); } else { @@ -78,7 +78,7 @@ public abstract class FloodFill { } } } - + return !limitReached; } } diff --git a/src/mightypork/utils/math/algo/pathfinding/Heuristic.java b/src/mightypork/utils/math/algo/pathfinding/Heuristic.java index ed1d913..a035ccb 100644 --- a/src/mightypork/utils/math/algo/pathfinding/Heuristic.java +++ b/src/mightypork/utils/math/algo/pathfinding/Heuristic.java @@ -5,10 +5,10 @@ import mightypork.utils.math.algo.Coord; public abstract class Heuristic { - + /** * Get tile cost (estimate of how many tiles remain to the target) - * + * * @param pos current pos * @param target target pos * @return estimated number of tiles diff --git a/src/mightypork/utils/math/algo/pathfinding/PathFinder.java b/src/mightypork/utils/math/algo/pathfinding/PathFinder.java index 46ea1a5..3a77647 100644 --- a/src/mightypork/utils/math/algo/pathfinding/PathFinder.java +++ b/src/mightypork/utils/math/algo/pathfinding/PathFinder.java @@ -15,34 +15,34 @@ import mightypork.utils.math.algo.pathfinding.heuristics.ManhattanHeuristic; /** * A* pathfinder - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class PathFinder { - + private static final FComparator F_COMPARATOR = new FComparator(); - + public static final Heuristic CORNER_HEURISTIC = new ManhattanHeuristic(); public static final Heuristic DIAGONAL_HEURISTIC = new DiagonalHeuristic(); - + private boolean ignoreStart; private boolean ignoreEnd; - - + + public List findPathRelative(Coord start, Coord end) { return findPathRelative(start, end, ignoreStart, ignoreEnd); } - - + + public List findPathRelative(Coord start, Coord end, boolean ignoreStart, boolean ignoreEnd) { final List path = findPath(start, end, ignoreStart, ignoreEnd); - + if (path == null) return null; - + final List out = new ArrayList<>(); - + final Coord current = start.copy(); for (final Coord c : path) { if (c.equals(current)) continue; @@ -50,24 +50,24 @@ public abstract class PathFinder { current.x = c.x; current.y = c.y; } - + return out; } - - + + public List findPath(Coord start, Coord end) { return findPath(start, end, ignoreStart, ignoreEnd); } - - + + public List findPath(Coord start, Coord end, boolean ignoreStart, boolean ignoreEnd) { final LinkedList open = new LinkedList<>(); final LinkedList closed = new LinkedList<>(); - + final Heuristic heuristic = getHeuristic(); - + // add first node { final Node n = new Node(start); @@ -75,37 +75,37 @@ public abstract class PathFinder { n.g_cost = 0; open.add(n); } - + Node current = null; - + while (true) { current = open.poll(); - + if (current == null) { break; } - + closed.add(current); - + if (current.pos.equals(end)) { break; } - + for (final Move go : getWalkSides()) { - + final Coord c = current.pos.add(go); if (!isAccessible(c) && !(c.equals(end) && ignoreEnd) && !(c.equals(start) && ignoreStart)) continue; final Node a = new Node(c); a.g_cost = current.g_cost + getCost(c, a.pos); a.h_cost = (int) (heuristic.getCost(a.pos, end) * getMinCost()); a.parent = current; - + if (!closed.contains(a)) { - + if (open.contains(a)) { - + boolean needSort = false; - + // find where it is for (final Node n : open) { if (n.pos.equals(a.pos)) { // found it @@ -117,51 +117,52 @@ public abstract class PathFinder { break; } } - + if (needSort) Collections.sort(open, F_COMPARATOR); - + } else { open.add(a); } } } - + } - + if (current == null) { return null; // no path found } - + final LinkedList path = new LinkedList<>(); - + // extract path elements while (current != null) { path.addFirst(current.pos); current = current.parent; } - + return path; } - + private static class Node { - + Coord pos; int g_cost; // to get there int h_cost; // to target Node parent; - - - public Node(Coord pos) { + + + public Node(Coord pos) + { this.pos = pos; } - - + + int fCost() { return g_cost + h_cost; } - - + + @Override public int hashCode() { @@ -170,8 +171,8 @@ public abstract class PathFinder { result = prime * result + ((pos == null) ? 0 : pos.hashCode()); return result; } - - + + @Override public boolean equals(Object obj) { @@ -184,63 +185,63 @@ public abstract class PathFinder { } else if (!pos.equals(other.pos)) return false; return true; } - - + + @Override public String toString() { return "N " + pos + ", G =" + g_cost + ", H = " + h_cost; } } - + private static class FComparator implements Comparator { - + @Override public int compare(Node n1, Node n2) { return n1.fCost() - n2.fCost(); } } - - + + public void setIgnoreEnd(boolean ignoreEnd) { this.ignoreEnd = ignoreEnd; } - - + + public void setIgnoreStart(boolean ignoreStart) { this.ignoreStart = ignoreStart; } - - + + /** * @return used heuristic */ protected abstract Heuristic getHeuristic(); - - + + protected abstract List getWalkSides(); - - + + /** * @param pos tile pos * @return true if the tile is walkable */ public abstract boolean isAccessible(Coord pos); - - + + /** * Cost of walking onto a tile. It's useful to use ie. 10 for basic step. - * + * * @param from last tile * @param to current tile * @return cost */ protected abstract int getCost(Coord from, Coord to); - - + + /** * @return lowest cost. Used to multiply heuristics. */ diff --git a/src/mightypork/utils/math/algo/pathfinding/PathFinderProxy.java b/src/mightypork/utils/math/algo/pathfinding/PathFinderProxy.java index bf21ab3..e4984f7 100644 --- a/src/mightypork/utils/math/algo/pathfinding/PathFinderProxy.java +++ b/src/mightypork/utils/math/algo/pathfinding/PathFinderProxy.java @@ -10,51 +10,52 @@ import mightypork.utils.math.algo.Move; /** * Pathfinder proxy. Can be used to override individual methods but keep the * rest as is. - * + * * @author Ondřej Hruška (MightyPork) */ public class PathFinderProxy extends PathFinder { - + private final PathFinder source; - - - public PathFinderProxy(PathFinder other) { + + + public PathFinderProxy(PathFinder other) + { this.source = other; } - - + + @Override public boolean isAccessible(Coord pos) { return source.isAccessible(pos); } - - + + @Override public int getCost(Coord from, Coord to) { return source.getCost(from, to); } - - + + @Override public int getMinCost() { return source.getMinCost(); } - - + + @Override protected Heuristic getHeuristic() { return source.getHeuristic(); } - - + + @Override protected List getWalkSides() { return source.getWalkSides(); } - + } diff --git a/src/mightypork/utils/math/algo/pathfinding/heuristics/DiagonalHeuristic.java b/src/mightypork/utils/math/algo/pathfinding/heuristics/DiagonalHeuristic.java index 4820eac..1bdc684 100644 --- a/src/mightypork/utils/math/algo/pathfinding/heuristics/DiagonalHeuristic.java +++ b/src/mightypork/utils/math/algo/pathfinding/heuristics/DiagonalHeuristic.java @@ -6,7 +6,7 @@ import mightypork.utils.math.algo.pathfinding.Heuristic; public class DiagonalHeuristic extends Heuristic { - + @Override public double getCost(Coord pos, Coord target) { diff --git a/src/mightypork/utils/math/algo/pathfinding/heuristics/ManhattanHeuristic.java b/src/mightypork/utils/math/algo/pathfinding/heuristics/ManhattanHeuristic.java index 9725794..d869054 100644 --- a/src/mightypork/utils/math/algo/pathfinding/heuristics/ManhattanHeuristic.java +++ b/src/mightypork/utils/math/algo/pathfinding/heuristics/ManhattanHeuristic.java @@ -6,7 +6,7 @@ import mightypork.utils.math.algo.pathfinding.Heuristic; public class ManhattanHeuristic extends Heuristic { - + @Override public double getCost(Coord pos, Coord target) { diff --git a/src/mightypork/utils/math/angles/Angles.java b/src/mightypork/utils/math/angles/Angles.java index 20c1cec..263aacf 100644 --- a/src/mightypork/utils/math/angles/Angles.java +++ b/src/mightypork/utils/math/angles/Angles.java @@ -3,14 +3,14 @@ package mightypork.utils.math.angles; /** * Common angles functionality - * + * * @author Ondřej Hruška (MightyPork) */ class Angles { - + /** * Delta of two angles (positive or negative - positive is CCW) - * + * * @param alpha first angle * @param beta second angle * @param fullAngle value of full angle @@ -22,14 +22,14 @@ class Angles { alpha = norm(alpha + fullAngle / 2D, fullAngle); beta = norm(beta + fullAngle / 2D, fullAngle); } - + return beta - alpha; } - - + + /** * Difference of two angles (same as delta, but always positive) - * + * * @param alpha first angle * @param beta second angle * @param fullAngle value of full angle @@ -39,11 +39,11 @@ class Angles { { return Math.abs(delta(alpha, beta, fullAngle)); } - - + + /** * Normalize angle to 0-full range - * + * * @param angle angle * @param fullAngle full angle * @return angle normalized diff --git a/src/mightypork/utils/math/angles/Deg.java b/src/mightypork/utils/math/angles/Deg.java index f9e0f4a..c39b96e 100644 --- a/src/mightypork/utils/math/angles/Deg.java +++ b/src/mightypork/utils/math/angles/Deg.java @@ -3,11 +3,11 @@ package mightypork.utils.math.angles; /** * Angle calculations for degrees. - * + * * @author Ondřej Hruška (MightyPork) */ public class Deg { - + /** 180° in degrees */ public static final double a180 = 180; /** 270° in degrees */ @@ -18,11 +18,11 @@ public class Deg { public static final double a45 = 45; /** 90° in degrees */ public static final double a90 = 90; - - + + /** * Subtract two angles alpha - beta - * + * * @param alpha first angle * @param beta second angle * @return (alpha - beta) in degrees @@ -31,11 +31,11 @@ public class Deg { { return Angles.delta(alpha, beta, a360); } - - + + /** * Difference of two angles (absolute value of delta) - * + * * @param alpha first angle * @param beta second angle * @return difference in radians @@ -44,11 +44,11 @@ public class Deg { { return Angles.diff(alpha, beta, a360); } - - + + /** * Cosinus in degrees - * + * * @param deg angle in degrees * @return cosinus */ @@ -56,11 +56,11 @@ public class Deg { { return Math.cos(toRad(deg)); } - - + + /** * Sinus in degrees - * + * * @param deg angle in degrees * @return sinus */ @@ -68,11 +68,11 @@ public class Deg { { return Math.sin(toRad(deg)); } - - + + /** * Tangents in degrees - * + * * @param deg angle in degrees * @return tangents */ @@ -80,11 +80,11 @@ public class Deg { { return Math.tan(toRad(deg)); } - - + + /** * Angle normalized to 0-360 range - * + * * @param angle angle to normalize * @return normalized angle */ @@ -92,11 +92,11 @@ public class Deg { { return Angles.norm(angle, a360); } - - + + /** * Convert to radians - * + * * @param deg degrees * @return radians */ @@ -104,11 +104,11 @@ public class Deg { { return Math.toRadians(deg); } - - + + /** * Round angle to 0,45,90,135... - * + * * @param deg angle in deg. to round * @param increment rounding increment (45 - round to 0,45,90...) * @return rounded @@ -123,11 +123,11 @@ public class Deg { if (a == 360) a = 0; return (int) Math.round(a); } - - + + /** * Round angle to 0,15,30,45,60,75,90... - * + * * @param deg angle in deg to round * @return rounded */ @@ -135,11 +135,11 @@ public class Deg { { return roundToIncrement(deg, 15); } - - + + /** * Round angle to 0,45,90,135... - * + * * @param deg angle in deg. to round * @return rounded */ @@ -147,11 +147,11 @@ public class Deg { { return roundToIncrement(deg, 45); } - - + + /** * Round angle to 0,90,180,270 - * + * * @param deg angle in deg. to round * @return rounded */ diff --git a/src/mightypork/utils/math/angles/Rad.java b/src/mightypork/utils/math/angles/Rad.java index ffe088f..3e45106 100644 --- a/src/mightypork/utils/math/angles/Rad.java +++ b/src/mightypork/utils/math/angles/Rad.java @@ -3,11 +3,11 @@ package mightypork.utils.math.angles; /** * Angle calculations for radians. - * + * * @author Ondřej Hruška (MightyPork) */ public class Rad { - + /** 180° in radians */ public static final double a180 = Math.PI; /** 270° in radians */ @@ -18,11 +18,11 @@ public class Rad { public static final double a45 = Math.PI / 4D; /** 90° in radians */ public static final double a90 = Math.PI / 2D; - - + + /** * Subtract two angles alpha - beta - * + * * @param alpha first angle * @param beta second angle * @return (alpha - beta) in radians @@ -31,11 +31,11 @@ public class Rad { { return Angles.delta(alpha, beta, a360); } - - + + /** * Difference of two angles (absolute value of delta) - * + * * @param alpha first angle * @param beta second angle * @return difference in radians @@ -44,11 +44,11 @@ public class Rad { { return Angles.delta(alpha, beta, a360); } - - + + /** * Cos - * + * * @param rad angle in rads * @return cos */ @@ -56,11 +56,11 @@ public class Rad { { return Math.cos(rad); } - - + + /** * Sin - * + * * @param rad angle in rads * @return sin */ @@ -68,11 +68,11 @@ public class Rad { { return Math.sin(rad); } - - + + /** * Tan - * + * * @param rad angle in rads * @return tan */ @@ -80,11 +80,11 @@ public class Rad { { return Math.tan(rad); } - - + + /** * Angle normalized to 0-2*PI range - * + * * @param angle angle to normalize * @return normalized angle */ @@ -92,11 +92,11 @@ public class Rad { { return Angles.norm(angle, a360); } - - + + /** * Convert to degrees - * + * * @param rad radians * @return degrees */ diff --git a/src/mightypork/utils/math/animation/Animator.java b/src/mightypork/utils/math/animation/Animator.java index 2486e21..e5cc6c9 100644 --- a/src/mightypork/utils/math/animation/Animator.java +++ b/src/mightypork/utils/math/animation/Animator.java @@ -10,124 +10,128 @@ import mightypork.utils.math.constraints.num.NumBound; public abstract class Animator implements NumBound, Updateable, Pauseable { - + private final NumAnimated numAnim; private final Num animatorValue; private final double highValue; private final double lowValue; - - - public Animator(double period) { + + + public Animator(double period) + { this(0, 1, period, Easing.LINEAR); } - - - public Animator(double start, double end, double period) { + + + public Animator(double start, double end, double period) + { this(start, end, period, Easing.LINEAR); } - - - public Animator(double period, Easing easing) { + + + public Animator(double period, Easing easing) + { this(0, 1, period, easing); } - - - public Animator(double start, double end, double period, Easing easing) { + + + public Animator(double start, double end, double period, Easing easing) + { numAnim = new NumAnimated(0, easing); numAnim.setDefaultDuration(period); - + this.lowValue = start; this.highValue = end; - + this.animatorValue = numAnim.mul(end - start).add(start); } - - + + @Override public void pause() { numAnim.pause(); } - - + + public void start() { resume(); } - - + + @Override public void resume() { numAnim.resume(); } - - + + @Override public boolean isPaused() { return numAnim.isPaused(); } - - + + public void reset() { numAnim.reset(); } - - + + public void restart() { reset(); resume(); } - - + + public void setDuration(double secs) { numAnim.setDefaultDuration(secs); } - - + + public double getDuration() { return numAnim.getDefaultDuration(); } - - + + @Override public Num getNum() { return animatorValue; } - - + + public double getValue() { return animatorValue.value(); } - - + + @Override public void update(double delta) { numAnim.update(delta); if (numAnim.isFinished()) nextCycle(numAnim); } - - + + @Stub protected abstract void nextCycle(NumAnimated anim); - - + + public void setProgress(double value) { final double target = numAnim.getEnd(); numAnim.setTo(Calc.clamp(value, lowValue, highValue)); numAnim.animate((target < value ? highValue : lowValue), target, numAnim.getDefaultDuration()); } - - + + public double getProgress() { return numAnim.value(); diff --git a/src/mightypork/utils/math/animation/AnimatorBounce.java b/src/mightypork/utils/math/animation/AnimatorBounce.java index 5610bc6..4c79808 100644 --- a/src/mightypork/utils/math/animation/AnimatorBounce.java +++ b/src/mightypork/utils/math/animation/AnimatorBounce.java @@ -3,34 +3,38 @@ package mightypork.utils.math.animation; /** * Animator that upon reaching max, animates back down and then up again - * + * * @author Ondřej Hruška (MightyPork) */ public class AnimatorBounce extends Animator { - + private boolean wasUp = false; - - - public AnimatorBounce(double start, double end, double period, Easing easing) { + + + public AnimatorBounce(double start, double end, double period, Easing easing) + { super(start, end, period, easing); } - - - public AnimatorBounce(double start, double end, double period) { + + + public AnimatorBounce(double start, double end, double period) + { super(start, end, period); } - - - public AnimatorBounce(double period, Easing easing) { + + + public AnimatorBounce(double period, Easing easing) + { super(period, easing); } - - - public AnimatorBounce(double period) { + + + public AnimatorBounce(double period) + { super(period); } - - + + @Override protected void nextCycle(NumAnimated anim) { @@ -39,8 +43,8 @@ public class AnimatorBounce extends Animator { } else { anim.fadeIn(); } - + wasUp = !wasUp; } - + } diff --git a/src/mightypork/utils/math/animation/AnimatorRewind.java b/src/mightypork/utils/math/animation/AnimatorRewind.java index 161d82c..b976c5e 100644 --- a/src/mightypork/utils/math/animation/AnimatorRewind.java +++ b/src/mightypork/utils/math/animation/AnimatorRewind.java @@ -4,36 +4,40 @@ package mightypork.utils.math.animation; /** * Animator that upon reaching top, jumps straight to zero and continues another * cycle. - * + * * @author Ondřej Hruška (MightyPork) */ public class AnimatorRewind extends Animator { - - public AnimatorRewind(double start, double end, double period, Easing easing) { + + public AnimatorRewind(double start, double end, double period, Easing easing) + { super(start, end, period, easing); } - - - public AnimatorRewind(double start, double end, double period) { + + + public AnimatorRewind(double start, double end, double period) + { super(start, end, period); } - - - public AnimatorRewind(double period, Easing easing) { + + + public AnimatorRewind(double period, Easing easing) + { super(period, easing); } - - - public AnimatorRewind(double period) { + + + public AnimatorRewind(double period) + { super(period); } - - + + @Override protected void nextCycle(NumAnimated anim) { anim.reset(); anim.fadeIn(); } - + } diff --git a/src/mightypork/utils/math/animation/Easing.java b/src/mightypork/utils/math/animation/Easing.java index 778c7b9..31bc069 100644 --- a/src/mightypork/utils/math/animation/Easing.java +++ b/src/mightypork/utils/math/animation/Easing.java @@ -3,23 +3,23 @@ package mightypork.utils.math.animation; /** * EasingFunction function. - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class Easing { - + /** * Get value at time t. - * + * * @param t time parameter (t = 1..1) * @return value at given t (0..1, can exceed if needed) */ public abstract double get(double t); - - + + /** * Reverse an easing (factory method) - * + * * @param original original easing * @return reversed easing */ @@ -27,11 +27,11 @@ public abstract class Easing { { return new Reverse(original); } - - + + /** * Combine two easings (factory method) - * + * * @param in initial easing * @param out terminal easing * @return product @@ -40,12 +40,12 @@ public abstract class Easing { { return new Composite(in, out); } - - + + /** * Create "bilinear" easing - compose of straight and reverse. (factory * method) - * + * * @param in initial easing * @return product */ @@ -53,55 +53,57 @@ public abstract class Easing { { return combine(in, reverse(in)); } - + /** * Reverse EasingFunction - * + * * @author Ondřej Hruška (MightyPork) */ private static class Reverse extends Easing { - + private final Easing ea; - - + + /** * @param in Easing to reverse */ - public Reverse(Easing in) { + public Reverse(Easing in) + { this.ea = in; } - - + + @Override public double get(double t) { return 1 - ea.get(1 - t); } } - + /** * Composite EasingFunction (0-0.5 EasingFunction A, 0.5-1 EasingFunction B) - * + * * @author Ondřej Hruška (MightyPork) */ private static class Composite extends Easing { - + private final Easing in; private final Easing out; - - + + /** * Create a composite EasingFunction - * + * * @param in initial EasingFunction * @param out terminal EasingFunction */ - public Composite(Easing in, Easing out) { + public Composite(Easing in, Easing out) + { this.in = in; this.out = out; } - - + + @Override public double get(double t) { @@ -109,172 +111,172 @@ public abstract class Easing { return 0.5 + out.get(2 * t - 1) * 0.5; } } - + /** No easing; At t=0.5 goes high. */ public static final Easing NONE = new Easing() { - + @Override public double get(double t) { return (t < 0.5 ? 0 : 1); } }; - + /** Linear (y=t) easing */ public static final Easing LINEAR = new Easing() { - + @Override public double get(double t) { return t; } }; - + /** Quadratic (y=t^2) easing in */ public static final Easing QUADRATIC_IN = new Easing() { - + @Override public double get(double t) { return t * t; } }; - + /** Quadratic (y=t^2) easing out */ public static final Easing QUADRATIC_OUT = reverse(QUADRATIC_IN); - + /** Quadratic (y=t^2) easing both */ public static final Easing QUADRATIC_BOTH = inOut(QUADRATIC_IN); - + /** Cubic (y=t^3) easing in */ public static final Easing CUBIC_IN = new Easing() { - + @Override public double get(double t) { return t * t * t; } }; - + /** Cubic (y=t^3) easing out */ public static final Easing CUBIC_OUT = reverse(CUBIC_IN); - + /** Cubic (y=t^3) easing both */ public static final Easing CUBIC_BOTH = inOut(CUBIC_IN); - + /** Quartic (y=t^4) easing in */ public static final Easing QUARTIC_IN = new Easing() { - + @Override public double get(double t) { return t * t * t * t; } }; - + /** Quartic (y=t^4) easing out */ public static final Easing QUARTIC_OUT = reverse(QUADRATIC_IN); - + /** Quartic (y=t^4) easing both */ public static final Easing QUARTIC_BOTH = inOut(QUADRATIC_IN); - + /** Quintic (y=t^5) easing in */ public static final Easing QUINTIC_IN = new Easing() { - + @Override public double get(double t) { return t * t * t * t * t; } }; - + /** Quintic (y=t^5) easing out */ public static final Easing QUINTIC_OUT = reverse(QUINTIC_IN); - + /** Quintic (y=t^5) easing both */ public static final Easing QUINTIC_BOTH = inOut(QUINTIC_IN); - + /** Sine easing in */ public static final Easing SINE_IN = new Easing() { - + @Override public double get(double t) { return 1 - Math.cos(t * (Math.PI / 2)); } }; - + /** Sine easing out */ public static final Easing SINE_OUT = reverse(SINE_IN); - + /** Sine easing both */ public static final Easing SINE_BOTH = inOut(SINE_IN); - + /** Exponential easing in */ public static final Easing EXPO_IN = new Easing() { - + @Override public double get(double t) { return Math.pow(2, 10 * (t - 1)); } }; - + /** Exponential easing out */ public static final Easing EXPO_OUT = reverse(EXPO_IN); - + /** Exponential easing both */ public static final Easing EXPO_BOTH = inOut(EXPO_IN); - + /** Circular easing in */ public static final Easing CIRC_IN = new Easing() { - + @Override public double get(double t) { return 1 - Math.sqrt(1 - t * t); } }; - + /** Circular easing out */ public static final Easing CIRC_OUT = reverse(CIRC_IN); - + /** Circular easing both */ public static final Easing CIRC_BOTH = inOut(CIRC_IN); - + /** Bounce easing in */ public static final Easing BOUNCE_OUT = new Easing() { - + @Override public double get(double t) { if (t < (1 / 2.75f)) { return (7.5625f * t * t); - + } else if (t < (2 / 2.75f)) { t -= (1.5f / 2.75f); return (7.5625f * t * t + 0.75f); - + } else if (t < (2.5 / 2.75)) { t -= (2.25f / 2.75f); return (7.5625f * t * t + 0.9375f); - + } else { t -= (2.625f / 2.75f); return (7.5625f * t * t + 0.984375f); } } }; - + /** Bounce easing out */ public static final Easing BOUNCE_IN = reverse(BOUNCE_OUT); - + /** Bounce easing both */ public static final Easing BOUNCE_BOTH = inOut(BOUNCE_IN); - + /** Back easing in */ public static final Easing BACK_IN = new Easing() { - + @Override public double get(double t) { @@ -282,31 +284,31 @@ public abstract class Easing { return t * t * ((s + 1) * t - s); } }; - + /** Back easing out */ public static final Easing BACK_OUT = reverse(BACK_IN); - + /** Back easing both */ public static final Easing BACK_BOTH = inOut(BACK_IN); - + /** Elastic easing in */ public static final Easing ELASTIC_IN = new Easing() { - + @Override public double get(double t) { if (t == 0) return 0; if (t == 1) return 1; - + final double p = .3f; final double s = p / 4; return -(Math.pow(2, 10 * (t -= 1)) * Math.sin((t - s) * (2 * Math.PI) / p)); } }; - + /** Elastic easing out */ public static final Easing ELASTIC_OUT = reverse(ELASTIC_IN); - + /** Elastic easing both */ public static final Easing ELASTIC_BOTH = inOut(ELASTIC_IN); } diff --git a/src/mightypork/utils/math/animation/NumAnimated.java b/src/mightypork/utils/math/animation/NumAnimated.java index f7d295c..4f2517c 100644 --- a/src/mightypork/utils/math/animation/NumAnimated.java +++ b/src/mightypork/utils/math/animation/NumAnimated.java @@ -11,109 +11,115 @@ import mightypork.utils.math.constraints.num.var.NumMutable; * Double which supports delta timing.
* When both in and out easings are set differently, then they'll be used for * fade-in and fade-out respectively. Otherwise both use the same. - * + * * @author Ondřej Hruška (MightyPork) */ public class NumAnimated extends NumMutable implements Updateable, Pauseable { - + /** target double */ protected double to = 0; - + /** last tick double */ protected double from = 0; - + /** how long the transition should last */ protected double duration = 0; - + /** current anim time */ protected double elapsedTime = 0; - + /** True if this animator is paused */ protected boolean paused = false; - + /** Easing fn */ protected Easing easingCurrent = Easing.LINEAR; protected Easing easingOut = Easing.LINEAR; protected Easing easingIn = Easing.LINEAR; - + /** Default duration (seconds) */ private double defaultDuration = 1; - - + + /** * With linear easing - * + * * @param value initial value */ - public NumAnimated(double value) { + public NumAnimated(double value) + { setTo(value); } - - + + /** * Create animator with easing - * + * * @param value initial value * @param easing easing function */ - public NumAnimated(double value, Easing easing) { + public NumAnimated(double value, Easing easing) + { this(value); setEasing(easing); } - - + + /** * Create animator with easing - * + * * @param value initial value * @param easingIn easing function (fade in) * @param easingOut easing function (fade out) */ - public NumAnimated(double value, Easing easingIn, Easing easingOut) { + public NumAnimated(double value, Easing easingIn, Easing easingOut) + { this(value); setEasing(easingIn, easingOut); } - - + + /** * Create animator with easing - * + * * @param value initial value * @param easing easing function * @param defaultDuration default fade duration */ - public NumAnimated(double value, Easing easing, double defaultDuration) { + public NumAnimated(double value, Easing easing, double defaultDuration) + { this(value); setEasing(easing); setDefaultDuration(defaultDuration); } - - + + /** * Create animator with easing - * + * * @param value initial value * @param easingIn easing function (fade in) * @param easingOut easing function (fade out) * @param defaultDuration default fade duration */ - public NumAnimated(double value, Easing easingIn, Easing easingOut, double defaultDuration) { + public NumAnimated(double value, Easing easingIn, Easing easingOut, double defaultDuration) + { this(value); setEasing(easingIn, easingOut); setDefaultDuration(defaultDuration); } - - + + /** * Create as copy of another - * + * * @param other other animator */ - public NumAnimated(NumAnimated other) { + public NumAnimated(NumAnimated other) + { setTo(other); } - - + + /** * @param easing easing function */ @@ -121,8 +127,8 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { { this.easingCurrent = this.easingIn = this.easingOut = easing; } - - + + /** * @param easingIn easing for fade in * @param easingOut easing for fade out @@ -133,30 +139,30 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { this.easingOut = easingOut; this.easingCurrent = easingIn; } - - + + /** * Get start value - * + * * @return number */ public double getStart() { return from; } - - + + /** * Get end value - * + * * @return number */ public double getEnd() { return to; } - - + + /** * @return current animation duration (seconds) */ @@ -164,8 +170,8 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { { return duration; } - - + + /** * @return elapsed time in current animation (seconds) */ @@ -173,8 +179,8 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { { return elapsedTime; } - - + + /** * @return default animation duration (seconds) */ @@ -182,8 +188,8 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { { return defaultDuration; } - - + + /** * @param defaultDuration default animation duration (seconds) */ @@ -191,11 +197,11 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { { this.defaultDuration = defaultDuration; } - - + + /** * Get value at delta time - * + * * @return the value */ @Override @@ -204,11 +210,11 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { if (duration == 0) return to; return Calc.interpolate(from, to, (elapsedTime / duration), easingCurrent); } - - + + /** * Get how much of the animation is already finished - * + * * @return completion ratio (0 to 1) */ public double getProgress() @@ -216,13 +222,13 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { if (duration == 0) return 1; return elapsedTime / duration; } - - + + @Override public void update(double delta) { if (paused || isFinished()) return; - + elapsedTime = Calc.clamp(elapsedTime + delta, 0, duration); if (isFinished()) { duration = 0; @@ -230,22 +236,22 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { from = to; } } - - + + /** * Get if animation is finished - * + * * @return is finished */ public boolean isFinished() { return duration == 0 || elapsedTime >= duration; } - - + + /** * Set to a value (without animation) - * + * * @param value */ @Override @@ -255,11 +261,11 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { elapsedTime = 0; duration = 0; } - - + + /** * Copy other - * + * * @param other */ public void setTo(NumAnimated other) @@ -274,11 +280,11 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { this.easingOut = other.easingOut; this.defaultDuration = other.defaultDuration; } - - + + /** * Animate between two states, start from current value (if it's in between) - * + * * @param from start value * @param to target state * @param time animation time (secs) @@ -286,45 +292,45 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { public void animate(double from, double to, double time) { final double current = value(); - + this.from = from; this.to = to; - + final double progress = getProgressFromValue(current); - + this.from = (progress > 0 ? current : from); - + this.duration = time * (1 - progress); this.elapsedTime = 0; } - - + + /** * Get progress already elapsed based on current value.
* Used to resume animation from current point in fading etc. - * + * * @param value current value * @return progress ratio 0-1 */ protected double getProgressFromValue(double value) { double p = 0; - + if (from == to) return 0; - + if (value >= from && value <= to) { // up p = ((value - from) / (to - from)); } else if (value >= to && value <= from) { // down p = ((from - value) / (from - to)); } - + return p; } - - + + /** * Animate to a value from current value - * + * * @param to target state * @param duration animation duration (speeds) */ @@ -335,11 +341,11 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { this.duration = duration; this.elapsedTime = 0; } - - + + /** * Animate 0 to 1 - * + * * @param time animation time (secs) */ public void fadeIn(double time) @@ -347,11 +353,11 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { easingCurrent = easingIn; animate(0, 1, time); } - - + + /** * Animate 1 to 0 - * + * * @param time animation time (secs) */ public void fadeOut(double time) @@ -359,8 +365,8 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { easingCurrent = easingOut; animate(1, 0, time); } - - + + /** * Animate 0 to 1 with default duration */ @@ -369,8 +375,8 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { easingCurrent = easingIn; animate(0, 1, defaultDuration); } - - + + /** * Animate 1 to 0 with default duration */ @@ -379,11 +385,11 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { easingCurrent = easingOut; animate(1, 0, defaultDuration); } - - + + /** * Make a copy - * + * * @return copy */ @Override @@ -391,15 +397,15 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { { return new NumAnimated(this); } - - + + @Override public String toString() { return "Animation(" + from + " -> " + to + ", t=" + duration + "s, elapsed=" + elapsedTime + "s)"; } - - + + /** * Set to zero and stop animation */ @@ -410,8 +416,8 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { duration = 0; paused = false; } - - + + /** * Stop animation, keep current value */ @@ -421,29 +427,29 @@ public class NumAnimated extends NumMutable implements Updateable, Pauseable { elapsedTime = 0; duration = 0; } - - + + @Override public void pause() { paused = true; } - - + + @Override public void resume() { paused = false; } - - + + @Override public boolean isPaused() { return paused; } - - + + public boolean isInProgress() { return !isFinished() && !isPaused(); diff --git a/src/mightypork/utils/math/animation/NumAnimatedDeg.java b/src/mightypork/utils/math/animation/NumAnimatedDeg.java index 32b2b06..fc4529e 100644 --- a/src/mightypork/utils/math/animation/NumAnimatedDeg.java +++ b/src/mightypork/utils/math/animation/NumAnimatedDeg.java @@ -7,34 +7,37 @@ import mightypork.utils.math.angles.Deg; /** * Degree animator - * + * * @author Ondřej Hruška (MightyPork) */ public class NumAnimatedDeg extends NumAnimated { - - public NumAnimatedDeg(NumAnimated other) { + + public NumAnimatedDeg(NumAnimated other) + { super(other); } - - - public NumAnimatedDeg(double value) { + + + public NumAnimatedDeg(double value) + { super(value); } - - - public NumAnimatedDeg(double value, Easing easing) { + + + public NumAnimatedDeg(double value, Easing easing) + { super(value, easing); } - - + + @Override public double value() { if (duration == 0) return Deg.norm(to); return Calc.interpolateDeg(from, to, (elapsedTime / duration), easingCurrent); } - - + + @Override protected double getProgressFromValue(double value) { @@ -43,7 +46,7 @@ public class NumAnimatedDeg extends NumAnimated { final double partial = Deg.diff(from, value); return partial / whole; } - + return 0; } } diff --git a/src/mightypork/utils/math/animation/NumAnimatedRad.java b/src/mightypork/utils/math/animation/NumAnimatedRad.java index 7057a63..569f799 100644 --- a/src/mightypork/utils/math/animation/NumAnimatedRad.java +++ b/src/mightypork/utils/math/animation/NumAnimatedRad.java @@ -7,34 +7,37 @@ import mightypork.utils.math.angles.Rad; /** * Radians animator - * + * * @author Ondřej Hruška (MightyPork) */ public class NumAnimatedRad extends NumAnimated { - - public NumAnimatedRad(NumAnimated other) { + + public NumAnimatedRad(NumAnimated other) + { super(other); } - - - public NumAnimatedRad(double value) { + + + public NumAnimatedRad(double value) + { super(value); } - - - public NumAnimatedRad(double value, Easing easing) { + + + public NumAnimatedRad(double value, Easing easing) + { super(value, easing); } - - + + @Override public double value() { if (duration == 0) return Rad.norm(to); return Calc.interpolateRad(from, to, (elapsedTime / duration), easingCurrent); } - - + + @Override protected double getProgressFromValue(double value) { @@ -43,7 +46,7 @@ public class NumAnimatedRad extends NumAnimated { final double partial = Rad.diff(from, value); return partial / whole; } - + return 0; } } diff --git a/src/mightypork/utils/math/animation/VectAnimated.java b/src/mightypork/utils/math/animation/VectAnimated.java index 32cd357..75fdbcf 100644 --- a/src/mightypork/utils/math/animation/VectAnimated.java +++ b/src/mightypork/utils/math/animation/VectAnimated.java @@ -10,64 +10,66 @@ import mightypork.utils.math.constraints.vect.var.VectMutable; /** * 3D coordinated with support for transitions, mutable. - * + * * @author Ondřej Hruška (MightyPork) */ public class VectAnimated extends VectMutable implements Pauseable, Updateable { - + private final NumAnimated x, y, z; private double defaultDuration = 0.5; - - + + /** * Create an animated vector; This way different easing / settings can be * specified for each coordinate. - * + * * @param x x animator * @param y y animator * @param z z animator */ - public VectAnimated(NumAnimated x, NumAnimated y, NumAnimated z) { + public VectAnimated(NumAnimated x, NumAnimated y, NumAnimated z) + { this.x = x; this.y = y; this.z = z; } - - + + /** * Create an animated vector - * + * * @param start initial positioon * @param easing animation easing */ - public VectAnimated(Vect start, Easing easing) { + public VectAnimated(Vect start, Easing easing) + { x = new NumAnimated(start.x(), easing); y = new NumAnimated(start.y(), easing); z = new NumAnimated(start.z(), easing); } - - + + @Override public double x() { return x.value(); } - - + + @Override public double y() { return y.value(); } - - + + @Override public double z() { return z.value(); } - - + + @Override public void setTo(double x, double y, double z) { @@ -75,35 +77,35 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { setY(y); setZ(z); } - - + + @Override public void setX(double x) { this.x.setTo(x); } - - + + @Override public void setY(double y) { this.y.setTo(y); } - - + + @Override public void setZ(double z) { this.z.setTo(z); } - - + + public void add(Vect offset, double duration) { animate(this.add(offset), duration); } - - + + public VectAnimated animate(double x, double y, double z, double duration) { this.x.animate(x, duration); @@ -111,15 +113,15 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { this.z.animate(z, duration); return this; } - - + + public VectAnimated animate(Vect target, double duration) { animate(target.x(), target.y(), target.z(), duration); return this; } - - + + public VectAnimated animate(double x, double y, double z) { this.x.animate(x, defaultDuration); @@ -127,15 +129,15 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { this.z.animate(z, defaultDuration); return this; } - - + + public VectAnimated animate(Vect target) { animate(target.x(), target.y(), target.z()); return this; } - - + + /** * @return the default duration (seconds) */ @@ -143,19 +145,19 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { { return defaultDuration; } - - + + /** * Set default animation duration (when changed without using animate()) - * + * * @param defaultDuration default duration (seconds) */ public void setDefaultDuration(double defaultDuration) { this.defaultDuration = defaultDuration; } - - + + @Override public void update(double delta) { @@ -163,8 +165,8 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { y.update(delta); z.update(delta); } - - + + @Override public void pause() { @@ -172,8 +174,8 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { y.pause(); z.pause(); } - - + + @Override public void resume() { @@ -181,15 +183,15 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { y.resume(); z.resume(); } - - + + @Override public boolean isPaused() { return x.isPaused(); // BÚNO } - - + + /** * @return true if the animation is finished */ @@ -197,8 +199,8 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { { return x.isFinished(); // BÚNO } - - + + /** * @return current animation duration */ @@ -206,8 +208,8 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { { return x.getDuration(); // BÚNO } - - + + /** * @return elapsed time since the start of the animation */ @@ -215,8 +217,8 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { { return x.getElapsed(); // BÚNO } - - + + /** * @return animation progress (elapsed / duration) */ @@ -224,11 +226,11 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { { return x.getProgress(); // BÚNO } - - + + /** * Set easing for all three coordinates - * + * * @param easing */ public void setEasing(Easing easing) @@ -237,12 +239,12 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { y.setEasing(easing); z.setEasing(easing); } - - + + /** * Create an animated vector; This way different easing / settings can be * specified for each coordinate. - * + * * @param x x animator * @param y y animator * @param z z animator @@ -253,11 +255,11 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { { return new VectAnimated(x, y, z); } - - + + /** * Create an animated vector - * + * * @param start initial positioon * @param easing animation easing * @return animated mutable vector @@ -267,11 +269,11 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { { return new VectAnimated(start, easing); } - - + + /** * Create an animated vector, initialized at 0,0,0 - * + * * @param easing animation easing * @return animated mutable vector */ @@ -280,5 +282,5 @@ public class VectAnimated extends VectMutable implements Pauseable, Updateable { { return new VectAnimated(Vect.ZERO, easing); } - + } diff --git a/src/mightypork/utils/math/color/Color.java b/src/mightypork/utils/math/color/Color.java index c848904..13704b5 100644 --- a/src/mightypork/utils/math/color/Color.java +++ b/src/mightypork/utils/math/color/Color.java @@ -12,15 +12,15 @@ import mightypork.utils.math.constraints.num.Num; /** * Color.
* All values are 0-1 - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class Color { - + private static final Stack alphaStack = new Stack<>(); private static volatile boolean alphaStackEnabled = true; - - + + @FactoryMethod public static final Color fromHex(int rgb_hex) { @@ -29,146 +29,146 @@ public abstract class Color { final int ri = (rgb_hex >> 16) & 0xff; return rgb(ri / 255D, gi / 255D, bi / 255D); } - - + + @FactoryMethod public static final Color rgb(double r, double g, double b) { return rgba(Num.make(r), Num.make(g), Num.make(b), Num.ONE); } - - + + @FactoryMethod public static final Color rgba(double r, double g, double b, double a) { return rgba(Num.make(r), Num.make(g), Num.make(b), Num.make(a)); } - - + + @FactoryMethod public static final Color rgb(Num r, Num g, Num b) { return rgba(r, g, b, Num.ONE); } - - + + @FactoryMethod public static final Color rgba(Num r, Num g, Num b, Num a) { return new ColorRgb(r, g, b, a); } - - + + @FactoryMethod public static final Color hsb(double h, double s, double b) { return hsba(Num.make(h), Num.make(s), Num.make(b), Num.ONE); } - - + + @FactoryMethod public static final Color hsba(double h, double s, double b, double a) { return hsba(Num.make(h), Num.make(s), Num.make(b), Num.make(a)); } - - + + @FactoryMethod public static final Color hsb(Num h, Num s, Num b) { return hsba(h, s, b, Num.ONE); } - - + + @FactoryMethod public static final Color hsba(Num h, Num s, Num b, Num a) { return new ColorHsb(h, s, b, a); } - - + + @FactoryMethod public static final Color light(double a) { return light(Num.make(a)); } - - + + @FactoryMethod public static final Color light(Num a) { return rgba(Num.ONE, Num.ONE, Num.ONE, a); } - - + + @FactoryMethod public static final Color dark(double a) { return dark(Num.make(a)); } - - + + @FactoryMethod public static final Color dark(Num a) { return rgba(Num.ZERO, Num.ZERO, Num.ZERO, a); } - - + + protected static final double clamp(Num n) { return Calc.clamp(n.value(), 0, 1); } - - + + protected static final double clamp(double n) { return Calc.clamp(n, 0, 1); } - - + + /** * @return red 0-1 */ public abstract double r(); - - + + /** * @return green 0-1 */ public abstract double g(); - - + + /** * @return blue 0-1 */ public abstract double b(); - - + + /** * @return alpha 0-1 */ public final double a() { double alpha = rawAlpha(); - + if (alphaStackEnabled) { - + for (final Num n : alphaStack) { alpha *= clamp(n.value()); } } - + return clamp(alpha); } - - + + /** * @return alpha 0-1, before multiplying with the global alpha value. */ protected abstract double rawAlpha(); - - + + /** *

* Push alpha multiplier on the stack (can be animated or whatever you @@ -180,7 +180,7 @@ public abstract class Color { * multiplier value should not exceed the range 0..1, otherwise it will be * clamped to it. *

- * + * * @param alpha alpha multiplier */ public static void pushAlpha(Num alpha) @@ -188,15 +188,15 @@ public abstract class Color { if (!alphaStackEnabled) { return; } - + alphaStack.push(alpha); } - - + + /** * Remove a pushed alpha multiplier from the stack. If there's no remaining * multiplier on the stack, an exception is raised. - * + * * @throws EmptyStackException if the stack is empty */ public static void popAlpha() @@ -204,27 +204,27 @@ public abstract class Color { if (!alphaStackEnabled) { return; } - + if (alphaStack.isEmpty()) { throw new EmptyStackException(); } - + alphaStack.pop(); } - - + + /** * Enable alpha stack. When disabled, pushAlpha() and popAlpha() have no * effect. - * + * * @param yes */ public static void enableAlphaStack(boolean yes) { alphaStackEnabled = yes; } - - + + /** * @return true if alpha stack is enabled. */ @@ -232,20 +232,20 @@ public abstract class Color { { return alphaStackEnabled; } - - + + public Color withAlpha(double multiplier) { return new ColorAlphaAdjuster(this, Num.make(multiplier)); } - - + + public Color withAlpha(Num multiplier) { return new ColorAlphaAdjuster(this, multiplier); } - - + + @Override public int hashCode() { @@ -262,15 +262,15 @@ public abstract class Color { result = prime * result + (int) (temp ^ (temp >>> 32)); return result; } - - + + @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof Color)) return false; - Color other = (Color) obj; + final Color other = (Color) obj; if (Double.doubleToLongBits(b()) != Double.doubleToLongBits(other.b())) return false; if (Double.doubleToLongBits(g()) != Double.doubleToLongBits(other.g())) return false; if (Double.doubleToLongBits(r()) != Double.doubleToLongBits(other.r())) return false; diff --git a/src/mightypork/utils/math/color/ColorAlphaAdjuster.java b/src/mightypork/utils/math/color/ColorAlphaAdjuster.java index 9d58577..5d87c43 100644 --- a/src/mightypork/utils/math/color/ColorAlphaAdjuster.java +++ b/src/mightypork/utils/math/color/ColorAlphaAdjuster.java @@ -5,42 +5,43 @@ import mightypork.utils.math.constraints.num.Num; public class ColorAlphaAdjuster extends Color { - + private final Color source; private final Num alphaAdjust; - - - public ColorAlphaAdjuster(Color source, Num alphaMul) { + + + public ColorAlphaAdjuster(Color source, Num alphaMul) + { this.source = source; this.alphaAdjust = alphaMul; } - - + + @Override public double r() { return source.r(); } - - + + @Override public double g() { return source.g(); } - - + + @Override public double b() { return source.b(); } - - + + @Override protected double rawAlpha() { return source.rawAlpha() * alphaAdjust.value(); } - + } diff --git a/src/mightypork/utils/math/color/ColorHsb.java b/src/mightypork/utils/math/color/ColorHsb.java index 781873f..c70b3dc 100644 --- a/src/mightypork/utils/math/color/ColorHsb.java +++ b/src/mightypork/utils/math/color/ColorHsb.java @@ -5,57 +5,58 @@ import mightypork.utils.math.constraints.num.Num; public class ColorHsb extends Color { - + private final Num h; private final Num s; private final Num b; private final Num a; - - - public ColorHsb(Num h, Num s, Num b, Num a) { + + + public ColorHsb(Num h, Num s, Num b, Num a) + { this.h = h; this.s = s; this.b = b; this.a = a; } - - + + private double[] asRgb() { final int hex = java.awt.Color.HSBtoRGB((float) clamp(h), (float) clamp(s), (float) clamp(b)); - + final int bi = hex & 0xff; final int gi = (hex >> 8) & 0xff; final int ri = (hex >> 16) & 0xff; return new double[] { ri / 255D, gi / 255D, bi / 255D, clamp(a) }; } - - + + @Override public double r() { return asRgb()[0]; } - - + + @Override public double g() { return asRgb()[1]; } - - + + @Override public double b() { return asRgb()[2]; } - - + + @Override protected double rawAlpha() { return asRgb()[3]; } - + } diff --git a/src/mightypork/utils/math/color/ColorRgb.java b/src/mightypork/utils/math/color/ColorRgb.java index 38eb212..37065af 100644 --- a/src/mightypork/utils/math/color/ColorRgb.java +++ b/src/mightypork/utils/math/color/ColorRgb.java @@ -5,46 +5,47 @@ import mightypork.utils.math.constraints.num.Num; public class ColorRgb extends Color { - + private final Num r; private final Num g; private final Num b; private final Num a; - - - public ColorRgb(Num r, Num g, Num b, Num a) { + + + public ColorRgb(Num r, Num g, Num b, Num a) + { this.r = r; this.g = g; this.b = b; this.a = a; } - - + + @Override public double r() { return clamp(r); } - - + + @Override public double g() { return clamp(g); } - - + + @Override public double b() { return clamp(b); } - - + + @Override protected double rawAlpha() { return clamp(a); } - + } diff --git a/src/mightypork/utils/math/color/Grad.java b/src/mightypork/utils/math/color/Grad.java index 7385b6a..ddf3fd6 100644 --- a/src/mightypork/utils/math/color/Grad.java +++ b/src/mightypork/utils/math/color/Grad.java @@ -1,27 +1,26 @@ package mightypork.utils.math.color; - - /** * Linear gradient (each corner can have different color) - * + * * @author MightyPork */ public class Grad { - + public final Color leftTop, rightTop, rightBottom, leftBottom; - - + + /** * Create a gradient - * + * * @param leftTop left top color * @param rightTop right top color * @param rightBottom right bottom color * @param leftBottom left bottom color */ - public Grad(Color leftTop, Color rightTop, Color rightBottom, Color leftBottom) { + public Grad(Color leftTop, Color rightTop, Color rightBottom, Color leftBottom) + { this.leftTop = leftTop; this.rightTop = rightTop; this.rightBottom = rightBottom; diff --git a/src/mightypork/utils/math/color/GradH.java b/src/mightypork/utils/math/color/GradH.java index 17d758c..76eb2c0 100644 --- a/src/mightypork/utils/math/color/GradH.java +++ b/src/mightypork/utils/math/color/GradH.java @@ -1,16 +1,15 @@ package mightypork.utils.math.color; - - /** * Linear horizontal gradient - * + * * @author MightyPork */ public class GradH extends Grad { - - public GradH(Color left, Color right) { + + public GradH(Color left, Color right) + { super(left, right, right, left); } } diff --git a/src/mightypork/utils/math/color/GradV.java b/src/mightypork/utils/math/color/GradV.java index b723d25..dfc92ca 100644 --- a/src/mightypork/utils/math/color/GradV.java +++ b/src/mightypork/utils/math/color/GradV.java @@ -1,16 +1,15 @@ package mightypork.utils.math.color; - - /** * Linear vertical gradient - * + * * @author MightyPork */ public class GradV extends Grad { - - public GradV(Color top, Color bottom) { + + public GradV(Color top, Color bottom) + { super(top, top, bottom, bottom); } } diff --git a/src/mightypork/utils/math/color/pal/CGA.java b/src/mightypork/utils/math/color/pal/CGA.java index 82a8125..3544033 100644 --- a/src/mightypork/utils/math/color/pal/CGA.java +++ b/src/mightypork/utils/math/color/pal/CGA.java @@ -6,16 +6,16 @@ import mightypork.utils.math.color.Color; /** * CGA palette - * + * * @author Ondřej Hruška (MightyPork) */ public interface CGA { - + Color BLACK = Color.fromHex(0x000000); Color GRAY_DARK = Color.fromHex(0x686868); Color GRAY_LIGHT = Color.fromHex(0xB8B8B8); Color WHITE = Color.fromHex(0xFFFFFF); - + Color RED_DARK = Color.fromHex(0xC41F0C); Color RED_LIGHT = Color.fromHex(0xFF706A); Color MAGENTA_DARK = Color.fromHex(0xC12BB6); @@ -26,7 +26,7 @@ public interface CGA { Color CYAN_LIGHT = Color.fromHex(0x23FCFE); Color GREEN_DARK = Color.fromHex(0x00B41D); Color GREEN_LIGHT = Color.fromHex(0x39FA6F); - + Color YELLOW = Color.fromHex(0xFFFD72); Color BROWN = Color.fromHex(0xC16A14); } diff --git a/src/mightypork/utils/math/color/pal/CMDR.java b/src/mightypork/utils/math/color/pal/CMDR.java index d8d5b75..c7d3c39 100644 --- a/src/mightypork/utils/math/color/pal/CMDR.java +++ b/src/mightypork/utils/math/color/pal/CMDR.java @@ -6,11 +6,11 @@ import mightypork.utils.math.color.Color; /** * COMMODORE palette - * + * * @author Ondřej Hruška (MightyPork) */ public interface CMDR { - + Color BLACK = Color.fromHex(0x040013); Color WHITE = Color.fromHex(0xFFFFFF); Color RED = Color.fromHex(0x883932); diff --git a/src/mightypork/utils/math/color/pal/PAL16.java b/src/mightypork/utils/math/color/pal/PAL16.java index fb32202..55f2375 100644 --- a/src/mightypork/utils/math/color/pal/PAL16.java +++ b/src/mightypork/utils/math/color/pal/PAL16.java @@ -6,27 +6,27 @@ import mightypork.utils.math.color.Color; /** * PAL16 palette via http://androidarts.com/palette/16pal.htm - * + * * @author Ondřej Hruška (MightyPork) */ public interface PAL16 { - + Color VOID = Color.fromHex(0x000000); Color ASH = Color.fromHex(0x9D9D9D); Color BLIND = Color.fromHex(0xFFFFFF); - + Color BLOODRED = Color.fromHex(0xBE2633); Color PIGMEAT = Color.fromHex(0xE06F8B); - + Color OLDPOOP = Color.fromHex(0x493C2B); Color NEWPOOP = Color.fromHex(0xA46422); Color BLAZE = Color.fromHex(0xEB8931); Color ZORNSKIN = Color.fromHex(0xF7E26B); - + Color SHADEGREEN = Color.fromHex(0x2F484E); Color LEAFGREEN = Color.fromHex(0x44891A); Color SLIMEGREEN = Color.fromHex(0xA3CE27); - + Color NIGHTBLUE = Color.fromHex(0x1B2632); Color SEABLUE = Color.fromHex(0x005784); Color SKYBLUE = Color.fromHex(0x31A2F2); diff --git a/src/mightypork/utils/math/color/pal/RGB.java b/src/mightypork/utils/math/color/pal/RGB.java index 1dc490e..ee9179e 100644 --- a/src/mightypork/utils/math/color/pal/RGB.java +++ b/src/mightypork/utils/math/color/pal/RGB.java @@ -6,11 +6,11 @@ import mightypork.utils.math.color.Color; /** * Basic RGB palette - * + * * @author Ondřej Hruška (MightyPork) */ public class RGB { - + public static final Color BLACK_10 = Color.rgba(0, 0, 0, 0.1); public static final Color BLACK_20 = Color.rgba(0, 0, 0, 0.2); public static final Color BLACK_30 = Color.rgba(0, 0, 0, 0.3); @@ -20,24 +20,24 @@ public class RGB { public static final Color BLACK_70 = Color.rgba(0, 0, 0, 0.7); public static final Color BLACK_80 = Color.rgba(0, 0, 0, 0.8); public static final Color BLACK_90 = Color.rgba(0, 0, 0, 0.9); - + public static final Color WHITE = Color.fromHex(0xFFFFFF); public static final Color BLACK = Color.fromHex(0x000000); public static final Color GRAY_DARK = Color.fromHex(0x808080); public static final Color GRAY = Color.fromHex(0xA0A0A0); public static final Color GRAY_LIGHT = Color.fromHex(0xC0C0C0); - + public static final Color RED = Color.fromHex(0xFF0000); public static final Color GREEN = Color.fromHex(0x00FF00); public static final Color BLUE = Color.fromHex(0x0000FF); - + public static final Color YELLOW = Color.fromHex(0xFFFF00); public static final Color CYAN = Color.fromHex(0x00FFFF); public static final Color MAGENTA = Color.fromHex(0xFF00FF); - + public static final Color PINK = Color.fromHex(0xFF3FFC); public static final Color ORANGE = Color.fromHex(0xFC4800); public static final Color BROWN = Color.fromHex(0x83501B); - + public static final Color NONE = Color.rgba(0, 0, 0, 0); } diff --git a/src/mightypork/utils/math/color/pal/ZX.java b/src/mightypork/utils/math/color/pal/ZX.java index ac2baf3..9715be5 100644 --- a/src/mightypork/utils/math/color/pal/ZX.java +++ b/src/mightypork/utils/math/color/pal/ZX.java @@ -6,15 +6,15 @@ import mightypork.utils.math.color.Color; /** * ZX Spectrum palette - * + * * @author Ondřej Hruška (MightyPork) */ public interface ZX { - + Color BLACK = Color.fromHex(0x000000); Color GRAY = Color.fromHex(0xCBCBCB); Color WHITE = Color.fromHex(0xFFFFFF); - + Color RED_DARK = Color.fromHex(0xD8240F); Color RED_LIGHT = Color.fromHex(0xFF3016); Color MAGENTA_DARK = Color.fromHex(0xD530C9); @@ -25,7 +25,7 @@ public interface ZX { Color CYAN_LIGHT = Color.fromHex(0xFFFD33); Color GREEN_DARK = Color.fromHex(0x00C721); Color GREEN_LIGHT = Color.fromHex(0x00F92C); - + Color YELLOW_DARK = Color.fromHex(0xCECA26); Color YELLOW_LIGHT = Color.fromHex(0xFFFD33); } diff --git a/src/mightypork/utils/math/constraints/CachedConstraint.java b/src/mightypork/utils/math/constraints/CachedConstraint.java index dede4e2..f2ba4f0 100644 --- a/src/mightypork/utils/math/constraints/CachedConstraint.java +++ b/src/mightypork/utils/math/constraints/CachedConstraint.java @@ -6,38 +6,38 @@ import mightypork.utils.interfaces.Pollable; /** * Constraint that is cached - * + * * @author Ondřej Hruška (MightyPork) * @param constraint type */ public interface CachedConstraint extends Pollable { - + /** * Called after the cache has changed value (and digest). */ void onConstraintChanged(); - - + + /** * @return the cached value */ C getCacheSource(); - - + + /** * Enable caching & digest caching - * + * * @param yes enable caching */ void enableCaching(boolean yes); - - + + /** * @return true if caching is on */ boolean isCachingEnabled(); - - + + /** * Update cached value and cached digest (if digest caching is enabled).
* source constraint is polled beforehand. diff --git a/src/mightypork/utils/math/constraints/CachedDigestable.java b/src/mightypork/utils/math/constraints/CachedDigestable.java index e0060a3..7925b18 100644 --- a/src/mightypork/utils/math/constraints/CachedDigestable.java +++ b/src/mightypork/utils/math/constraints/CachedDigestable.java @@ -17,12 +17,12 @@ package mightypork.utils.math.constraints; * Implementing class typically needs a field to store the last digest, a flag * that digest caching is enabled, and a flag that a digest is dirty. *

- * + * * @author Ondřej Hruška (MightyPork) * @param digest class */ public interface CachedDigestable extends Digestable { - + /** *

* Toggle digest caching. @@ -30,22 +30,22 @@ public interface CachedDigestable extends Digestable { *

* To trigger update of the cache, call the poll() method. *

- * + * * @param yes */ void enableDigestCaching(boolean yes); - - + + /** * @return true if digest caching is enabled. */ boolean isDigestCachingEnabled(); - - + + /** * If digest caching is enabled, mark current cached value as "dirty". Dirty * digest should be re-created next time a value is requested.
*/ void markDigestDirty(); - + } diff --git a/src/mightypork/utils/math/constraints/DigestCache.java b/src/mightypork/utils/math/constraints/DigestCache.java index 36e0da3..4640f9c 100644 --- a/src/mightypork/utils/math/constraints/DigestCache.java +++ b/src/mightypork/utils/math/constraints/DigestCache.java @@ -3,17 +3,17 @@ package mightypork.utils.math.constraints; /** * Parametrized implementation of a {@link CachedDigestable} - * + * * @author Ondřej Hruška (MightyPork) * @param digest class */ public abstract class DigestCache implements CachedDigestable { - + private D last_digest; private boolean caching_enabled = false; private boolean dirty = true; - - + + @Override public final D digest() { @@ -22,39 +22,39 @@ public abstract class DigestCache implements CachedDigestable { last_digest = createDigest(); dirty = false; } - + return last_digest; } - + return createDigest(); } - - + + /** * @return fresh new digest */ protected abstract D createDigest(); - - + + @Override public final void enableDigestCaching(boolean yes) { caching_enabled = yes; markDigestDirty(); // mark dirty } - - + + @Override public final boolean isDigestCachingEnabled() { return caching_enabled; } - - + + @Override public final void markDigestDirty() { dirty = true; } - + } diff --git a/src/mightypork/utils/math/constraints/Digestable.java b/src/mightypork/utils/math/constraints/Digestable.java index 7fd28b4..b1d6acc 100644 --- a/src/mightypork/utils/math/constraints/Digestable.java +++ b/src/mightypork/utils/math/constraints/Digestable.java @@ -3,18 +3,18 @@ package mightypork.utils.math.constraints; /** * COnstraint that can be converted to a digest, representing current state - * + * * @author Ondřej Hruška (MightyPork) * @param */ public interface Digestable { - + /** * Take a digest. If digest caching is enabled and the cached digest is * marked as dirty, a new one should be made. - * + * * @return digest */ D digest(); - + } diff --git a/src/mightypork/utils/math/constraints/num/Num.java b/src/mightypork/utils/math/constraints/num/Num.java index 415eb88..e97a8da 100644 --- a/src/mightypork/utils/math/constraints/num/Num.java +++ b/src/mightypork/utils/math/constraints/num/Num.java @@ -12,45 +12,45 @@ import mightypork.utils.math.constraints.vect.Vect; public abstract class Num implements NumBound, CachedDigestable { - + public static final NumConst ZERO = Num.make(0); public static final NumConst ONE = Num.make(1); - - + + @FactoryMethod public static Num make(NumBound bound) { return new NumProxy(bound); } - - + + @FactoryMethod public static NumConst make(double value) { return new NumConst(value); } - - + + @FactoryMethod public static NumVar makeVar() { return makeVar(0); } - - + + @FactoryMethod public static NumVar makeVar(double value) { return new NumVar(value); } - - + + @FactoryMethod public static NumVar makeVar(Num copied) { return new NumVar(copied.value()); } - + private Num p_ceil; private Num p_floor; private Num p_sgn; @@ -67,89 +67,89 @@ public abstract class Num implements NumBound, CachedDigestable { private Num p_square; private Num p_neg; private Num p_abs; - + private final DigestCache dc = new DigestCache() { - + @Override protected NumDigest createDigest() { return new NumDigest(Num.this); } }; - - + + public NumConst freeze() { return new NumConst(value()); } - - + + /** * Wrap this constraint into a caching adapter. Value will stay fixed (ie. * no re-calculations) until cache receives a poll() call. - * + * * @return the caching adapter */ public NumCache cached() { return new NumCache(this); } - - + + /** * Get a snapshot of the current state, to be used for processing. - * + * * @return digest */ - + @Override public NumDigest digest() { return dc.digest(); } - - + + @Override public void enableDigestCaching(boolean yes) { dc.enableDigestCaching(yes); } - - + + @Override public boolean isDigestCachingEnabled() { return dc.isDigestCachingEnabled(); } - - + + @Override public void markDigestDirty() { dc.markDigestDirty(); } - - + + @Override public Num getNum() { return this; } - - + + /** * @return the number */ public abstract double value(); - - + + public Num add(final double addend) { return new Num() { - + private final Num t = Num.this; - - + + @Override public double value() { @@ -157,15 +157,15 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num add(final Num addend) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -173,39 +173,39 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num sub(final double subtrahend) { return add(-subtrahend); } - - + + public Num abs() { if (p_abs == null) p_abs = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.abs(t.value()); } }; - + return p_abs; } - - + + public Num sub(final Num subtrahend) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -213,22 +213,22 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num div(final double factor) { return mul(1 / factor); } - - + + public Num div(final Num factor) { - + return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -236,15 +236,15 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num mul(final double factor) { return new Num() { - + private final Num t = Num.this; - - + + @Override public double value() { @@ -252,16 +252,16 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num mul(final Num factor) { - + return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -269,15 +269,15 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num average(final double other) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -285,15 +285,15 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num average(final Num other) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -301,21 +301,21 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num perc(final double percent) { return mul(percent / 100D); } - - + + public Num perc(final Num percent) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -323,231 +323,231 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num cos() { if (p_cos == null) p_cos = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.cos(t.value()); } }; - + return p_cos; } - - + + public Num acos() { if (p_acos == null) p_acos = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.acos(t.value()); } }; - + return p_acos; } - - + + public Num sin() { if (p_sin == null) p_sin = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.sin(t.value()); } }; - + return p_sin; } - - + + public Num asin() { if (p_asin == null) p_asin = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.asin(t.value()); } }; - + return p_asin; } - - + + public Num tan() { if (p_tan == null) p_tan = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.tan(t.value()); } }; - + return p_tan; } - - + + public Num atan() { if (p_atan == null) p_atan = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.atan(t.value()); } }; - + return p_atan; } - - + + public Num cbrt() { if (p_cbrt == null) p_cbrt = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.cbrt(t.value()); } }; - + return p_cbrt; } - - + + public Num sqrt() { if (p_sqrt == null) p_sqrt = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.sqrt(t.value()); } }; - + return p_sqrt; } - - + + public Num neg() { if (p_neg == null) p_neg = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return -1 * t.value(); } }; - + return p_neg; } - - + + public Num round() { if (p_round == null) p_round = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.round(t.value()); } }; - + return p_round; } - - + + public Num floor() { if (p_floor == null) p_floor = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.floor(t.value()); } }; - + return p_floor; } - - + + public Num ceil() { if (p_ceil == null) p_ceil = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.round(t.value()); } }; - + return p_ceil; } - - + + public Num pow(final double other) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -555,15 +555,15 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num pow(final Num power) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -571,15 +571,15 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num cube() { if (p_cube == null) p_cube = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -587,18 +587,18 @@ public abstract class Num implements NumBound, CachedDigestable { return v * v * v; } }; - + return p_cube; } - - + + public Num square() { if (p_square == null) p_square = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -606,24 +606,24 @@ public abstract class Num implements NumBound, CachedDigestable { return v * v; } }; - + return p_square; } - - + + public Num half() { return mul(0.5); } - - + + public Num max(final double other) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -631,15 +631,15 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num max(final Num other) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -647,15 +647,15 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num min(final Num other) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -663,15 +663,15 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num min(final double other) { return new Num() { - + final Num t = Num.this; - - + + @Override public double value() { @@ -679,44 +679,44 @@ public abstract class Num implements NumBound, CachedDigestable { } }; } - - + + public Num signum() { if (p_sgn == null) p_sgn = new Num() { - + final Num t = Num.this; - - + + @Override public double value() { return Math.signum(t.value()); } }; - + return p_sgn; } - - + + public boolean isNegative() { return value() < 0; } - - + + public boolean isPositive() { return value() > 0; } - - + + public boolean isZero() { return value() == 0; } - - + + @Override public int hashCode() { @@ -727,8 +727,8 @@ public abstract class Num implements NumBound, CachedDigestable { result = prime * result + (int) (temp ^ (temp >>> 32)); return result; } - - + + @Override public boolean equals(Object obj) { @@ -736,18 +736,18 @@ public abstract class Num implements NumBound, CachedDigestable { if (obj == null) return false; if (!(obj instanceof Num)) return false; final Num other = (Num) obj; - + return value() == other.value(); } - - + + @Override public String toString() { return Double.toString(value()); } - - + + /** * @return vect with both coords of this size */ diff --git a/src/mightypork/utils/math/constraints/num/NumBound.java b/src/mightypork/utils/math/constraints/num/NumBound.java index 168f32d..b896abf 100644 --- a/src/mightypork/utils/math/constraints/num/NumBound.java +++ b/src/mightypork/utils/math/constraints/num/NumBound.java @@ -3,14 +3,14 @@ package mightypork.utils.math.constraints.num; /** * Interface for something that has/is a Num. Num itself implements it as well. - * + * * @author Ondřej Hruška (MightyPork) */ public interface NumBound { - + /** * @return the Num value */ Num getNum(); - + } diff --git a/src/mightypork/utils/math/constraints/num/NumConst.java b/src/mightypork/utils/math/constraints/num/NumConst.java index b29ac42..31c7761 100644 --- a/src/mightypork/utils/math/constraints/num/NumConst.java +++ b/src/mightypork/utils/math/constraints/num/NumConst.java @@ -8,32 +8,34 @@ import mightypork.utils.math.constraints.num.caching.NumDigest; * Constant number.
* It's arranged so that operations with constant arguments yield constant * results. - * + * * @author Ondřej Hruška (MightyPork) */ public class NumConst extends Num { - + private final double value; private NumDigest digest; - - - NumConst(Num copied) { + + + NumConst(Num copied) + { this.value = copied.value(); } - - - NumConst(double value) { + + + NumConst(double value) + { this.value = value; } - - + + @Override public double value() { return value; } - - + + /** * @deprecated No good to copy a constant. */ @@ -43,226 +45,226 @@ public class NumConst extends Num { { return this; } - - + + @Override public NumDigest digest() { return (digest != null) ? digest : (digest = super.digest()); } - - + + @Override public NumConst add(double addend) { return Num.make(value() + addend); } - - + + public NumConst add(NumConst addend) { return Num.make(value + addend.value); } - - + + @Override public NumConst sub(double subtrahend) { return add(-subtrahend); } - - + + public NumConst sub(NumConst addend) { return Num.make(value - addend.value); } - - + + @Override public NumConst mul(double factor) { return Num.make(value() * factor); } - - + + public NumConst mul(NumConst addend) { return Num.make(value * addend.value); } - - + + @Override public NumConst div(double factor) { return mul(1 / factor); } - - + + public NumConst div(NumConst addend) { return Num.make(value / addend.value); } - - + + @Override public NumConst perc(double percents) { return mul(percents / 100); } - - + + @Override public NumConst neg() { return mul(-1); } - - + + @Override public NumConst abs() { return Num.make(Math.abs(value())); } - - + + @Override public NumConst max(double other) { return Num.make(Math.max(value(), other)); } - - + + @Override public NumConst min(double other) { return Num.make(Math.min(value(), other)); } - - + + @Override public NumConst pow(double power) { return Num.make(Math.pow(value(), power)); } - - + + @Override public NumConst square() { final double v = value(); return Num.make(v * v); } - - + + @Override public NumConst cube() { final double v = value(); return Num.make(v * v * v); } - - + + @Override public NumConst sqrt() { return Num.make(Math.sqrt(value())); } - - + + @Override public NumConst cbrt() { return Num.make(Math.cbrt(value())); } - - + + @Override public NumConst sin() { return Num.make(Math.sin(value())); } - - + + @Override public NumConst cos() { return Num.make(Math.cos(value())); } - - + + @Override public NumConst tan() { return Num.make(Math.tan(value())); } - - + + @Override public NumConst asin() { return Num.make(Math.asin(value())); } - - + + @Override public NumConst acos() { return Num.make(Math.acos(value())); } - - + + @Override public NumConst atan() { return Num.make(Math.atan(value())); } - - + + @Override public NumConst signum() { return Num.make(Math.signum(value())); } - - + + @Override public NumConst average(double other) { return Num.make((value() + other) / 2); } - - + + public NumConst average(NumConst other) { return super.average(other).freeze(); } - - + + @Override public NumConst round() { return Num.make(Math.round(value())); } - - + + @Override public NumConst ceil() { return Num.make(Math.ceil(value())); } - - + + @Override public NumConst floor() { return Num.make(Math.floor(value())); } - - + + @Override public NumConst half() { return mul(0.5); } - + } diff --git a/src/mightypork/utils/math/constraints/num/PluggableNumBound.java b/src/mightypork/utils/math/constraints/num/PluggableNumBound.java index 032bdc9..55ef7fb 100644 --- a/src/mightypork/utils/math/constraints/num/PluggableNumBound.java +++ b/src/mightypork/utils/math/constraints/num/PluggableNumBound.java @@ -3,14 +3,14 @@ package mightypork.utils.math.constraints.num; /** * Pluggable numeric constraint - * + * * @author Ondřej Hruška (MightyPork) */ public interface PluggableNumBound extends NumBound { - + /** * @param num bound to set */ abstract void setNum(NumBound num); - + } diff --git a/src/mightypork/utils/math/constraints/num/batch/NumMul.java b/src/mightypork/utils/math/constraints/num/batch/NumMul.java index 016bea5..43dfdc2 100644 --- a/src/mightypork/utils/math/constraints/num/batch/NumMul.java +++ b/src/mightypork/utils/math/constraints/num/batch/NumMul.java @@ -9,14 +9,14 @@ import mightypork.utils.math.constraints.num.Num; /** * Expandable multiplication of multiple numbers - * + * * @author Ondřej Hruška (MightyPork) */ public class NumMul extends Num { - + private final List factors = new ArrayList<>(); - - + + @Override public double value() { @@ -26,22 +26,22 @@ public class NumMul extends Num { } return v; } - - + + /** * Add a number to the multiplication - * + * * @param factor added number */ public void addFactor(Num factor) { factors.add(factor); } - - + + /** * Add a number to the multiplication - * + * * @param factor added number */ public void addFactor(double factor) diff --git a/src/mightypork/utils/math/constraints/num/batch/NumSum.java b/src/mightypork/utils/math/constraints/num/batch/NumSum.java index f63f5fe..8e9e201 100644 --- a/src/mightypork/utils/math/constraints/num/batch/NumSum.java +++ b/src/mightypork/utils/math/constraints/num/batch/NumSum.java @@ -9,14 +9,14 @@ import mightypork.utils.math.constraints.num.Num; /** * Expandable sum of multiple numbers - * + * * @author Ondřej Hruška (MightyPork) */ public class NumSum extends Num { - + private final List summands = new ArrayList<>(); - - + + @Override public double value() { @@ -26,22 +26,22 @@ public class NumSum extends Num { } return v; } - - + + /** * Add a number to the sum - * + * * @param summand added number */ public void addSummand(Num summand) { summands.add(summand); } - - + + /** * Add a number to the sum - * + * * @param summand added number */ public void addSummand(double summand) diff --git a/src/mightypork/utils/math/constraints/num/caching/AbstractNumCache.java b/src/mightypork/utils/math/constraints/num/caching/AbstractNumCache.java index 83c6809..1099dab 100644 --- a/src/mightypork/utils/math/constraints/num/caching/AbstractNumCache.java +++ b/src/mightypork/utils/math/constraints/num/caching/AbstractNumCache.java @@ -15,69 +15,70 @@ import mightypork.utils.math.constraints.num.var.NumVar; * Values are held in a caching VectVar, and digest caching is enabled by * default. *

- * + * * @author Ondřej Hruška (MightyPork) */ public abstract class AbstractNumCache extends NumAdapter implements CachedConstraint { - + private final NumVar cache = Num.makeVar(); private boolean inited = false; private boolean cachingEnabled = true; - - - public AbstractNumCache() { + + + public AbstractNumCache() + { enableDigestCaching(true); // it changes only on poll } - - + + @Override protected final Num getSource() { if (!inited) markDigestDirty(); - + return (cachingEnabled ? cache : getCacheSource()); } - - + + @Override public final void poll() { inited = true; - + // poll source final Num source = getCacheSource(); source.markDigestDirty(); // poll cached - + // store source value cache.setTo(source); - + // mark my digest dirty markDigestDirty(); - + onConstraintChanged(); } - - + + @Override public abstract void onConstraintChanged(); - - + + @Override public abstract Num getCacheSource(); - - + + @Override public final void enableCaching(boolean yes) { cachingEnabled = yes; enableDigestCaching(yes); } - - + + @Override public final boolean isCachingEnabled() { return cachingEnabled; } - + } diff --git a/src/mightypork/utils/math/constraints/num/caching/NumCache.java b/src/mightypork/utils/math/constraints/num/caching/NumCache.java index 4e10d19..a2173e2 100644 --- a/src/mightypork/utils/math/constraints/num/caching/NumCache.java +++ b/src/mightypork/utils/math/constraints/num/caching/NumCache.java @@ -6,29 +6,30 @@ import mightypork.utils.math.constraints.num.Num; /** * Num cache implementation - * + * * @author Ondřej Hruška (MightyPork) */ public class NumCache extends AbstractNumCache { - + private final Num source; - - - public NumCache(Num source) { + + + public NumCache(Num source) + { this.source = source; } - - + + @Override public final Num getCacheSource() { return source; } - - + + @Override public void onConstraintChanged() { } - + } diff --git a/src/mightypork/utils/math/constraints/num/caching/NumDigest.java b/src/mightypork/utils/math/constraints/num/caching/NumDigest.java index 599706a..edb1e3a 100644 --- a/src/mightypork/utils/math/constraints/num/caching/NumDigest.java +++ b/src/mightypork/utils/math/constraints/num/caching/NumDigest.java @@ -5,15 +5,16 @@ import mightypork.utils.math.constraints.num.Num; public class NumDigest { - + public final double value; - - - public NumDigest(Num num) { + + + public NumDigest(Num num) + { this.value = num.value(); } - - + + @Override public String toString() { diff --git a/src/mightypork/utils/math/constraints/num/proxy/NumAdapter.java b/src/mightypork/utils/math/constraints/num/proxy/NumAdapter.java index 5b2693d..19de7b7 100644 --- a/src/mightypork/utils/math/constraints/num/proxy/NumAdapter.java +++ b/src/mightypork/utils/math/constraints/num/proxy/NumAdapter.java @@ -5,14 +5,14 @@ import mightypork.utils.math.constraints.num.Num; public abstract class NumAdapter extends Num { - + protected abstract Num getSource(); - - + + @Override public double value() { return getSource().value(); } - + } diff --git a/src/mightypork/utils/math/constraints/num/proxy/NumProxy.java b/src/mightypork/utils/math/constraints/num/proxy/NumProxy.java index da9b67f..96f8687 100644 --- a/src/mightypork/utils/math/constraints/num/proxy/NumProxy.java +++ b/src/mightypork/utils/math/constraints/num/proxy/NumProxy.java @@ -8,34 +8,36 @@ import mightypork.utils.math.constraints.num.PluggableNumBound; /** * Pluggable num proxy - * + * * @author Ondřej Hruška (MightyPork) */ public class NumProxy extends NumAdapter implements PluggableNumBound { - + private NumBound backing = null; - - - public NumProxy() { + + + public NumProxy() + { } - - - public NumProxy(NumBound bound) { + + + public NumProxy(NumBound bound) + { backing = bound; } - - + + @Override public void setNum(NumBound num) { this.backing = num; } - - + + @Override protected Num getSource() { return backing.getNum(); } - + } diff --git a/src/mightypork/utils/math/constraints/num/var/NumMutable.java b/src/mightypork/utils/math/constraints/num/var/NumMutable.java index e359473..4a22609 100644 --- a/src/mightypork/utils/math/constraints/num/var/NumMutable.java +++ b/src/mightypork/utils/math/constraints/num/var/NumMutable.java @@ -6,30 +6,30 @@ import mightypork.utils.math.constraints.num.Num; /** * Mutable numeric variable - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class NumMutable extends Num { - + /** * Assign a value - * + * * @param value new value */ public abstract void setTo(double value); - - + + /** * Assign a value - * + * * @param value new value */ public void setTo(Num value) { setTo(value.value()); } - - + + /** * Set to zero */ @@ -37,5 +37,5 @@ public abstract class NumMutable extends Num { { setTo(0); } - + } diff --git a/src/mightypork/utils/math/constraints/num/var/NumVar.java b/src/mightypork/utils/math/constraints/num/var/NumVar.java index 015fe41..54ed86b 100644 --- a/src/mightypork/utils/math/constraints/num/var/NumVar.java +++ b/src/mightypork/utils/math/constraints/num/var/NumVar.java @@ -6,35 +6,37 @@ import mightypork.utils.math.constraints.num.Num; /** * Mutable numeric variable. - * + * * @author Ondřej Hruška (MightyPork) */ public class NumVar extends NumMutable { - + private double value; - - - public NumVar(Num value) { + + + public NumVar(Num value) + { this(value.value()); } - - - public NumVar(double value) { + + + public NumVar(double value) + { this.value = value; } - - + + @Override public double value() { return value; } - - + + @Override public void setTo(double value) { this.value = value; } - + } diff --git a/src/mightypork/utils/math/constraints/rect/PluggableRectBound.java b/src/mightypork/utils/math/constraints/rect/PluggableRectBound.java index c29a0e9..acf94d8 100644 --- a/src/mightypork/utils/math/constraints/rect/PluggableRectBound.java +++ b/src/mightypork/utils/math/constraints/rect/PluggableRectBound.java @@ -3,14 +3,14 @@ package mightypork.utils.math.constraints.rect; /** * Pluggable rect bound - * + * * @author Ondřej Hruška (MightyPork) */ public interface PluggableRectBound extends RectBound { - + /** * @param rect context to set */ abstract void setRect(RectBound rect); - + } diff --git a/src/mightypork/utils/math/constraints/rect/Rect.java b/src/mightypork/utils/math/constraints/rect/Rect.java index d8b8ea7..dc20741 100644 --- a/src/mightypork/utils/math/constraints/rect/Rect.java +++ b/src/mightypork/utils/math/constraints/rect/Rect.java @@ -18,166 +18,166 @@ import mightypork.utils.math.constraints.vect.VectConst; /** * Common methods for all kinds of Rects - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class Rect implements RectBound, CachedDigestable { - + public static final RectConst ZERO = new RectConst(0, 0, 0, 0); public static final RectConst ONE = new RectConst(0, 0, 1, 1); - - + + @FactoryMethod public static Rect make(Num width, Num height) { final Vect origin = Vect.ZERO; final Vect size = Vect.make(width, height); - + return Rect.make(origin, size); } - - + + public static Rect make(Vect size) { return Rect.make(size.xn(), size.yn()); } - - + + @FactoryMethod public static Rect make(RectBound bound) { return new RectProxy(bound); } - - + + @FactoryMethod public static Rect make(Num x, Num y, Num width, Num height) { final Vect origin = Vect.make(x, y); final Vect size = Vect.make(width, height); - + return Rect.make(origin, size); } - - + + @FactoryMethod public static Rect make(Vect origin, Num width, Num height) { return make(origin, Vect.make(width, height)); } - - + + @FactoryMethod public static Rect make(final Vect origin, final Vect size) { return new RectVectAdapter(origin, size); } - - + + @FactoryMethod public static RectConst make(NumConst width, NumConst height) { final VectConst origin = Vect.ZERO; final VectConst size = Vect.make(width, height); - + return Rect.make(origin, size); } - - + + public static Rect make(Num side) { return make(side, side); } - - + + public static RectConst make(NumConst side) { return make(side, side); } - - + + public static RectConst make(double side) { return make(side, side); } - - + + @FactoryMethod public static RectConst make(NumConst x, NumConst y, NumConst width, NumConst height) { final VectConst origin = Vect.make(x, y); final VectConst size = Vect.make(width, height); - + return Rect.make(origin, size); } - - + + @FactoryMethod public static RectConst make(final VectConst origin, final VectConst size) { return new RectConst(origin, size); } - - + + @FactoryMethod public static RectConst make(double width, double height) { return Rect.make(0, 0, width, height); } - - + + @FactoryMethod public static RectConst make(double x, double y, double width, double height) { return new RectConst(x, y, width, height); } - - + + @FactoryMethod public static RectVar makeVar(double x, double y) { return Rect.makeVar(0, 0, x, y); } - - + + @FactoryMethod public static RectVar makeVar(Rect copied) { return Rect.makeVar(copied.origin(), copied.size()); } - - + + @FactoryMethod public static RectVar makeVar(Vect origin, Vect size) { return Rect.makeVar(origin.x(), origin.y(), size.x(), size.y()); } - - + + @FactoryMethod public static RectVar makeVar(double x, double y, double width, double height) { return new RectVar(x, y, width, height); } - - + + @FactoryMethod public static RectVar makeVar() { return Rect.makeVar(Rect.ZERO); } - + private Vect p_bl; private Vect p_bc; private Vect p_br; // p_t == origin private Vect p_tc; private Vect p_tr; - + private Vect p_cl; private Vect p_cc; private Vect p_cr; - + private Num p_x; private Num p_y; private Num p_w; @@ -192,20 +192,20 @@ public abstract class Rect implements RectBound, CachedDigestable { private Rect p_edge_b; private Rect p_axis_v; private Rect p_axis_h; - + private final DigestCache dc = new DigestCache() { - + @Override protected RectDigest createDigest() { return new RectDigest(Rect.this); } }; - - + + /** * Get a copy of current value - * + * * @return copy */ public RectConst freeze() @@ -213,135 +213,135 @@ public abstract class Rect implements RectBound, CachedDigestable { // must NOT call RectVal.make, it'd cause infinite recursion. return new RectConst(this); } - - + + /** * Wrap this constraint into a caching adapter. Value will stay fixed (ie. * no re-calculations) until cache receives a poll() call. - * + * * @return the caching adapter */ public RectCache cached() { return new RectCache(this); } - - + + @Override public RectDigest digest() { return dc.digest(); } - - + + @Override public void enableDigestCaching(boolean yes) { dc.enableDigestCaching(yes); } - - + + @Override public boolean isDigestCachingEnabled() { return dc.isDigestCachingEnabled(); } - - + + @Override public void markDigestDirty() { dc.markDigestDirty(); } - - + + @Override public Rect getRect() { return this; } - - + + @Override public String toString() { return String.format("Rect { at %s , size %s }", origin(), size()); } - - + + /** * Origin (top left). - * + * * @return origin (top left) */ public abstract Vect origin(); - - + + /** * Size (spanning right down from Origin). - * + * * @return size vector */ public abstract Vect size(); - - + + /** * Add vector to origin - * + * * @param move offset vector * @return result */ public Rect move(final Vect move) { return new Rect() { - + private final Rect t = Rect.this; - - + + @Override public Vect size() { return t.size(); } - - + + @Override public Vect origin() { return t.origin().add(move); } - + }; } - - + + public Rect moveX(Num x) { return move(x, Num.ZERO); } - - + + public Rect moveY(Num y) { return move(Num.ZERO, y); } - - + + public Rect moveX(double x) { return move(x, 0); } - - + + public Rect moveY(double y) { return move(0, y); } - - + + /** * Add X and Y to origin - * + * * @param x x to add * @param y y to add * @return result @@ -349,67 +349,67 @@ public abstract class Rect implements RectBound, CachedDigestable { public Rect move(final double x, final double y) { return new Rect() { - + private final Rect t = Rect.this; - - + + @Override public Vect size() { return t.size(); } - - + + @Override public Vect origin() { return t.origin().add(x, y); } - + }; } - - + + public Rect move(final Num x, final Num y) { return new Rect() { - + private final Rect t = Rect.this; - - + + @Override public Vect size() { return t.size(); } - - + + @Override public Vect origin() { return t.origin().add(x, y); } - + }; } - - + + /** * Shrink to sides - * + * * @param shrink shrink size (horizontal and vertical) * @return result */ - + public Rect shrink(Vect shrink) { return shrink(shrink.x(), shrink.y()); } - - + + /** * Shrink to all sides - * + * * @param shrink shrink * @return result */ @@ -417,11 +417,11 @@ public abstract class Rect implements RectBound, CachedDigestable { { return shrink(shrink, shrink, shrink, shrink); } - - + + /** * Shrink to all sides - * + * * @param shrink shrink * @return result */ @@ -429,11 +429,11 @@ public abstract class Rect implements RectBound, CachedDigestable { { return shrink(shrink, shrink, shrink, shrink); } - - + + /** * Shrink to sides at sides - * + * * @param x horizontal shrink * @param y vertical shrink * @return result @@ -442,17 +442,17 @@ public abstract class Rect implements RectBound, CachedDigestable { { return shrink(x, x, y, y); } - - + + public Rect shrink(Num x, Num y) { return shrink(x, x, y, y); } - - + + /** * Shrink the rect - * + * * @param left shrink * @param right shrink * @param top shrink @@ -463,107 +463,107 @@ public abstract class Rect implements RectBound, CachedDigestable { { return grow(-left, -right, -top, -bottom); } - - + + public Rect shrinkLeft(final double shrink) { return growLeft(-shrink); } - - + + public Rect shrinkRight(final double shrink) { return growRight(-shrink); } - - + + public Rect shrinkTop(final double shrink) { return growUp(-shrink); } - - + + public Rect shrinkBottom(final double shrink) { return growDown(-shrink); } - - + + public Rect growLeft(final double shrink) { return grow(shrink, 0, 0, 0); } - - + + public Rect growRight(final double shrink) { return grow(0, shrink, 0, 0); } - - + + public Rect growUp(final double shrink) { return grow(0, 0, shrink, 0); } - - + + public Rect growDown(final double shrink) { return grow(0, 0, 0, shrink); } - - + + public Rect shrinkLeft(final Num shrink) { return shrink(shrink, Num.ZERO, Num.ZERO, Num.ZERO); } - - + + public Rect shrinkRight(final Num shrink) { return shrink(Num.ZERO, shrink, Num.ZERO, Num.ZERO); } - - + + public Rect shrinkTop(final Num shrink) { return shrink(Num.ZERO, Num.ZERO, shrink, Num.ZERO); } - - + + public Rect shrinkBottom(final Num shrink) { return shrink(Num.ZERO, Num.ZERO, Num.ZERO, shrink); } - - + + public Rect growLeft(final Num shrink) { return grow(shrink, Num.ZERO, Num.ZERO, Num.ZERO); } - - + + public Rect growRight(final Num shrink) { return grow(Num.ZERO, shrink, Num.ZERO, Num.ZERO); } - - + + public Rect growUp(final Num shrink) { return grow(Num.ZERO, Num.ZERO, shrink, Num.ZERO); } - - + + public Rect growDown(final Num shrink) { return grow(Num.ZERO, Num.ZERO, Num.ZERO, shrink); } - - + + /** * Grow to sides - * + * * @param grow grow size (added to each side) * @return grown copy */ @@ -571,11 +571,11 @@ public abstract class Rect implements RectBound, CachedDigestable { { return grow(grow.x(), grow.y()); } - - + + /** * Grow to all sides - * + * * @param grow grow * @return result */ @@ -583,11 +583,11 @@ public abstract class Rect implements RectBound, CachedDigestable { { return grow(grow, grow, grow, grow); } - - + + /** * Grow to all sides - * + * * @param grow grow * @return result */ @@ -595,11 +595,11 @@ public abstract class Rect implements RectBound, CachedDigestable { { return grow(grow, grow, grow, grow); } - - + + /** * Grow to sides - * + * * @param x horizontal grow * @param y vertical grow * @return result @@ -608,17 +608,17 @@ public abstract class Rect implements RectBound, CachedDigestable { { return grow(x, x, y, y); } - - + + public Rect grow(Num x, Num y) { return grow(x, x, y, y); } - - + + /** * Grow the rect - * + * * @param left growth * @param right growth * @param top growth @@ -628,324 +628,324 @@ public abstract class Rect implements RectBound, CachedDigestable { public Rect grow(final double left, final double right, final double top, final double bottom) { return new Rect() { - + private final Rect t = Rect.this; - - + + @Override public Vect size() { return t.size().add(left + right, top + bottom); } - - + + @Override public Vect origin() { return t.origin().sub(left, top); } - + }; } - - + + public Rect shrink(final Num left, final Num right, final Num top, final Num bottom) { return new Rect() { - + private final Rect t = Rect.this; - - + + @Override public Vect size() { return t.size().sub(left.add(right), top.add(bottom)); } - - + + @Override public Vect origin() { return t.origin().add(left, top); } - + }; } - - + + public Rect grow(final Num left, final Num right, final Num top, final Num bottom) { - + return new Rect() { - + private final Rect t = Rect.this; - - + + @Override public Vect size() { return t.size().add(left.add(right), top.add(bottom)); } - - + + @Override public Vect origin() { return t.origin().sub(left, top); } - + }; } - - + + /** * Round coords - * + * * @return result */ public Rect round() { - + return new Rect() { - + private final Rect t = Rect.this; - - + + @Override public Vect size() { return t.size().round(); } - - + + @Override public Vect origin() { return t.origin().round(); } - + }; } - - + + /** * Round coords down - * + * * @return result */ public Rect floor() { - + return new Rect() { - + private final Rect t = Rect.this; - - + + @Override public Vect size() { return t.size().floor(); } - - + + @Override public Vect origin() { return t.origin().floor(); } - + }; } - - + + /** * Round coords up - * + * * @return result */ public Rect ceil() { - + return new Rect() { - + private final Rect t = Rect.this; - - + + @Override public Vect size() { return t.size().ceil(); } - - + + @Override public Vect origin() { return t.origin().ceil(); } - + }; } - - + + public Num x() { return p_x != null ? p_x : (p_x = origin().xn()); } - - + + public Num y() { return p_y != null ? p_y : (p_y = origin().yn()); } - - + + public Num width() { return p_w != null ? p_w : (p_w = size().xn()); } - - + + public Num height() { return p_h != null ? p_h : (p_h = size().yn()); } - - + + public Num left() { return p_l != null ? p_l : (p_l = origin().xn()); } - - + + public Num right() { return p_r != null ? p_r : (p_r = origin().xn().add(size().xn())); } - - + + public Num top() { return p_t != null ? p_t : (p_t = origin().yn()); } - - + + public Num bottom() { return p_b != null ? p_b : (p_b = origin().yn().add(size().yn())); } - - + + public Vect topLeft() { return origin(); } - - + + public Vect topCenter() { return p_tc != null ? p_tc : (p_tc = origin().add(size().xn().half(), Num.ZERO)); } - - + + public Vect topRight() { return p_tr != null ? p_tr : (p_tr = origin().add(size().xn(), Num.ZERO)); } - - + + public Vect centerLeft() { return p_cl != null ? p_cl : (p_cl = origin().add(Num.ZERO, size().yn().half())); } - - + + public Vect center() { return p_cc != null ? p_cc : (p_cc = origin().add(size().half())); } - - + + public Vect centerRight() { return p_cr != null ? p_cr : (p_cr = origin().add(size().xn(), size().yn().half())); } - - + + public Vect bottomLeft() { return p_bl != null ? p_bl : (p_bl = origin().add(Num.ZERO, size().yn())); } - - + + public Vect bottomCenter() { return p_bc != null ? p_bc : (p_bc = origin().add(size().xn().half(), size().yn())); } - - + + public Vect bottomRight() { return p_br != null ? p_br : (p_br = origin().add(size().xn(), size().yn())); } - - + + public Rect leftEdge() { return p_edge_l != null ? p_edge_l : (p_edge_l = topLeft().expand(Num.ZERO, Num.ZERO, Num.ZERO, height())); } - - + + public Rect rightEdge() { return p_edge_r != null ? p_edge_r : (p_edge_r = topRight().expand(Num.ZERO, Num.ZERO, Num.ZERO, height())); } - - + + public Rect topEdge() { return p_edge_t != null ? p_edge_t : (p_edge_t = topLeft().expand(Num.ZERO, width(), Num.ZERO, Num.ZERO)); } - - + + public Rect bottomEdge() { return p_edge_b != null ? p_edge_b : (p_edge_b = bottomLeft().expand(Num.ZERO, width(), Num.ZERO, Num.ZERO)); } - - + + public Rect axisV() { return p_axis_v != null ? p_axis_v : (p_axis_v = topCenter().expand(Num.ZERO, Num.ZERO, Num.ZERO, height())); } - - + + public Rect axisH() { return p_axis_h != null ? p_axis_h : (p_axis_h = centerLeft().expand(Num.ZERO, width(), Num.ZERO, Num.ZERO)); } - - + + /** * Center to given point - * + * * @param point new center * @return centered */ public Rect centerTo(final Vect point) { return new Rect() { - + Rect t = Rect.this; - - + + @Override public Vect size() { return t.size(); } - - + + @Override public Vect origin() { @@ -953,11 +953,11 @@ public abstract class Rect implements RectBound, CachedDigestable { } }; } - - + + /** * Check if point is inside this rectangle - * + * * @param point point to test * @return is inside */ @@ -965,19 +965,19 @@ public abstract class Rect implements RectBound, CachedDigestable { { final double x = point.x(); final double y = point.y(); - + final double x1 = origin().x(); final double y1 = origin().y(); final double x2 = x1 + size().x(); final double y2 = y1 + size().y(); - + return x >= x1 && y >= y1 && x <= x2 && y <= y2; } - - + + /** * Center to given rect's center - * + * * @param parent rect to center to * @return centered */ @@ -985,12 +985,12 @@ public abstract class Rect implements RectBound, CachedDigestable { { return centerTo(parent.center()); } - - + + /** * Get TiledRect with given number of evenly spaced tiles. Tile indexes are * one-based by default. - * + * * @param horizontal horizontal tile count * @param vertical vertical tile count * @return tiled rect @@ -999,12 +999,12 @@ public abstract class Rect implements RectBound, CachedDigestable { { return new TiledRect(this, horizontal, vertical); } - - + + /** * Get TiledRect with N columns and 1 row. Column indexes are one-based by * default. - * + * * @param columns number of columns * @return tiled rect */ @@ -1012,12 +1012,12 @@ public abstract class Rect implements RectBound, CachedDigestable { { return new TiledRect(this, columns, 1); } - - + + /** * Get TiledRect with N rows and 1 column. Row indexes are one-based by * default. - * + * * @param rows number of columns * @return tiled rect */ @@ -1025,11 +1025,11 @@ public abstract class Rect implements RectBound, CachedDigestable { { return new TiledRect(this, 1, rows); } - - + + /** * Check for intersection - * + * * @param other other rect * @return true if they intersect */ @@ -1039,23 +1039,23 @@ public abstract class Rect implements RectBound, CachedDigestable { double th = this.size().y(); double rw = other.size().x(); double rh = other.size().y(); - + if (rw <= 0 || rh <= 0 || tw <= 0 || th <= 0) { return false; } - + final double tx = this.origin().x(); final double ty = this.origin().y(); final double rx = other.origin().x(); final double ry = other.origin().y(); - + rw += rx; rh += ry; tw += tx; th += ty; - + // overflow || intersect return ((rw < rx || rw > tx) && (rh < ry || rh > ty) && (tw < tx || tw > rx) && (th < ty || th > ry)); } - + } diff --git a/src/mightypork/utils/math/constraints/rect/RectBound.java b/src/mightypork/utils/math/constraints/rect/RectBound.java index 900913b..84d7859 100644 --- a/src/mightypork/utils/math/constraints/rect/RectBound.java +++ b/src/mightypork/utils/math/constraints/rect/RectBound.java @@ -4,11 +4,11 @@ package mightypork.utils.math.constraints.rect; /** * Interface for something that has/is a Rect. Rect itself implements it as * well. - * + * * @author Ondřej Hruška (MightyPork) */ public interface RectBound { - + /** * @return the Rect value */ diff --git a/src/mightypork/utils/math/constraints/rect/RectConst.java b/src/mightypork/utils/math/constraints/rect/RectConst.java index c1195a8..9f74fb5 100644 --- a/src/mightypork/utils/math/constraints/rect/RectConst.java +++ b/src/mightypork/utils/math/constraints/rect/RectConst.java @@ -11,14 +11,14 @@ import mightypork.utils.math.constraints.vect.VectConst; * Rectangle with constant bounds, that can never change.
* It's arranged so that operations with constant arguments yield constant * results. - * + * * @author Ondřej Hruška (MightyPork) */ public class RectConst extends Rect { - + private final VectConst pos; private final VectConst size; - + // cached with lazy loading private NumConst v_b; private NumConst v_r; @@ -40,45 +40,48 @@ public class RectConst extends Rect { private RectConst v_ceil; private RectConst v_axis_v; private RectConst v_axis_h; - - + + /** * Create at given origin, with given size. - * + * * @param x * @param y * @param width * @param height */ - RectConst(double x, double y, double width, double height) { + RectConst(double x, double y, double width, double height) + { this.pos = Vect.make(x, y); this.size = Vect.make(width, height); } - - + + /** * Create at given origin, with given size. - * + * * @param origin * @param size */ - RectConst(Vect origin, Vect size) { + RectConst(Vect origin, Vect size) + { this.pos = origin.freeze(); this.size = size.freeze(); } - - + + /** * Create at given origin, with given size. - * + * * @param another other coord */ - RectConst(Rect another) { + RectConst(Rect another) + { this.pos = another.origin().freeze(); this.size = another.size().freeze(); } - - + + /** * @deprecated it's useless to copy a constant */ @@ -88,394 +91,394 @@ public class RectConst extends Rect { { return this; // already constant } - - + + @Override public RectDigest digest() { return (digest != null) ? digest : (digest = super.digest()); } - - + + @Override public VectConst origin() { return pos; } - - + + @Override public VectConst size() { return size; } - - + + @Override public RectConst move(Vect move) { return move(move.x(), move.y()); } - - + + @Override public RectConst move(double x, double y) { return Rect.make(pos.add(x, y), size); } - - + + public RectConst move(NumConst x, NumConst y) { return super.move(x, y).freeze(); } - - + + @Override public RectConst shrink(double left, double right, double top, double bottom) { return super.shrink(left, right, top, bottom).freeze(); - + } - - + + @Override public RectConst grow(double left, double right, double top, double bottom) { return super.grow(left, right, top, bottom).freeze(); } - - + + @Override public RectConst round() { return (v_round != null) ? v_round : (v_round = Rect.make(pos.round(), size.round())); } - - + + @Override public RectConst floor() { return (v_floor != null) ? v_floor : (v_floor = Rect.make(pos.floor(), size.floor())); } - - + + @Override public RectConst ceil() { return (v_ceil != null) ? v_ceil : (v_ceil = Rect.make(pos.ceil(), size.ceil())); } - - + + @Override public NumConst x() { return pos.xn(); } - - + + @Override public NumConst y() { return pos.yn(); } - - + + @Override public NumConst width() { return size.xn(); } - - + + @Override public NumConst height() { return size.yn(); } - - + + @Override public NumConst left() { return pos.xn(); } - - + + @Override public NumConst right() { return (v_r != null) ? v_r : (v_r = super.right().freeze()); } - - + + @Override public NumConst top() { return pos.yn(); } - - + + @Override public NumConst bottom() { return (v_b != null) ? v_b : (v_b = super.bottom().freeze()); } - - + + @Override public VectConst topLeft() { return pos; } - - + + @Override public VectConst topCenter() { return (v_tc != null) ? v_tc : (v_tc = super.topCenter().freeze()); } - - + + @Override public VectConst topRight() { return (v_tr != null) ? v_tr : (v_tr = super.topRight().freeze()); } - - + + @Override public VectConst centerLeft() { return (v_cl != null) ? v_cl : (v_cl = super.centerLeft().freeze()); } - - + + @Override public VectConst center() { return (v_c != null) ? v_c : (v_c = super.center().freeze()); } - - + + @Override public VectConst centerRight() { return (v_cr != null) ? v_cr : (v_cr = super.centerRight().freeze()); } - - + + @Override public VectConst bottomLeft() { return (v_bl != null) ? v_bl : (v_bl = super.bottomLeft().freeze()); } - - + + @Override public VectConst bottomCenter() { return (v_bc != null) ? v_bc : (v_bc = super.bottomCenter().freeze()); } - - + + @Override public VectConst bottomRight() { return (v_br != null) ? v_br : (v_br = super.bottomRight().freeze()); } - - + + @Override public RectConst leftEdge() { return (v_edge_l != null) ? v_edge_l : (v_edge_l = super.leftEdge().freeze()); } - - + + @Override public RectConst rightEdge() { return (v_edge_r != null) ? v_edge_r : (v_edge_r = super.rightEdge().freeze()); } - - + + @Override public RectConst topEdge() { return (v_edge_t != null) ? v_edge_t : (v_edge_t = super.topEdge().freeze()); } - - + + @Override public RectConst bottomEdge() { return (v_edge_b != null) ? v_edge_b : (v_edge_b = super.bottomEdge().freeze()); } - - + + @Override public Rect axisV() { return (v_axis_v != null) ? v_axis_v : (v_axis_v = super.axisV().freeze()); } - - + + @Override public Rect axisH() { return (v_axis_h != null) ? v_axis_h : (v_axis_h = super.axisH().freeze()); } - - + + @Override public Rect shrink(Vect shrink) { return super.shrink(shrink); } - - + + @Override public RectConst shrink(double x, double y) { return super.shrink(x, y).freeze(); } - - + + public RectConst shrink(NumConst left, NumConst right, NumConst top, NumConst bottom) { return super.shrink(left, right, top, bottom).freeze(); } - - + + public RectConst grow(NumConst left, NumConst right, NumConst top, NumConst bottom) { return super.grow(left, right, top, bottom).freeze(); } - - + + @Override public RectConst shrinkLeft(double shrink) { return super.shrinkLeft(shrink).freeze(); } - - + + @Override public RectConst shrinkRight(double shrink) { return super.shrinkRight(shrink).freeze(); } - - + + @Override public RectConst shrinkTop(double shrink) { return super.shrinkTop(shrink).freeze(); } - - + + @Override public RectConst shrinkBottom(double shrink) { return super.shrinkBottom(shrink).freeze(); } - - + + @Override public RectConst growLeft(double shrink) { return super.growLeft(shrink).freeze(); } - - + + @Override public RectConst growRight(double shrink) { return super.growRight(shrink).freeze(); } - - + + @Override public RectConst growUp(double shrink) { return super.growUp(shrink).freeze(); } - - + + @Override public RectConst growDown(double shrink) { return super.growDown(shrink).freeze(); } - - + + public RectConst shrinkLeft(NumConst shrink) { return super.shrinkLeft(shrink).freeze(); } - - + + public RectConst shrinkRight(NumConst shrink) { return super.shrinkRight(shrink).freeze(); } - - + + public RectConst shrinkTop(NumConst shrink) { return super.shrinkTop(shrink).freeze(); } - - + + public RectConst shrinkBottom(NumConst shrink) { return super.shrinkBottom(shrink).freeze(); } - - + + public RectConst growLeft(NumConst shrink) { return super.growLeft(shrink).freeze(); } - - + + public RectConst growRight(NumConst shrink) { return super.growRight(shrink).freeze(); } - - + + public RectConst growUp(NumConst shrink) { return super.growUp(shrink).freeze(); } - - + + public RectConst growBottom(NumConst shrink) { return super.growDown(shrink).freeze(); } - - + + public RectConst centerTo(VectConst point) { return super.centerTo(point).freeze(); } - - + + public RectConst centerTo(RectConst parent) { return super.centerTo(parent).freeze(); } - - + + public RectConst shrink(NumConst x, NumConst y) { return super.shrink(x, y).freeze(); } - - + + public RectConst grow(NumConst x, NumConst y) { return super.grow(x, y).freeze(); diff --git a/src/mightypork/utils/math/constraints/rect/builders/TiledRect.java b/src/mightypork/utils/math/constraints/rect/builders/TiledRect.java index 0b63f4f..49849d7 100644 --- a/src/mightypork/utils/math/constraints/rect/builders/TiledRect.java +++ b/src/mightypork/utils/math/constraints/rect/builders/TiledRect.java @@ -9,46 +9,47 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Utility for cutting rect into evenly sized cells. - * + * * @author Ondřej Hruška (MightyPork) */ public class TiledRect extends RectProxy { - + final private int tilesY; final private int tilesX; final private Num perRow; final private Num perCol; - + /** Left top tile */ private Rect aTile; - - - public TiledRect(Rect source, int horizontal, int vertical) { + + + public TiledRect(Rect source, int horizontal, int vertical) + { super(source); this.tilesX = horizontal; this.tilesY = vertical; - + this.perRow = height().div(vertical); this.perCol = width().div(horizontal); - + this.aTile = Rect.make(origin(), perCol, perRow); } - - + + /** * Set tile overlap. Applies only to tile, not span. - * + * * @param overlap how far to overlap to neighbouring tiles on all sides */ public void setOverlap(double overlap) { aTile = aTile.grow(overlap); } - - + + /** * Get a tile. - * + * * @param x x position * @param y y position * @return tile @@ -59,18 +60,18 @@ public class TiledRect extends RectProxy { if (x >= tilesX || x < 0) { throw new IndexOutOfBoundsException("X coordinate out fo range: " + x); } - + if (y >= tilesY || y < 0) { throw new IndexOutOfBoundsException("Y coordinate out of range: " + y); } - + return aTile.move(perCol.mul(x), perRow.mul(y)); } - - + + /** * Get a span (tile spanning across multiple cells) - * + * * @param x x start position * @param y y start position * @param size_x horizontal size (columns) @@ -82,28 +83,28 @@ public class TiledRect extends RectProxy { { final int x_to = x + size_x - 1; final int y_to = y + size_y - 1; - + if (size_x <= 0 || size_y <= 0) { throw new IndexOutOfBoundsException("Size must be > 0."); } - + if (x >= tilesX || x < 0 || x_to >= tilesX || x_to < 0) { throw new IndexOutOfBoundsException("X coordinate(s) out of range."); } - + if (y >= tilesY || y < 0 || y_to >= tilesY || y_to < 0) { throw new IndexOutOfBoundsException("Y coordinate(s) out of range."); } - + final Vect orig = origin().add(perCol.mul(x), perRow.mul(y)); - + return Rect.make(orig, perCol.mul(size_x), perRow.mul(size_y)); } - - + + /** * Get n-th column - * + * * @param n column index * @return the column tile * @throws IndexOutOfBoundsException when invalid index is specified. @@ -112,11 +113,11 @@ public class TiledRect extends RectProxy { { return tile(n, 0); } - - + + /** * Get n-th row - * + * * @param n row index * @return the row rect * @throws IndexOutOfBoundsException when invalid index is specified. diff --git a/src/mightypork/utils/math/constraints/rect/caching/AbstractRectCache.java b/src/mightypork/utils/math/constraints/rect/caching/AbstractRectCache.java index 75c27a9..33e69fe 100644 --- a/src/mightypork/utils/math/constraints/rect/caching/AbstractRectCache.java +++ b/src/mightypork/utils/math/constraints/rect/caching/AbstractRectCache.java @@ -15,60 +15,61 @@ import mightypork.utils.math.constraints.rect.var.RectVar; * Values are held in a caching VectVar, and digest caching is enabled by * default. *

- * + * * @author Ondřej Hruška (MightyPork) */ public abstract class AbstractRectCache extends RectAdapter implements CachedConstraint { - + private final RectVar cache = Rect.makeVar(); private boolean inited = false; private boolean cachingEnabled = true; - - - public AbstractRectCache() { + + + public AbstractRectCache() + { enableDigestCaching(true); // it changes only on poll } - - + + @Override protected final Rect getSource() { if (!inited) poll(); - + return (cachingEnabled ? cache : getCacheSource()); } - - + + @Override public final void poll() { inited = true; - + // poll source final Rect source = getCacheSource(); source.markDigestDirty(); // poll cached - + // store source value cache.setTo(source); - + markDigestDirty(); - + onConstraintChanged(); } - - + + @Override public final void enableCaching(boolean yes) { cachingEnabled = yes; enableDigestCaching(yes); } - - + + @Override public final boolean isCachingEnabled() { return cachingEnabled; } - + } diff --git a/src/mightypork/utils/math/constraints/rect/caching/RectCache.java b/src/mightypork/utils/math/constraints/rect/caching/RectCache.java index db1b858..9f386c7 100644 --- a/src/mightypork/utils/math/constraints/rect/caching/RectCache.java +++ b/src/mightypork/utils/math/constraints/rect/caching/RectCache.java @@ -6,29 +6,30 @@ import mightypork.utils.math.constraints.rect.Rect; /** * Rect cache implementation - * + * * @author Ondřej Hruška (MightyPork) */ public class RectCache extends AbstractRectCache { - + private final Rect source; - - - public RectCache(Rect source) { + + + public RectCache(Rect source) + { this.source = source; } - - + + @Override public final Rect getCacheSource() { return source; } - - + + @Override public void onConstraintChanged() { } - + } diff --git a/src/mightypork/utils/math/constraints/rect/caching/RectDigest.java b/src/mightypork/utils/math/constraints/rect/caching/RectDigest.java index 3007b9b..e5aee62 100644 --- a/src/mightypork/utils/math/constraints/rect/caching/RectDigest.java +++ b/src/mightypork/utils/math/constraints/rect/caching/RectDigest.java @@ -5,35 +5,37 @@ import mightypork.utils.math.constraints.rect.Rect; public class RectDigest { - + public final double x; public final double y; public final double width; public final double height; - + public final double left; public final double right; public final double top; public final double bottom; - - - public RectDigest(Rect rect) { + + + public RectDigest(Rect rect) + { this.x = rect.origin().x(); this.y = rect.origin().y(); - + this.width = rect.size().x(); this.height = rect.size().y(); - + this.left = x; this.right = x + width; this.top = y; this.bottom = y + height; } - - + + @Override public String toString() { - return String.format("Rect{ at: (%.1f, %.1f), size: (%.1f, %.1f), bounds: L %.1f R %.1f T %.1f B %.1f }", x, y, width, height, left, right, top, bottom); + return String + .format("Rect{ at: (%.1f, %.1f), size: (%.1f, %.1f), bounds: L %.1f R %.1f T %.1f B %.1f }", x, y, width, height, left, right, top, bottom); } } diff --git a/src/mightypork/utils/math/constraints/rect/proxy/RectAdapter.java b/src/mightypork/utils/math/constraints/rect/proxy/RectAdapter.java index cd1cd85..9b5b2ea 100644 --- a/src/mightypork/utils/math/constraints/rect/proxy/RectAdapter.java +++ b/src/mightypork/utils/math/constraints/rect/proxy/RectAdapter.java @@ -9,50 +9,50 @@ import mightypork.utils.math.constraints.vect.proxy.VectAdapter; /** * Rect proxy with abstract method for plugging in / generating rect * dynamically. - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class RectAdapter extends Rect { - + // adapters are needed in case the vect returned from source changes // (is replaced). This way, references to origin and rect will stay intact. - + private final VectAdapter originAdapter = new VectAdapter() { - + @Override protected Vect getSource() { return RectAdapter.this.getSource().origin(); } }; - + private final VectAdapter sizeAdapter = new VectAdapter() { - + @Override protected Vect getSource() { return RectAdapter.this.getSource().size(); } }; - - + + /** * @return the proxied coord */ protected abstract Rect getSource(); - - + + @Override public Vect origin() { return originAdapter; } - - + + @Override public Vect size() { return sizeAdapter; } - + } diff --git a/src/mightypork/utils/math/constraints/rect/proxy/RectProxy.java b/src/mightypork/utils/math/constraints/rect/proxy/RectProxy.java index 415f30f..db8b984 100644 --- a/src/mightypork/utils/math/constraints/rect/proxy/RectProxy.java +++ b/src/mightypork/utils/math/constraints/rect/proxy/RectProxy.java @@ -8,34 +8,36 @@ import mightypork.utils.math.constraints.rect.RectBound; /** * Pluggable rect proxy - * + * * @author Ondřej Hruška (MightyPork) */ public class RectProxy extends RectAdapter implements PluggableRectBound { - + private RectBound backing = null; - - - public RectProxy() { + + + public RectProxy() + { } - - - public RectProxy(RectBound proxied) { + + + public RectProxy(RectBound proxied) + { backing = proxied; } - - + + @Override public void setRect(RectBound proxied) { this.backing = proxied; } - - + + @Override public Rect getSource() { return backing.getRect(); } - + } diff --git a/src/mightypork/utils/math/constraints/rect/proxy/RectVectAdapter.java b/src/mightypork/utils/math/constraints/rect/proxy/RectVectAdapter.java index 95a2156..35c2f91 100644 --- a/src/mightypork/utils/math/constraints/rect/proxy/RectVectAdapter.java +++ b/src/mightypork/utils/math/constraints/rect/proxy/RectVectAdapter.java @@ -7,32 +7,33 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Rect made of two {@link Vect}s - * + * * @author Ondřej Hruška (MightyPork) */ public class RectVectAdapter extends Rect { - + private final Vect origin; private final Vect size; - - - public RectVectAdapter(Vect origin, Vect size) { + + + public RectVectAdapter(Vect origin, Vect size) + { this.origin = origin; this.size = size; } - - + + @Override public Vect origin() { return origin; } - - + + @Override public Vect size() { return size; } - + } diff --git a/src/mightypork/utils/math/constraints/rect/var/RectMutable.java b/src/mightypork/utils/math/constraints/rect/var/RectMutable.java index 0506dd8..dfa13e8 100644 --- a/src/mightypork/utils/math/constraints/rect/var/RectMutable.java +++ b/src/mightypork/utils/math/constraints/rect/var/RectMutable.java @@ -7,25 +7,25 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Mutable rectangle; operations change it's state. - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class RectMutable extends Rect { - + /** * Set to other rect's coordinates - * + * * @param rect other rect */ public void setTo(Rect rect) { setTo(rect.origin(), rect.size()); } - - + + /** * Set to given size and position - * + * * @param origin new origin * @param width new width * @param height new height @@ -34,11 +34,11 @@ public abstract class RectMutable extends Rect { { setTo(origin, Vect.make(width, height)); } - - + + /** * Set to given size and position - * + * * @param x origin.x * @param y origin.y * @param width new width @@ -48,11 +48,11 @@ public abstract class RectMutable extends Rect { { setTo(Vect.make(x, y), Vect.make(width, height)); } - - + + /** * Set to given size and position - * + * * @param origin new origin * @param size new size */ @@ -61,8 +61,8 @@ public abstract class RectMutable extends Rect { setOrigin(origin); setSize(size); } - - + + /** * Set to zero */ @@ -70,22 +70,22 @@ public abstract class RectMutable extends Rect { { setTo(Vect.ZERO, Vect.ZERO); } - - + + public abstract void setOrigin(double x, double y); - - + + public void setOrigin(Vect origin) { setOrigin(origin.x(), origin.y()); } - - + + public void setSize(Vect size) { setSize(size.x(), size.y()); } - - + + public abstract void setSize(double x, double y); } diff --git a/src/mightypork/utils/math/constraints/rect/var/RectVar.java b/src/mightypork/utils/math/constraints/rect/var/RectVar.java index 3ce2824..c04413a 100644 --- a/src/mightypork/utils/math/constraints/rect/var/RectVar.java +++ b/src/mightypork/utils/math/constraints/rect/var/RectVar.java @@ -6,46 +6,47 @@ import mightypork.utils.math.constraints.vect.var.VectVar; public class RectVar extends RectMutable { - + final VectVar pos = Vect.makeVar(); final VectVar size = Vect.makeVar(); - - + + /** * Create at given origin, with given size. - * + * * @param x * @param y * @param width * @param height */ - public RectVar(double x, double y, double width, double height) { + public RectVar(double x, double y, double width, double height) + { this.pos.setTo(x, y); this.size.setTo(width, height); } - - + + @Override public Vect origin() { return pos; } - - + + @Override public Vect size() { return size; } - - + + @Override public void setOrigin(double x, double y) { this.pos.setTo(x, y); } - - + + @Override public void setSize(double x, double y) { diff --git a/src/mightypork/utils/math/constraints/vect/PluggableVectBound.java b/src/mightypork/utils/math/constraints/vect/PluggableVectBound.java index 29c9884..b4142e0 100644 --- a/src/mightypork/utils/math/constraints/vect/PluggableVectBound.java +++ b/src/mightypork/utils/math/constraints/vect/PluggableVectBound.java @@ -3,14 +3,14 @@ package mightypork.utils.math.constraints.vect; /** * Pluggable vector constraint - * + * * @author Ondřej Hruška (MightyPork) */ public interface PluggableVectBound extends VectBound { - + /** * @param num bound to set */ abstract void setVect(VectBound num); - + } diff --git a/src/mightypork/utils/math/constraints/vect/Vect.java b/src/mightypork/utils/math/constraints/vect/Vect.java index 4841f9b..927931f 100644 --- a/src/mightypork/utils/math/constraints/vect/Vect.java +++ b/src/mightypork/utils/math/constraints/vect/Vect.java @@ -16,201 +16,201 @@ import mightypork.utils.math.constraints.vect.var.VectVar; /** * The most basic Vec methods - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class Vect implements VectBound, CachedDigestable { - + public static final VectConst ZERO = new VectConst(0, 0, 0); public static final VectConst ONE = new VectConst(1, 1, 1); - - + + @FactoryMethod public static Vect make(Num xy) { return make(xy, xy); } - - + + @FactoryMethod public static Vect make(Num xc, Num yc) { return Vect.make(xc, yc, Num.ZERO); } - - + + @FactoryMethod public static Vect make(Num xc, Num yc, Num zc) { return new VectNumAdapter(xc, yc, zc); } - - + + @FactoryMethod public static Vect make(VectBound bound) { return new VectProxy(bound); } - - + + @FactoryMethod public static VectConst make(NumConst xy) { return make(xy, xy); } - - + + @FactoryMethod public static VectConst make(NumConst xc, NumConst yc) { return Vect.make(xc, yc, Num.ZERO); } - - + + @FactoryMethod public static VectConst make(NumConst xc, NumConst yc, NumConst zc) { return new VectConst(xc.value(), yc.value(), zc.value()); } - - + + @FactoryMethod public static VectConst make(double xy) { return make(xy, xy); } - - + + @FactoryMethod public static VectConst make(double x, double y) { return Vect.make(x, y, 0); } - - + + @FactoryMethod public static VectConst make(double x, double y, double z) { return new VectConst(x, y, z); } - - + + @FactoryMethod public static VectVar makeVar() { return Vect.makeVar(Vect.ZERO); } - - + + @FactoryMethod public static VectVar makeVar(double x, double y) { return Vect.makeVar(x, y, 0); } - - + + @FactoryMethod public static VectVar makeVar(Vect copied) { return Vect.makeVar(copied.x(), copied.y(), copied.z()); } - - + + @FactoryMethod public static VectVar makeVar(double x, double y, double z) { return new VectVar(x, y, z); } - - + + public static VectConst fromString(String string) { try { String s = string.trim(); - + // drop whitespace s = s.replaceAll("\\s", ""); - + // drop brackets s = s.replaceAll("[\\(\\[\\{\\)\\]\\}]", ""); - + // norm separators s = s.replaceAll("[:;]", "|"); - + // norm floating point s = s.replaceAll("[,]", "."); - + final String[] parts = s.split("[|]"); - + if (parts.length >= 2) { - + final double x = Double.parseDouble(parts[0].trim()); final double y = Double.parseDouble(parts[1].trim()); - + if (parts.length == 2) { return Vect.make(x, y); } - + final double z = Double.parseDouble(parts[2].trim()); - + return Vect.make(x, y, z); } - + } catch (final RuntimeException e) { return null; } return null; } - - + + @Override public String toString() { return String.format("(%.1f ; %.1f ; %.1f)", x(), y(), z()); } - + private Num p_size; private Vect p_neg; private Vect p_half; private Vect p_abs; - + private Num p_xc; private Num p_yc; private Num p_zc; - + private final DigestCache dc = new DigestCache() { - + @Override protected VectDigest createDigest() { return new VectDigest(Vect.this); } }; - - + + /** * @return X coordinate */ public abstract double x(); - - + + /** * @return Y coordinate */ public abstract double y(); - - + + /** * (Implemented in Vect for convenience when creating 2D vects) - * + * * @return Z coordinate */ public double z() { return 0; } - - + + /** * @return X rounded */ @@ -218,8 +218,8 @@ public abstract class Vect implements VectBound, CachedDigestable { { return (int) Math.round(x()); } - - + + /** * @return Y rounded */ @@ -227,8 +227,8 @@ public abstract class Vect implements VectBound, CachedDigestable { { return (int) Math.round(y()); } - - + + /** * @return Z rounded */ @@ -236,69 +236,69 @@ public abstract class Vect implements VectBound, CachedDigestable { { return (int) Math.round(z()); } - - + + /** * @return X constraint */ public Num xn() { if (p_xc == null) p_xc = new Num() { - + @Override public double value() { return x(); } }; - + return p_xc; } - - + + /** * @return Y constraint */ public Num yn() { if (p_yc == null) p_yc = new Num() { - + @Override public double value() { return y(); } }; - + return p_yc; } - - + + /** * @return Z constraint */ public Num zn() { if (p_zc == null) p_zc = new Num() { - + @Override public double value() { return z(); } }; - + return p_zc; } - - + + @Override public final Vect getVect() { return this; } - - + + /** * @return true if zero */ @@ -306,62 +306,62 @@ public abstract class Vect implements VectBound, CachedDigestable { { return x() == 0 && y() == 0 && z() == 0; } - - + + /** * Get a static immutable copy of the current state. - * + * * @return a immutable copy */ public VectConst freeze() { return new VectConst(this); } - - + + /** * Wrap this constraint into a caching adapter. Value will stay fixed (ie. * no re-calculations) until cache receives a poll() call. - * + * * @return the caching adapter */ public VectCache cached() { return new VectCache(this); } - - + + @Override public VectDigest digest() { return dc.digest(); } - - + + @Override public void enableDigestCaching(boolean yes) { dc.enableDigestCaching(yes); } - - + + @Override public boolean isDigestCachingEnabled() { return dc.isDigestCachingEnabled(); } - - + + @Override public void markDigestDirty() { dc.markDigestDirty(); } - - + + /** * Get a view with X set to given value - * + * * @param x x coordinate * @return result */ @@ -369,11 +369,11 @@ public abstract class Vect implements VectBound, CachedDigestable { { return withX(Num.make(x)); } - - + + /** * Get a view with Y set to given value - * + * * @param y y coordinate * @return result */ @@ -381,11 +381,11 @@ public abstract class Vect implements VectBound, CachedDigestable { { return withY(Num.make(y)); } - - + + /** * Get a view with Z set to given value - * + * * @param z z coordinate * @return result */ @@ -393,29 +393,29 @@ public abstract class Vect implements VectBound, CachedDigestable { { return withZ(Num.make(z)); } - - + + public Vect withX(final Num x) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return x.value(); } - - + + @Override public double y() { return t.z(); } - - + + @Override public double z() { @@ -423,29 +423,29 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + public Vect withY(final Num y) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return t.x(); } - - + + @Override public double y() { return y.value(); } - - + + @Override public double z() { @@ -453,29 +453,29 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + public Vect withZ(final Num z) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return t.x(); } - - + + @Override public double y() { return t.y(); } - - + + @Override public double z() { @@ -483,48 +483,48 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Get absolute value (positive) - * + * * @return result */ public Vect abs() { if (p_abs == null) p_abs = new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return Math.abs(t.x()); } - - + + @Override public double y() { return Math.abs(t.y()); } - - + + @Override public double z() { return Math.abs(t.z()); } }; - + return p_abs; } - - + + /** * Add a vector. - * + * * @param vec offset * @return result */ @@ -532,12 +532,12 @@ public abstract class Vect implements VectBound, CachedDigestable { { return add(vec.xn(), vec.yn(), vec.zn()); } - - + + /** * Add to each component.
* Z is unchanged. - * + * * @param x x offset * @param y y offset * @return result @@ -546,11 +546,11 @@ public abstract class Vect implements VectBound, CachedDigestable { { return add(x, y, 0); } - - + + /** * Add to each component. - * + * * @param x x offset * @param y y offset * @param z z offset @@ -559,24 +559,24 @@ public abstract class Vect implements VectBound, CachedDigestable { public Vect add(final double x, final double y, final double z) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return t.x() + x; } - - + + @Override public double y() { return t.y() + y; } - - + + @Override public double z() { @@ -584,35 +584,35 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + public Vect add(Num x, Num y) { return add(x, y, Num.ZERO); } - - + + public Vect add(final Num x, final Num y, final Num z) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return t.x() + x.value(); } - - + + @Override public double y() { return t.y() + y.value(); } - - + + @Override public double z() { @@ -620,11 +620,11 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Get copy divided by two - * + * * @return result */ public Vect half() @@ -632,11 +632,11 @@ public abstract class Vect implements VectBound, CachedDigestable { if (p_half == null) p_half = mul(0.5); return p_half; } - - + + /** * Multiply each component. - * + * * @param d multiplier * @return result */ @@ -644,11 +644,11 @@ public abstract class Vect implements VectBound, CachedDigestable { { return mul(d, d, d); } - - + + /** * Multiply each component. - * + * * @param vec vector of multipliers * @return result */ @@ -656,12 +656,12 @@ public abstract class Vect implements VectBound, CachedDigestable { { return mul(vec.xn(), vec.yn(), vec.zn()); } - - + + /** * Multiply each component.
* Z is unchanged. - * + * * @param x x multiplier * @param y y multiplier * @return result @@ -670,11 +670,11 @@ public abstract class Vect implements VectBound, CachedDigestable { { return mul(x, y, 1); } - - + + /** * Multiply each component. - * + * * @param x x multiplier * @param y y multiplier * @param z z multiplier @@ -683,24 +683,24 @@ public abstract class Vect implements VectBound, CachedDigestable { public Vect mul(final double x, final double y, final double z) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return t.x() * x; } - - + + @Override public double y() { return t.y() * y; } - - + + @Override public double z() { @@ -708,11 +708,11 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Multiply each component. - * + * * @param d multiplier * @return result */ @@ -720,11 +720,11 @@ public abstract class Vect implements VectBound, CachedDigestable { { return mul(d, d, d); } - - + + /** * Multiply each component. - * + * * @param x x multiplier * @param y y multiplier * @return result @@ -733,11 +733,11 @@ public abstract class Vect implements VectBound, CachedDigestable { { return mul(x, y, Num.ONE); } - - + + /** * Multiply each component. - * + * * @param x x multiplier * @param y y multiplier * @param z z multiplier @@ -746,24 +746,24 @@ public abstract class Vect implements VectBound, CachedDigestable { public Vect mul(final Num x, final Num y, final Num z) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return t.x() * x.value(); } - - + + @Override public double y() { return t.y() * y.value(); } - - + + @Override public double z() { @@ -771,34 +771,34 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Round coordinates. - * + * * @return result */ public Vect round() { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return Math.round(t.x()); } - - + + @Override public double y() { return Math.round(t.y()); } - - + + @Override public double z() { @@ -806,34 +806,34 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Round coordinates down. - * + * * @return result */ public Vect floor() { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return Math.floor(t.x()); } - - + + @Override public double y() { return Math.floor(t.y()); } - - + + @Override public double z() { @@ -841,34 +841,34 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Round coordinates up. - * + * * @return result */ public Vect ceil() { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return Math.ceil(t.x()); } - - + + @Override public double y() { return Math.ceil(t.y()); } - - + + @Override public double z() { @@ -876,11 +876,11 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Subtract vector. - * + * * @param vec offset * @return result */ @@ -888,12 +888,12 @@ public abstract class Vect implements VectBound, CachedDigestable { { return sub(vec.xn(), vec.yn(), vec.zn()); } - - + + /** * Subtract a 2D vector.
* Z is unchanged. - * + * * @param x x offset * @param y y offset * @return result @@ -902,11 +902,11 @@ public abstract class Vect implements VectBound, CachedDigestable { { return add(-x, -y, 0); } - - + + /** * Subtract a 3D vector. - * + * * @param x x offset * @param y y offset * @param z z offset @@ -916,35 +916,35 @@ public abstract class Vect implements VectBound, CachedDigestable { { return add(-x, -y, -z); } - - + + public Vect sub(Num x, Num y) { return sub(x, y, Num.ZERO); } - - + + public Vect sub(final Num x, final Num y, final Num z) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return t.x() - x.value(); } - - + + @Override public double y() { return t.y() - y.value(); } - - + + @Override public double z() { @@ -952,11 +952,11 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Negate all coordinates (* -1) - * + * * @return result */ public Vect neg() @@ -964,118 +964,118 @@ public abstract class Vect implements VectBound, CachedDigestable { if (p_neg == null) p_neg = mul(-1); return p_neg; } - - + + /** * Scale vector to given size. - * + * * @param size size we need * @return result */ public Vect norm(final Num size) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { final double tSize = t.size().value(); final double nSize = size.value(); - + if (tSize == 0 || nSize == 0) return 0; - + return t.x() / (nSize / tSize); } - - + + @Override public double y() { final double tSize = t.size().value(); final double nSize = size.value(); - + if (tSize == 0 || nSize == 0) return 0; - + return t.y() / (nSize / tSize); } - - + + @Override public double z() { final double tSize = t.size().value(); final double nSize = size.value(); - + if (tSize == 0 || nSize == 0) return 0; - + return t.z() / (nSize / tSize); } }; } - - + + public Vect norm(final double size) { return norm(Num.make(size)); } - - + + /** * Get distance to other point - * + * * @param point other point * @return distance */ public Num dist(final Vect point) { return new Num() { - + final Vect t = Vect.this; - - + + @Override public double value() { final double dx = t.x() - point.x(); final double dy = t.y() - point.y(); final double dz = t.z() - point.z(); - + return Math.sqrt(dx * dx + dy * dy + dz * dz); } }; } - - + + /** * Get middle of line to other point - * + * * @param point other point * @return result */ public Vect midTo(final Vect point) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return (point.x() + t.x()) * 0.5; } - - + + @Override public double y() { return (point.y() + t.y()) * 0.5; } - - + + @Override public double z() { @@ -1083,35 +1083,35 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Create vector from this point to other point - * + * * @param point second point * @return result */ public Vect vectTo(final Vect point) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return (point.x() - t.x()); } - - + + @Override public double y() { return (point.y() - t.y()); } - - + + @Override public double z() { @@ -1119,35 +1119,35 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Get cross product (vector multiplication) - * + * * @param vec other vector * @return result */ public Vect cross(final Vect vec) { return new Vect() { - + final Vect t = Vect.this; - - + + @Override public double x() { return t.y() * vec.z() - t.z() * vec.y(); } - - + + @Override public double y() { return t.z() * vec.x() - t.x() * vec.z(); } - - + + @Override public double z() { @@ -1155,21 +1155,21 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Get dot product (scalar multiplication) - * + * * @param vec other vector * @return dot product */ public Num dot(final Vect vec) { return new Num() { - + final Vect t = Vect.this; - - + + @Override public double value() { @@ -1177,20 +1177,20 @@ public abstract class Vect implements VectBound, CachedDigestable { } }; } - - + + /** * Get vector size - * + * * @return size */ public Num size() { if (p_size == null) p_size = new Num() { - + final Vect t = Vect.this; - - + + @Override public double value() { @@ -1198,14 +1198,14 @@ public abstract class Vect implements VectBound, CachedDigestable { return Math.sqrt(x * x + y * y + z * z); } }; - + return p_size; } - - + + /** * Expand to a rect, with given growth to each side. - * + * * @param left * @param right * @param top @@ -1216,11 +1216,11 @@ public abstract class Vect implements VectBound, CachedDigestable { { return Rect.make(this, Vect.ZERO).grow(left, right, top, bottom); } - - + + /** * Expand to a rect, with given growth to each side. - * + * * @param left * @param right * @param top @@ -1231,8 +1231,8 @@ public abstract class Vect implements VectBound, CachedDigestable { { return Rect.make(this, Vect.ZERO).grow(left, right, top, bottom); } - - + + @Override public int hashCode() { @@ -1243,8 +1243,8 @@ public abstract class Vect implements VectBound, CachedDigestable { result = prime * result + Double.valueOf(z()).hashCode(); return result; } - - + + @Override public boolean equals(Object obj) { @@ -1252,17 +1252,17 @@ public abstract class Vect implements VectBound, CachedDigestable { if (obj == null) return false; if (!(obj instanceof Vect)) return false; final Vect other = (Vect) obj; - + return x() == other.x() && y() == other.y() && z() == other.z(); } - - + + public final boolean isInside(Rect bounds) { return bounds.contains(this); } - - + + public Rect startRect() { return expand(0, 0, 0, 0); diff --git a/src/mightypork/utils/math/constraints/vect/VectBound.java b/src/mightypork/utils/math/constraints/vect/VectBound.java index 5d7bd3c..f0f6601 100644 --- a/src/mightypork/utils/math/constraints/vect/VectBound.java +++ b/src/mightypork/utils/math/constraints/vect/VectBound.java @@ -4,11 +4,11 @@ package mightypork.utils.math.constraints.vect; /** * Interface for something that has/is a Vect. Vect itself implements it as * well. - * + * * @author Ondřej Hruška (MightyPork) */ public interface VectBound { - + /** * @return the Vect value */ diff --git a/src/mightypork/utils/math/constraints/vect/VectConst.java b/src/mightypork/utils/math/constraints/vect/VectConst.java index 56feb52..3b1e418 100644 --- a/src/mightypork/utils/math/constraints/vect/VectConst.java +++ b/src/mightypork/utils/math/constraints/vect/VectConst.java @@ -12,11 +12,11 @@ import mightypork.utils.math.constraints.vect.caching.VectDigest; * This coordinate is guaranteed to never change, as opposed to view.
* It's arranged so that operations with constant arguments yield constant * results. - * + * * @author Ondřej Hruška (MightyPork) */ public final class VectConst extends Vect { - + private final double x, y, z; // non-parametric operations are cached using lazy load. private NumConst v_size; @@ -30,344 +30,346 @@ public final class VectConst extends Vect { private NumConst v_yc; private NumConst v_zc; private VectDigest digest; - - - VectConst(Vect other) { + + + VectConst(Vect other) + { this(other.x(), other.y(), other.z()); } - - - VectConst(double x, double y, double z) { + + + VectConst(double x, double y, double z) + { this.x = x; this.y = y; this.z = z; } - - + + @Override public double x() { return x; } - - + + @Override public double y() { return y; } - - + + @Override public double z() { return z; } - - + + /** * @return X constraint */ - + @Override public final NumConst xn() { return (v_xc != null) ? v_xc : (v_xc = Num.make(this.x)); } - - + + /** * @return Y constraint */ - + @Override public final NumConst yn() { return (v_yc != null) ? v_yc : (v_yc = Num.make(this.y)); } - - + + /** * @return Z constraint */ - + @Override public final NumConst zn() { return (v_zc != null) ? v_zc : (v_zc = Num.make(this.z)); } - - + + /** * @deprecated it's useless to copy a constant */ - + @Override @Deprecated public VectConst freeze() { return this; // it's constant already } - - + + @Override public VectDigest digest() { return (digest != null) ? digest : (digest = super.digest()); } - - + + @Override public VectConst abs() { return (v_abs != null) ? v_abs : (v_abs = super.abs().freeze()); } - - + + @Override public VectConst add(double x, double y) { return super.add(x, y).freeze(); } - - + + @Override public VectConst add(double x, double y, double z) { return super.add(x, y, z).freeze(); } - - + + @Override public VectConst half() { return (v_half != null) ? v_half : (v_half = super.half().freeze()); } - - + + @Override public VectConst mul(double d) { return super.mul(d).freeze(); } - - + + @Override public VectConst mul(double x, double y) { return super.mul(x, y).freeze(); } - - + + @Override public VectConst mul(double x, double y, double z) { return super.mul(x, y, z).freeze(); } - - + + @Override public VectConst round() { return (v_round != null) ? v_round : (v_round = super.round().freeze()); } - - + + @Override public VectConst floor() { return (v_floor != null) ? v_floor : (v_floor = super.floor().freeze()); } - - + + @Override public VectConst ceil() { if (v_ceil != null) return v_ceil; return v_ceil = super.ceil().freeze(); } - - + + @Override public VectConst sub(double x, double y) { return super.sub(x, y).freeze(); } - - + + @Override public VectConst sub(double x, double y, double z) { return super.sub(x, y, z).freeze(); } - - + + @Override public VectConst neg() { return (v_neg != null) ? v_neg : (v_neg = super.neg().freeze()); } - - + + @Override public VectConst norm(double size) { return super.norm(size).freeze(); } - - + + @Override public NumConst size() { return (v_size != null) ? v_size : (v_size = super.size().freeze()); } - - + + @Override public VectConst withX(double x) { return super.withX(x).freeze(); } - - + + @Override public VectConst withY(double y) { return super.withY(y).freeze(); } - - + + @Override public VectConst withZ(double z) { return super.withZ(z).freeze(); } - - + + public VectConst withX(NumConst x) { return super.withX(x).freeze(); } - - + + public VectConst withY(NumConst y) { return super.withY(y).freeze(); } - - + + public VectConst withZ(NumConst z) { return super.withZ(z).freeze(); } - - + + public VectConst add(VectConst vec) { return super.add(vec).freeze(); } - - + + public VectConst add(NumConst x, NumConst y) { return super.add(x, y).freeze(); } - - + + public VectConst add(NumConst x, NumConst y, NumConst z) { return super.add(x, y, z).freeze(); } - - + + public VectConst mul(VectConst vec) { return super.mul(vec).freeze(); } - - + + public VectConst mul(NumConst d) { return super.mul(d).freeze(); } - - + + public VectConst mul(NumConst x, NumConst y) { return super.mul(x, y).freeze(); } - - + + public VectConst mul(NumConst x, NumConst y, NumConst z) { return super.mul(x, y, z).freeze(); } - - + + public VectConst sub(VectConst vec) { return super.sub(vec).freeze(); } - - + + public VectConst sub(NumConst x, NumConst y) { return super.sub(x, y).freeze(); } - - + + public VectConst sub(NumConst x, NumConst y, NumConst z) { return super.sub(x, y, z).freeze(); } - - + + public VectConst norm(NumConst size) { return super.norm(size).freeze(); } - - + + public NumConst dist(VectConst point) { return super.dist(point).freeze(); } - - + + public VectConst midTo(VectConst point) { return super.midTo(point).freeze(); } - - + + public VectConst vectTo(VectConst point) { return super.vectTo(point).freeze(); } - - + + public NumConst dot(VectConst vec) { return super.dot(vec).freeze(); } - - + + public VectConst cross(VectConst vec) { return super.cross(vec).freeze(); } - - + + @Override public RectConst expand(double left, double right, double top, double bottom) { return super.expand(left, right, top, bottom).freeze(); } - - + + public RectConst expand(NumConst left, NumConst right, NumConst top, NumConst bottom) { return super.expand(left, right, top, bottom).freeze(); } - + } diff --git a/src/mightypork/utils/math/constraints/vect/caching/AbstractVectCache.java b/src/mightypork/utils/math/constraints/vect/caching/AbstractVectCache.java index 2994c3e..a1258c2 100644 --- a/src/mightypork/utils/math/constraints/vect/caching/AbstractVectCache.java +++ b/src/mightypork/utils/math/constraints/vect/caching/AbstractVectCache.java @@ -15,60 +15,61 @@ import mightypork.utils.math.constraints.vect.var.VectVar; * Values are held in a caching VectVar, and digest caching is enabled by * default. *

- * + * * @author Ondřej Hruška (MightyPork) */ public abstract class AbstractVectCache extends VectAdapter implements CachedConstraint { - + private final VectVar cache = Vect.makeVar(); private boolean inited = false; private boolean cachingEnabled = true; - - - public AbstractVectCache() { + + + public AbstractVectCache() + { enableDigestCaching(true); // it changes only on poll } - - + + @Override protected final Vect getSource() { if (!inited) markDigestDirty(); - + return (cachingEnabled ? cache : getCacheSource()); } - - + + @Override public final void poll() { inited = true; - + // poll source final Vect source = getCacheSource(); source.markDigestDirty(); // poll cached - + // store source value cache.setTo(source); - + markDigestDirty(); - + onConstraintChanged(); } - - + + @Override public final void enableCaching(boolean yes) { cachingEnabled = yes; enableDigestCaching(yes); } - - + + @Override public final boolean isCachingEnabled() { return cachingEnabled; } - + } diff --git a/src/mightypork/utils/math/constraints/vect/caching/VectCache.java b/src/mightypork/utils/math/constraints/vect/caching/VectCache.java index 84e5db3..5fbad9b 100644 --- a/src/mightypork/utils/math/constraints/vect/caching/VectCache.java +++ b/src/mightypork/utils/math/constraints/vect/caching/VectCache.java @@ -6,27 +6,28 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Vect cache implementation - * + * * @author Ondřej Hruška (MightyPork) */ public class VectCache extends AbstractVectCache { - + private final Vect source; - - - public VectCache(Vect source) { + + + public VectCache(Vect source) + { this.source = source; enableDigestCaching(true); } - - + + @Override public Vect getCacheSource() { return source; } - - + + @Override public void onConstraintChanged() { diff --git a/src/mightypork/utils/math/constraints/vect/caching/VectDigest.java b/src/mightypork/utils/math/constraints/vect/caching/VectDigest.java index 48a5797..d858ef1 100644 --- a/src/mightypork/utils/math/constraints/vect/caching/VectDigest.java +++ b/src/mightypork/utils/math/constraints/vect/caching/VectDigest.java @@ -5,19 +5,20 @@ import mightypork.utils.math.constraints.vect.Vect; public class VectDigest { - + public final double x; public final double y; public final double z; - - - public VectDigest(Vect vect) { + + + public VectDigest(Vect vect) + { this.x = vect.x(); this.y = vect.y(); this.z = vect.z(); } - - + + @Override public String toString() { diff --git a/src/mightypork/utils/math/constraints/vect/proxy/VectAdapter.java b/src/mightypork/utils/math/constraints/vect/proxy/VectAdapter.java index e5ade38..d51efa2 100644 --- a/src/mightypork/utils/math/constraints/vect/proxy/VectAdapter.java +++ b/src/mightypork/utils/math/constraints/vect/proxy/VectAdapter.java @@ -7,35 +7,35 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Vect proxy with abstract method for plugging in / generating coordinates * dynamically. - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class VectAdapter extends Vect { - + /** * @return the proxied coord */ protected abstract Vect getSource(); - - + + @Override public double x() { return getSource().x(); } - - + + @Override public double y() { return getSource().y(); } - - + + @Override public double z() { return getSource().z(); } - + } diff --git a/src/mightypork/utils/math/constraints/vect/proxy/VectNumAdapter.java b/src/mightypork/utils/math/constraints/vect/proxy/VectNumAdapter.java index 40b348c..1b6bb2e 100644 --- a/src/mightypork/utils/math/constraints/vect/proxy/VectNumAdapter.java +++ b/src/mightypork/utils/math/constraints/vect/proxy/VectNumAdapter.java @@ -8,48 +8,50 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Coord view composed of given {@link NumBound}s, using their current values. - * + * * @author Ondřej Hruška (MightyPork) */ public class VectNumAdapter extends Vect { - + private final Num constrX; private final Num constrY; private final Num constrZ; - - - public VectNumAdapter(Num x, Num y, Num z) { + + + public VectNumAdapter(Num x, Num y, Num z) + { this.constrX = x; this.constrY = y; this.constrZ = z; } - - - public VectNumAdapter(Num x, Num y) { + + + public VectNumAdapter(Num x, Num y) + { this.constrX = x; this.constrY = y; this.constrZ = Num.ZERO; } - - + + @Override public double x() { return constrX.value(); } - - + + @Override public double y() { return constrY.value(); } - - + + @Override public double z() { return constrZ.value(); } - + } diff --git a/src/mightypork/utils/math/constraints/vect/proxy/VectProxy.java b/src/mightypork/utils/math/constraints/vect/proxy/VectProxy.java index 862fb81..35acc0f 100644 --- a/src/mightypork/utils/math/constraints/vect/proxy/VectProxy.java +++ b/src/mightypork/utils/math/constraints/vect/proxy/VectProxy.java @@ -8,34 +8,36 @@ import mightypork.utils.math.constraints.vect.VectBound; /** * Pluggable vect proxy - * + * * @author Ondřej Hruška (MightyPork) */ public class VectProxy extends VectAdapter implements PluggableVectBound { - + private VectBound backing = null; - - - public VectProxy() { + + + public VectProxy() + { } - - - public VectProxy(VectBound proxied) { + + + public VectProxy(VectBound proxied) + { backing = proxied; } - - + + @Override public void setVect(VectBound proxied) { this.backing = proxied; } - - + + @Override protected Vect getSource() { return backing.getVect(); } - + } diff --git a/src/mightypork/utils/math/constraints/vect/var/VectMutable.java b/src/mightypork/utils/math/constraints/vect/var/VectMutable.java index dd00e06..e90bbc5 100644 --- a/src/mightypork/utils/math/constraints/vect/var/VectMutable.java +++ b/src/mightypork/utils/math/constraints/vect/var/VectMutable.java @@ -6,11 +6,11 @@ import mightypork.utils.math.constraints.vect.Vect; /** * Mutable coord - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class VectMutable extends Vect { - + /** * Set all to zeros. */ @@ -18,23 +18,23 @@ public abstract class VectMutable extends Vect { { setTo(0, 0, 0); } - - + + /** * Set coordinates to match other coord. - * + * * @param copied coord whose coordinates are used */ public void setTo(Vect copied) { setTo(copied.x(), copied.y(), copied.z()); } - - + + /** * Set 2D coordinates.
* Z is unchanged. - * + * * @param x x coordinate * @param y y coordinate */ @@ -43,37 +43,37 @@ public abstract class VectMutable extends Vect { setX(x); setY(y); } - - + + /** * Set coordinates. - * + * * @param x x coordinate * @param y y coordinate * @param z z coordinate */ public abstract void setTo(double x, double y, double z); - - + + /** * Set X coordinate. - * + * * @param x x coordinate */ public abstract void setX(double x); - - + + /** * Set Y coordinate. - * + * * @param y y coordinate */ public abstract void setY(double y); - - + + /** * Set Z coordinate. - * + * * @param z z coordinate */ public abstract void setZ(double z); diff --git a/src/mightypork/utils/math/constraints/vect/var/VectVar.java b/src/mightypork/utils/math/constraints/vect/var/VectVar.java index 2e64189..d0ff355 100644 --- a/src/mightypork/utils/math/constraints/vect/var/VectVar.java +++ b/src/mightypork/utils/math/constraints/vect/var/VectVar.java @@ -4,48 +4,49 @@ package mightypork.utils.math.constraints.vect.var; /** * Mutable coordinate.
* All Vec methods (except copy) alter data values and return this instance. - * + * * @author Ondřej Hruška (MightyPork) */ public class VectVar extends VectMutable { - + private double x, y, z; - - + + /** * @param x X coordinate * @param y Y coordinate * @param z Z coordinate */ - public VectVar(double x, double y, double z) { + public VectVar(double x, double y, double z) + { super(); this.x = x; this.y = y; this.z = z; } - - + + @Override public double x() { return x; } - - + + @Override public double y() { return y; } - - + + @Override public double z() { return z; } - - + + @Override public void setTo(double x, double y, double z) { @@ -53,22 +54,22 @@ public class VectVar extends VectMutable { this.y = y; this.z = z; } - - + + @Override public void setX(double x) { this.x = x; } - - + + @Override public void setY(double y) { this.y = y; } - - + + @Override public void setZ(double z) { diff --git a/src/mightypork/utils/math/noise/NoiseGen.java b/src/mightypork/utils/math/noise/NoiseGen.java index 37c49b9..2b0fbd3 100644 --- a/src/mightypork/utils/math/noise/NoiseGen.java +++ b/src/mightypork/utils/math/noise/NoiseGen.java @@ -3,66 +3,68 @@ package mightypork.utils.math.noise; /** * 2D Perlin noise generator - * + * * @author Ondřej Hruška (MightyPork) */ public class NoiseGen { - + private static final double lowBound = -0.7072; private static final double highBound = 0.7072; - + private final PerlinNoiseGenerator noiser; - + private final double lowMul; private final double highMul; private final double middle; private final double density; - - + + /** * make a new noise generator with a random seed - * + * * @param density noise density (0..1). Lower density means larger "spots". * @param low low bound ("valley") * @param middle middle bound ("surface") * @param high high bound ("hill") */ - public NoiseGen(double density, double low, double middle, double high) { + public NoiseGen(double density, double low, double middle, double high) + { this(density, low, middle, high, Double.doubleToLongBits(Math.random())); } - - + + /** * make a new noise generator - * + * * @param density noise density (0..1). Lower density means larger "spots". * @param low low bound ("valley") * @param middle middle bound ("surface") * @param high high bound ("hill") * @param seed random seed to use */ - public NoiseGen(double density, double low, double middle, double high, long seed) { + public NoiseGen(double density, double low, double middle, double high, long seed) + { if (low > middle || middle > high) throw new IllegalArgumentException("Invalid value range."); - + this.density = density; - + // norm low and high to be around zero low -= middle; high -= middle; - - // scale + + // scale this.middle = middle; - + lowMul = Math.abs(low / lowBound); highMul = Math.abs(high / highBound); - + noiser = new PerlinNoiseGenerator(seed); } - - + + /** * Get value at coord - * + * * @param x x coordinate * @param y y coordinate * @return value @@ -70,24 +72,24 @@ public class NoiseGen { public double valueAt(double x, double y) { double raw = noiser.noise2(x * density, y * density); - + if (raw < lowBound) { raw = lowBound; } else if (raw > highBound) { raw = highBound; } - + if (raw < 0) { return middle + lowMul * raw; } else { return middle + highMul * raw; } } - - + + /** * Build a map [height][width] of noise values - * + * * @param width map width (number of columns) * @param height map height (number of rows ) * @return the map @@ -95,13 +97,13 @@ public class NoiseGen { public double[][] buildMap(int width, int height) { final double[][] map = new double[height][width]; - + for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { map[y][x] = valueAt(x, y); } } - + return map; } } diff --git a/src/mightypork/utils/math/noise/PerlinNoiseGenerator.java b/src/mightypork/utils/math/noise/PerlinNoiseGenerator.java index 19afdc3..96f6114 100644 --- a/src/mightypork/utils/math/noise/PerlinNoiseGenerator.java +++ b/src/mightypork/utils/math/noise/PerlinNoiseGenerator.java @@ -25,61 +25,63 @@ import java.util.Random; *

* Computing noise for one and two dimensions can make use of the 3D problem * space by just setting the un-needed dimensions to a fixed value. - * + * * @author Justin Couch * @edited by Ondřej Hruška * @version $Revision: 1.4 $ * @source http://code.j3d.org/download.html */ public class PerlinNoiseGenerator { - + // Constants for setting up the Perlin-1 noise functions private static final int B = 0x1000; private static final int BM = 0xff; - + private static final int N = 0x1000; - + /** Default seed to use for the random number generation */ private static final int DEFAULT_SEED = 100; - + /** Default sample size to work with */ private static final int DEFAULT_SAMPLE_SIZE = 256; - + private final Random rand = new Random(DEFAULT_SEED); - + /** Permutation array for the improved noise function */ private final int[] p_imp; - + /** P array for perline 1 noise */ private int[] p; private double[][] g3; private double[][] g2; private double[] g1; - - + + /** * Create a new noise creator with the default seed value */ - public PerlinNoiseGenerator() { + public PerlinNoiseGenerator() + { this(DEFAULT_SEED); } - - + + /** * Create a new noise creator with the given seed value for the randomness - * + * * @param seed The seed value to use */ - public PerlinNoiseGenerator(long seed) { + public PerlinNoiseGenerator(long seed) + { p_imp = new int[DEFAULT_SAMPLE_SIZE << 1]; - + int i, j, k; rand.setSeed(seed); - + // Calculate the table of psuedo-random coefficients. for (i = 0; i < DEFAULT_SAMPLE_SIZE; i++) p_imp[i] = i; - + // generate the psuedo-random permutation table. while (--i > 0) { k = p_imp[i]; @@ -87,14 +89,14 @@ public class PerlinNoiseGenerator { p_imp[i] = p_imp[j]; p_imp[j] = k; } - + initPerlin1(); } - - + + /** * Computes noise function for three dimensions at the point (x,y,z). - * + * * @param x x dimension parameter * @param y y dimension parameter * @param z z dimension parameter @@ -106,27 +108,27 @@ public class PerlinNoiseGenerator { final int uc_x = (int) Math.floor(x) & 255; final int uc_y = (int) Math.floor(y) & 255; final int uc_z = (int) Math.floor(z) & 255; - + // Relative location of the point in the unit cube final double xo = x - Math.floor(x); final double yo = y - Math.floor(y); final double zo = z - Math.floor(z); - + // Fade curves for x, y and z final double u = fade(xo); final double v = fade(yo); final double w = fade(zo); - + // Generate a hash for each coordinate to find out where in the cube // it lies. final int a = p_imp[uc_x] + uc_y; final int aa = p_imp[a] + uc_z; final int ab = p_imp[a + 1] + uc_z; - + final int b = p_imp[uc_x + 1] + uc_y; final int ba = p_imp[b] + uc_z; final int bb = p_imp[b + 1] + uc_z; - + // blend results from the 8 corners based on the noise function final double c1 = grad(p_imp[aa], xo, yo, zo); final double c2 = grad(p_imp[ba], xo - 1, yo, zo); @@ -136,14 +138,14 @@ public class PerlinNoiseGenerator { final double c6 = grad(p_imp[ba + 1], xo - 1, yo, zo - 1); final double c7 = grad(p_imp[ab + 1], xo, yo - 1, zo - 1); final double c8 = grad(p_imp[bb + 1], xo - 1, yo - 1, zo - 1); - + return lerp(w, lerp(v, lerp(u, c1, c2), lerp(u, c3, c4)), lerp(v, lerp(u, c5, c6), lerp(u, c7, c8))); } - - + + /** * 1-D noise generation function using the original perlin algorithm. - * + * * @param x Seed for the noise function * @return The noisy output */ @@ -154,19 +156,19 @@ public class PerlinNoiseGenerator { final int bx1 = (bx0 + 1) & BM; final double rx0 = t - (int) t; final double rx1 = rx0 - 1; - + final double sx = sCurve(rx0); - + final double u = rx0 * g1[p[bx0]]; final double v = rx1 * g1[p[bx1]]; - + return lerp(sx, u, v); } - - + + /** * Create noise in a 2D space using the orignal perlin noise algorithm. - * + * * @param x The X coordinate of the location to sample * @param y The Y coordinate of the location to sample * @return A noisy value at the given position @@ -178,43 +180,43 @@ public class PerlinNoiseGenerator { final int bx1 = (bx0 + 1) & BM; final double rx0 = t - (int) t; final double rx1 = rx0 - 1; - + t = y + N; final int by0 = ((int) t) & BM; final int by1 = (by0 + 1) & BM; final double ry0 = t - (int) t; final double ry1 = ry0 - 1; - + final int i = p[bx0]; final int j = p[bx1]; - + final int b00 = p[i + by0]; final int b10 = p[j + by0]; final int b01 = p[i + by1]; final int b11 = p[j + by1]; - + final double sx = sCurve(rx0); final double sy = sCurve(ry0); - + double[] q = g2[b00]; double u = rx0 * q[0] + ry0 * q[1]; q = g2[b10]; double v = rx1 * q[0] + ry0 * q[1]; final double a = lerp(sx, u, v); - + q = g2[b01]; u = rx0 * q[0] + ry1 * q[1]; q = g2[b11]; v = rx1 * q[0] + ry1 * q[1]; final double b = lerp(sx, u, v); - + return lerp(sy, a, b); } - - + + /** * Create noise in a 3D space using the orignal perlin noise algorithm. - * + * * @param x The X coordinate of the location to sample * @param y The Y coordinate of the location to sample * @param z The Z coordinate of the location to sample @@ -227,73 +229,73 @@ public class PerlinNoiseGenerator { final int bx1 = (bx0 + 1) & BM; final double rx0 = t - (int) t; final double rx1 = rx0 - 1; - + t = y + N; final int by0 = ((int) t) & BM; final int by1 = (by0 + 1) & BM; final double ry0 = t - (int) t; final double ry1 = ry0 - 1; - + t = z + N; final int bz0 = ((int) t) & BM; final int bz1 = (bz0 + 1) & BM; final double rz0 = t - (int) t; final double rz1 = rz0 - 1; - + final int i = p[bx0]; final int j = p[bx1]; - + final int b00 = p[i + by0]; final int b10 = p[j + by0]; final int b01 = p[i + by1]; final int b11 = p[j + by1]; - + t = sCurve(rx0); final double sy = sCurve(ry0); final double sz = sCurve(rz0); - + double[] q = g3[b00 + bz0]; double u = (rx0 * q[0] + ry0 * q[1] + rz0 * q[2]); q = g3[b10 + bz0]; double v = (rx1 * q[0] + ry0 * q[1] + rz0 * q[2]); double a = lerp(t, u, v); - + q = g3[b01 + bz0]; u = (rx0 * q[0] + ry1 * q[1] + rz0 * q[2]); q = g3[b11 + bz0]; v = (rx1 * q[0] + ry1 * q[1] + rz0 * q[2]); double b = lerp(t, u, v); - + final double c = lerp(sy, a, b); - + q = g3[b00 + bz1]; u = (rx0 * q[0] + ry0 * q[1] + rz1 * q[2]); q = g3[b10 + bz1]; v = (rx1 * q[0] + ry0 * q[1] + rz1 * q[2]); a = lerp(t, u, v); - + q = g3[b01 + bz1]; u = (rx0 * q[0] + ry1 * q[1] + rz1 * q[2]); q = g3[b11 + bz1]; v = (rx1 * q[0] + ry1 * q[1] + rz1 * q[2]); b = lerp(t, u, v); - + final double d = lerp(sy, a, b); - + return lerp(sz, c, d); } - - + + /** * Create a turbulent noise output based on the core noise function. This * uses the noise as a base function and is suitable for creating clouds, * marble and explosion effects. For example, a typical marble effect would * set the colour to be: - * + * *

-     *    sin(point + turbulence(point) * point.x);
-     * 
- * + * sin(point + turbulence(point) * point.x); + * + * * @param x * @param y * @param z @@ -308,23 +310,23 @@ public class PerlinNoiseGenerator { double p_z = z; double t = 0; double f; - + for (f = loF; f < hiF; f *= 2) { t += Math.abs(improvedNoise(p_x, p_y, p_z)) / f; - + p_x *= 2; p_y *= 2; p_z *= 2; } - + return t - 0.3; } - - + + /** * Create a turbulance function in 2D using the original perlin noise * function. - * + * * @param x The X coordinate of the location to sample * @param y The Y coordinate of the location to sample * @param freq The frequency of the turbluance to create @@ -333,20 +335,20 @@ public class PerlinNoiseGenerator { public double turbulence2(double x, double y, double freq) { double t = 0; - + do { t += noise2(freq * x, freq * y) / freq; freq *= 0.5f; } while (freq >= 1); - + return t; } - - + + /** * Create a turbulance function in 3D using the original perlin noise * function. - * + * * @param x The X coordinate of the location to sample * @param y The Y coordinate of the location to sample * @param z The Z coordinate of the location to sample @@ -356,19 +358,19 @@ public class PerlinNoiseGenerator { public double turbulence3(double x, double y, double z, double freq) { double t = 0; - + do { t += noise3(freq * x, freq * y, freq * z) / freq; freq *= 0.5f; } while (freq >= 1); - + return t; } - - + + /** * Create a 1D tileable noise function for the given width. - * + * * @param x The X coordinate to generate the noise for * @param w The width of the tiled block * @return The value of the noise at the given coordinate @@ -377,11 +379,11 @@ public class PerlinNoiseGenerator { { return (noise1(x) * (w - x) + noise1(x - w) * x) / w; } - - + + /** * Create a 2D tileable noise function for the given width and height. - * + * * @param x The X coordinate to generate the noise for * @param y The Y coordinate to generate the noise for * @param w The width of the tiled block @@ -392,12 +394,12 @@ public class PerlinNoiseGenerator { { return (noise2(x, y) * (w - x) * (h - y) + noise2(x - w, y) * x * (h - y) + noise2(x, y - h) * (w - x) * y + noise2(x - w, y - h) * x * y) / (w * h); } - - + + /** * Create a 3D tileable noise function for the given width, height and * depth. - * + * * @param x The X coordinate to generate the noise for * @param y The Y coordinate to generate the noise for * @param z The Z coordinate to generate the noise for @@ -408,13 +410,16 @@ public class PerlinNoiseGenerator { */ public double tileableNoise3(double x, double y, double z, double w, double h, double d) { - return (noise3(x, y, z) * (w - x) * (h - y) * (d - z) + noise3(x - w, y, z) * x * (h - y) * (d - z) + noise3(x, y - h, z) * (w - x) * y * (d - z) + noise3(x - w, y - h, z) * x * y * (d - z) + noise3(x, y, z - d) * (w - x) * (h - y) * z + noise3(x - w, y, z - d) * x * (h - y) * z + noise3(x, y - h, z - d) * (w - x) * y * z + noise3(x - w, y - h, z - d) * x * y * z) / (w * h * d); + return (noise3(x, y, z) * (w - x) * (h - y) * (d - z) + noise3(x - w, y, z) * x * (h - y) * (d - z) + noise3(x, y - h, z) * (w - x) * y * (d - z) + + noise3(x - w, y - h, z) * x * y * (d - z) + noise3(x, y, z - d) * (w - x) * (h - y) * z + noise3(x - w, y, z - d) * x * (h - y) * z + + noise3(x, y - h, z - d) * (w - x) * y * z + noise3(x - w, y - h, z - d) * x * y * z) + / (w * h * d); } - - + + /** * Create a turbulance function that can be tiled across a surface in 2D. - * + * * @param x The X coordinate of the location to sample * @param y The Y coordinate of the location to sample * @param w The width to tile over @@ -425,19 +430,19 @@ public class PerlinNoiseGenerator { public double tileableTurbulence2(double x, double y, double w, double h, double freq) { double t = 0; - + do { t += tileableNoise2(freq * x, freq * y, w * freq, h * freq) / freq; freq *= 0.5f; } while (freq >= 1); - + return t; } - - + + /** * Create a turbulance function that can be tiled across a surface in 3D. - * + * * @param x The X coordinate of the location to sample * @param y The Y coordinate of the location to sample * @param z The Z coordinate of the location to sample @@ -450,16 +455,16 @@ public class PerlinNoiseGenerator { public double tileableTurbulence3(double x, double y, double z, double w, double h, double d, double freq) { double t = 0; - + do { t += tileableNoise3(freq * x, freq * y, freq * z, w * freq, h * freq, d * freq) / freq; freq *= 0.5f; } while (freq >= 1); - + return t; } - - + + /** * Simple lerp function using doubles. */ @@ -467,12 +472,12 @@ public class PerlinNoiseGenerator { { return a + t * (b - a); } - - + + /** * Fade curve calculation which is 6t^5 - 15t^4 + 10t^3. This is the new * algorithm, where the old one used to be 3t^2 - 2t^3. - * + * * @param t The t parameter to calculate the fade for * @return the drop-off amount. */ @@ -480,8 +485,8 @@ public class PerlinNoiseGenerator { { return t * t * t * (t * (t * 6 - 15) + 10); } - - + + /** * Calculate the gradient function based on the hash code. */ @@ -491,11 +496,11 @@ public class PerlinNoiseGenerator { final int h = hash & 15; final double u = (h < 8 || h == 12 || h == 13) ? x : y; final double v = (h < 4 || h == 12 || h == 13) ? y : z; - + return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v); } - - + + /** * S-curve function for value distribution for Perlin-1 noise function. */ @@ -503,8 +508,8 @@ public class PerlinNoiseGenerator { { return (t * t * (3 - 2 * t)); } - - + + /** * 2D-vector normalisation function. */ @@ -514,8 +519,8 @@ public class PerlinNoiseGenerator { v[0] *= s; v[1] *= s; } - - + + /** * 3D-vector normalisation function. */ @@ -526,8 +531,8 @@ public class PerlinNoiseGenerator { v[1] *= s; v[2] *= s; } - - + + /** * Initialise the lookup arrays used by Perlin 1 function. */ @@ -538,28 +543,28 @@ public class PerlinNoiseGenerator { g2 = new double[B + B + 2][2]; g1 = new double[B + B + 2]; int i, j, k; - + for (i = 0; i < B; i++) { p[i] = i; - + g1[i] = (((rand.nextDouble() * Integer.MAX_VALUE) % (B + B)) - B) / B; - + for (j = 0; j < 2; j++) g2[i][j] = (((rand.nextDouble() * Integer.MAX_VALUE) % (B + B)) - B) / B; normalize2(g2[i]); - + for (j = 0; j < 3; j++) g3[i][j] = (((rand.nextDouble() * Integer.MAX_VALUE) % (B + B)) - B) / B; normalize3(g3[i]); } - + while (--i > 0) { k = p[i]; j = (int) ((rand.nextDouble() * Integer.MAX_VALUE) % B); p[i] = p[j]; p[j] = k; } - + for (i = 0; i < B + 2; i++) { p[B + i] = p[i]; g1[B + i] = g1[i]; diff --git a/src/mightypork/utils/math/timing/FpsMeter.java b/src/mightypork/utils/math/timing/FpsMeter.java index 1c22e49..aaeb15d 100644 --- a/src/mightypork/utils/math/timing/FpsMeter.java +++ b/src/mightypork/utils/math/timing/FpsMeter.java @@ -4,16 +4,16 @@ package mightypork.utils.math.timing; /** * Class for counting FPS in games.
* This class can be used also as a simple frequency meter - output is in Hz. - * + * * @author Ondřej Hruška (MightyPork) */ public class FpsMeter { - + private long frames = 0; private long lastTimeMillis = System.currentTimeMillis(); private long lastSecFPS = 0; - - + + /** * @return current second's FPS */ @@ -21,8 +21,8 @@ public class FpsMeter { { return lastSecFPS; } - - + + /** * Notification that frame was rendered */ diff --git a/src/mightypork/utils/math/timing/Profiler.java b/src/mightypork/utils/math/timing/Profiler.java index 79700c8..b4a5f93 100644 --- a/src/mightypork/utils/math/timing/Profiler.java +++ b/src/mightypork/utils/math/timing/Profiler.java @@ -4,29 +4,60 @@ package mightypork.utils.math.timing; import mightypork.utils.Support; +/** + * Time metering utils for profiling.
+ * The profiler work with long (starting ms time), so it has very little + * overhead and you can easily have multiple "profilers" running at the same + * time. + * + * @author Ondřej Hruška (MightyPork) + */ public class Profiler { - + + /** + * Get current time, to be later used in the end*() methods + * + * @return current time (ms) + */ public static long begin() { return System.currentTimeMillis(); } - - + + + /** + * Get seconds since begin. + * + * @param begun profiling start time (ms), obtained using begin() + * @return seconds elapsed + */ public static double end(long begun) { - return endLong(begun) / 1000D; + return endMs(begun) / 1000D; } - - - public static long endLong(long begun) + + + /** + * Get milliseconds since begin. + * + * @param begun profiling start time (ms), obtained using begin() + * @return milliseconds elapsed + */ + public static long endMs(long begun) { return System.currentTimeMillis() - begun; } - - + + + /** + * Elapsed time in human readable format, in seconds. + * + * @param begun profiling start time (ms), obtained using begin() + * @return something like "0.121 s" + */ public static String endStr(long begun) { return Support.str(end(begun)) + " s"; } - + } diff --git a/src/mightypork/utils/math/timing/TaskRepeater.java b/src/mightypork/utils/math/timing/TaskRepeater.java index f221101..10960c8 100644 --- a/src/mightypork/utils/math/timing/TaskRepeater.java +++ b/src/mightypork/utils/math/timing/TaskRepeater.java @@ -7,38 +7,39 @@ import mightypork.utils.math.animation.NumAnimated; public abstract class TaskRepeater extends AnimatorRewind implements Runnable, Enableable { - + private boolean enabled = true; - - - public TaskRepeater(double period) { + + + public TaskRepeater(double period) + { super(period); } - - + + @Override protected void nextCycle(NumAnimated anim) { if (isEnabled()) run(); super.nextCycle(anim); } - - + + @Override public void setEnabled(boolean yes) { this.enabled = yes; } - - + + @Override public boolean isEnabled() { return enabled; } - - + + @Override public abstract void run(); - + } diff --git a/src/mightypork/utils/math/timing/TimedTask.java b/src/mightypork/utils/math/timing/TimedTask.java index 7bebf05..11407fc 100644 --- a/src/mightypork/utils/math/timing/TimedTask.java +++ b/src/mightypork/utils/math/timing/TimedTask.java @@ -7,15 +7,15 @@ import mightypork.utils.math.animation.NumAnimated; /** * Delayed runnable controlled by delta timing. - * + * * @author Ondřej Hruška (MightyPork) */ public abstract class TimedTask implements Runnable, Updateable { - + private final NumAnimated timer = new NumAnimated(0); private boolean running = false; - - + + @Override public void update(double delta) { @@ -27,26 +27,26 @@ public abstract class TimedTask implements Runnable, Updateable { } } } - - + + public boolean isRunning() { return !timer.isFinished(); } - - + + public void start(double seconds) { timer.reset(); timer.animate(1, seconds); running = true; } - - + + public void stop() { running = false; timer.reset(); } - + } diff --git a/src/mightypork/utils/math/timing/TimerDelta.java b/src/mightypork/utils/math/timing/TimerDelta.java index 8833e0c..851d8c7 100644 --- a/src/mightypork/utils/math/timing/TimerDelta.java +++ b/src/mightypork/utils/math/timing/TimerDelta.java @@ -3,38 +3,39 @@ package mightypork.utils.math.timing; /** * Timer for delta timing - * + * * @author Ondřej Hruška (MightyPork) */ public class TimerDelta { - + private long lastFrame; - + private static final long SECOND = 1000000000; // a million nanoseconds - - + + /** * New delta timer */ - public TimerDelta() { + public TimerDelta() + { lastFrame = System.nanoTime(); } - - + + /** * Get current time in NS - * + * * @return current time NS */ public long getTime() { return System.nanoTime(); } - - + + /** * Get time since the last "getDelta()" call. - * + * * @return delta time (seconds) */ public double getDelta() diff --git a/src/mightypork/utils/math/timing/TimerFps.java b/src/mightypork/utils/math/timing/TimerFps.java index 786a443..a44fb30 100644 --- a/src/mightypork/utils/math/timing/TimerFps.java +++ b/src/mightypork/utils/math/timing/TimerFps.java @@ -3,33 +3,34 @@ package mightypork.utils.math.timing; /** * Timer for interpolated timing - * + * * @author Ondřej Hruška (MightyPork) */ public class TimerFps { - + private long lastFrame = 0; private long nextFrame = 0; private long skipped = 0; private long lastSkipped = 0; - + private static final long SECOND = 1000000000; // a million nanoseconds private final long FRAME; // a time of one frame in nanoseconds - - + + /** * New interpolated timer - * + * * @param fps target FPS */ - public TimerFps(long fps) { + public TimerFps(long fps) + { FRAME = Math.round(SECOND / (double) fps); - + lastFrame = System.nanoTime(); nextFrame = System.nanoTime() + FRAME; } - - + + /** * Sync and calculate dropped frames etc. */ @@ -43,22 +44,22 @@ public class TimerFps { nextFrame += skippedNow * FRAME; } } - - + + /** * Get nanotime - * + * * @return nanotime */ public long getTime() { return System.nanoTime(); } - - + + /** * Get fraction of next frame - * + * * @return fraction */ public double getFraction() @@ -66,20 +67,20 @@ public class TimerFps { if (getSkipped() >= 1) { return 1; } - + final long time = getTime(); - + if (time <= nextFrame) { return (double) (time - lastFrame) / (double) FRAME; } - + return 1; } - - + + /** * Get number of elapsed ticks - * + * * @return ticks */ public int getSkipped() @@ -88,8 +89,8 @@ public class TimerFps { lastSkipped = skipped; return (int) change; } - - + + /** * Clear timer and start counting new tick. */ diff --git a/src/mightypork/utils/string/AlphanumComparator.java b/src/mightypork/utils/string/AlphanumComparator.java index db8ab08..dee9f0b 100644 --- a/src/mightypork/utils/string/AlphanumComparator.java +++ b/src/mightypork/utils/string/AlphanumComparator.java @@ -30,23 +30,23 @@ import java.util.Comparator; /** * String comparator taking care of strings with numbers. - * + * * @author Daniel Migowski * @author Andre Bogus * @author David Koelle * @author Ondřej Hruška (MightyPork) */ public class AlphanumComparator implements Comparator { - + public static final AlphanumComparator instance = new AlphanumComparator(); - - + + private final boolean isDigit(char ch) { return ch >= '0' && ch <= '9'; } - - + + /** * Length of string is passed in for improved efficiency (only need to * calculate it once) @@ -57,7 +57,7 @@ public class AlphanumComparator implements Comparator { char c = s.charAt(marker); chunk.append(c); marker++; - + if (isDigit(c)) { while (marker < slength) { c = s.charAt(marker); @@ -75,8 +75,8 @@ public class AlphanumComparator implements Comparator { } return chunk.toString(); } - - + + @Override public int compare(String s1, String s2) { @@ -84,14 +84,14 @@ public class AlphanumComparator implements Comparator { int thatMarker = 0; final int s1Length = s1.length(); final int s2Length = s2.length(); - + while (thisMarker < s1Length && thatMarker < s2Length) { final String thisChunk = getChunk(s1, s1Length, thisMarker); thisMarker += thisChunk.length(); - + final String thatChunk = getChunk(s2, s2Length, thatMarker); thatMarker += thatChunk.length(); - + // If both chunks contain numeric characters, sort them numerically int result = 0; if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) { @@ -110,10 +110,10 @@ public class AlphanumComparator implements Comparator { } else { result = thisChunk.compareTo(thatChunk); } - + if (result != 0) return result; } - + return s1Length - s2Length; } } diff --git a/src/mightypork/utils/string/StringProvider.java b/src/mightypork/utils/string/StringProvider.java index 5376c91..41fcf63 100644 --- a/src/mightypork/utils/string/StringProvider.java +++ b/src/mightypork/utils/string/StringProvider.java @@ -3,10 +3,10 @@ package mightypork.utils.string; /** * Can be used for dynamic string generating - * + * * @author Ondřej Hruška (MightyPork) */ public interface StringProvider { - + String getString(); } diff --git a/src/mightypork/utils/string/StringUtil.java b/src/mightypork/utils/string/StringUtil.java index 1c2e472..659d74f 100644 --- a/src/mightypork/utils/string/StringUtil.java +++ b/src/mightypork/utils/string/StringUtil.java @@ -3,41 +3,41 @@ package mightypork.utils.string; /** * General purpose string utilities - * + * * @author Ondřej Hruška (MightyPork) */ public class StringUtil { - + public static String fromLastDot(String s) { return fromLastChar(s, '.'); } - - + + public static String toLastDot(String s) { return toLastChar(s, '.'); } - - + + public static String fromLastChar(String s, char c) { if (s == null) return null; return s.substring(s.lastIndexOf(c) + 1, s.length()); } - - + + public static String toLastChar(String s, char c) { if (s == null) return null; if (s.lastIndexOf(c) == -1) return s; return s.substring(0, s.lastIndexOf(c)); } - - + + /** * Repeat a string - * + * * @param repeated string * @param count * @return output @@ -49,20 +49,20 @@ public class StringUtil { s += repeated; return s; } - - + + public static boolean isValidFilenameChar(char ch) { return isValidFilenameString(Character.toString(ch)); } - - + + public static boolean isValidFilenameString(String filename) { return filename.matches("[a-zA-Z0-9 +\\-.,_%@#!]+"); } - - + + public static String ellipsisStart(String orig, int length) { if (orig.length() > length) { @@ -70,8 +70,8 @@ public class StringUtil { } return orig; } - - + + public static String ellipsisEnd(String orig, int length) { if (orig.length() > length) { diff --git a/src/mightypork/utils/string/StringWrapper.java b/src/mightypork/utils/string/StringWrapper.java index 551583c..586f399 100644 --- a/src/mightypork/utils/string/StringWrapper.java +++ b/src/mightypork/utils/string/StringWrapper.java @@ -2,16 +2,33 @@ package mightypork.utils.string; /** - * String provider with constant string - * + * String provider that holds a string. + * * @author Ondřej Hruška (MightyPork) */ public class StringWrapper implements StringProvider { - private final String value; + private String value; - public StringWrapper(String value) { + /** + * Create a string wrapper + * + * @param value original value + */ + public StringWrapper(String value) + { + this.value = value; + } + + + /** + * Set the string + * + * @param value string to set + */ + public void setString(String value) + { this.value = value; } diff --git a/src/mightypork/utils/string/validation/CharFilter.java b/src/mightypork/utils/string/validation/CharFilter.java index 33ecd31..7354360 100644 --- a/src/mightypork/utils/string/validation/CharFilter.java +++ b/src/mightypork/utils/string/validation/CharFilter.java @@ -2,6 +2,6 @@ package mightypork.utils.string.validation; public interface CharFilter { - + public boolean isValid(char c); } diff --git a/src/mightypork/utils/string/validation/CharFilterRegex.java b/src/mightypork/utils/string/validation/CharFilterRegex.java index 1272dbf..dc58303 100644 --- a/src/mightypork/utils/string/validation/CharFilterRegex.java +++ b/src/mightypork/utils/string/validation/CharFilterRegex.java @@ -2,19 +2,20 @@ package mightypork.utils.string.validation; public class CharFilterRegex implements CharFilter { - + private final String formula; - - - public CharFilterRegex(String regex) { + + + public CharFilterRegex(String regex) + { this.formula = regex; } - - + + @Override public boolean isValid(char c) { return Character.toString(c).matches(formula); } - + } diff --git a/src/mightypork/utils/string/validation/CharFilterWhitelist.java b/src/mightypork/utils/string/validation/CharFilterWhitelist.java index 5ab41e6..6a83f7f 100644 --- a/src/mightypork/utils/string/validation/CharFilterWhitelist.java +++ b/src/mightypork/utils/string/validation/CharFilterWhitelist.java @@ -2,19 +2,20 @@ package mightypork.utils.string.validation; public class CharFilterWhitelist implements CharFilter { - + private final String whitelist; - - - public CharFilterWhitelist(String allowed) { + + + public CharFilterWhitelist(String allowed) + { this.whitelist = allowed; } - - + + @Override public boolean isValid(char c) { return whitelist.contains(Character.toString(c)); } - + } diff --git a/src/mightypork/utils/string/validation/StringFilter.java b/src/mightypork/utils/string/validation/StringFilter.java index 79a883a..4d656c1 100644 --- a/src/mightypork/utils/string/validation/StringFilter.java +++ b/src/mightypork/utils/string/validation/StringFilter.java @@ -3,10 +3,10 @@ package mightypork.utils.string.validation; /** * Utility interface for string filters (accepting filepaths and similar) - * + * * @author Ondřej Hruška (MightyPork) */ public interface StringFilter { - + public boolean isValid(String entry); } diff --git a/src/mightypork/utils/struct/Mutable.java b/src/mightypork/utils/struct/Mutable.java index fdf1ad9..30aa004 100644 --- a/src/mightypork/utils/struct/Mutable.java +++ b/src/mightypork/utils/struct/Mutable.java @@ -3,56 +3,57 @@ package mightypork.utils.struct; /** * Mutable object - * + * * @author Ondřej Hruška (MightyPork) * @param type */ public class Mutable { - + /** The wrapped value */ private T o = null; - - + + /** * New mutable object - * + * * @param o value */ - public Mutable(T o) { + public Mutable(T o) + { this.o = o; } - - + + /** * Get the wrapped value - * + * * @return value */ public T get() { return o; } - - + + /** * Set value - * + * * @param o new value to set */ public void set(T o) { this.o = o; } - - + + @Override public String toString() { if (o == null) return ""; return o.toString(); } - - + + @Override public int hashCode() { @@ -61,8 +62,8 @@ public class Mutable { result = prime * result + ((o == null) ? 0 : o.hashCode()); return result; } - - + + @Override public boolean equals(Object obj) { diff --git a/src/mightypork/utils/struct/Pair.java b/src/mightypork/utils/struct/Pair.java index 0c04b96..757bb12 100644 --- a/src/mightypork/utils/struct/Pair.java +++ b/src/mightypork/utils/struct/Pair.java @@ -3,37 +3,38 @@ package mightypork.utils.struct; /** * Structure of 2 objects. - * + * * @author Ondřej Hruška (MightyPork) * @copy (c) 2012 * @param 1st object class * @param 2nd object class */ public class Pair { - + /** * 1st object */ public T1 first; - + /** * 2nd object */ public T2 second; - - + + /** * Make structure of 2 objects - * + * * @param first 1st object * @param second 2nd object */ - public Pair(T1 first, T2 second) { + public Pair(T1 first, T2 second) + { this.first = first; this.second = second; } - - + + /** * @return 1st object */ @@ -41,8 +42,8 @@ public class Pair { { return first; } - - + + /** * @return 2nd object */ @@ -50,8 +51,8 @@ public class Pair { { return second; } - - + + @Override public boolean equals(Object obj) { @@ -67,8 +68,8 @@ public class Pair { } else if (!second.equals(other.second)) return false; return true; } - - + + @Override public int hashCode() { @@ -78,12 +79,12 @@ public class Pair { result = prime * result + ((second == null) ? 0 : second.hashCode()); return result; } - - + + @Override public String toString() { return "PAIR{" + first + "," + second + "}"; } - + } diff --git a/src/mightypork/utils/struct/Triad.java b/src/mightypork/utils/struct/Triad.java index aa788ac..e200f4a 100644 --- a/src/mightypork/utils/struct/Triad.java +++ b/src/mightypork/utils/struct/Triad.java @@ -3,7 +3,7 @@ package mightypork.utils.struct; /** * Structure of 3 objects. - * + * * @author Ondřej Hruška (MightyPork) * @copy (c) 2012 * @param 1st object class @@ -11,26 +11,27 @@ package mightypork.utils.struct; * @param 3rd object class */ public class Triad extends Pair { - + /** * 3rd object */ public T3 third; - - + + /** * Make structure of 3 objects - * + * * @param objA 1st object * @param objB 2nd object * @param objC 3rd object */ - public Triad(T1 objA, T2 objB, T3 objC) { + public Triad(T1 objA, T2 objB, T3 objC) + { super(objA, objB); third = objC; } - - + + /** * @return 3rd object */ @@ -38,49 +39,49 @@ public class Triad extends Pair { { return third; } - - + + /** * Set 1st object - * + * * @param obj 1st object */ public void setThird(T3 obj) { third = obj; } - - + + @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (!(obj instanceof Triad)) return false; - + if (!super.equals(obj)) return false; - + final Triad other = (Triad) obj; - + if (third == null) { if (other.third != null) return false; } else if (!third.equals(other.third)) return false; - + return true; } - - + + @Override public int hashCode() { return super.hashCode() + (third == null ? 0 : third.hashCode()); } - - + + @Override public String toString() { return "TRIAD{" + first + "," + second + "," + third + "}"; } - + }