All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.praxislive.code.DefaultDelegateAPI Maven / Gradle / Ivy

Go to download

Forest-of-actors runtime supporting real-time systems and real-time recoding - bringing aspects of Erlang, Smalltalk and Extempore to Java.

There is a newer version: 6.0.0-beta1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2022 Neil C Smith.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version 3 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
 * version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License version 3
 * along with this work; if not, see http://www.gnu.org/licenses/
 *
 *
 * Please visit https://www.praxislive.org if you need additional information or
 * have any questions.
 */
package org.praxislive.code;

import java.util.concurrent.ThreadLocalRandom;
import org.praxislive.code.userapi.Property;
import org.praxislive.core.Value;
import org.praxislive.core.types.PArray;
import org.praxislive.core.types.PBoolean;
import org.praxislive.core.types.PNumber;
import org.praxislive.core.types.PString;

/**
 * Default delegate API for use as trait by delegate subclasses.
 */
public interface DefaultDelegateAPI {

    /**
     * Casting function to convert an object into a double value. If the value
     * is a {@link PNumber} the value will be extracted directly. If the value
     * is a {@link Property} the value will be extracted using
     * {@link Property#getDouble()}. All other types will be converted into a
     * Value (if necessary) and an attempt made to coerce into a PNumber.
     * Otherwise zero is returned.
     *
     * @param value object value to convert
     * @return value as double or zero
     */
    public default double D(Object value) {
        return D(value, 0);
    }

    /**
     * Casting function to convert an object into a double value. If the value
     * is a {@link PNumber} the value will be extracted directly. If the value
     * is a {@link Property} the value will be extracted using
     * {@link Property#getDouble(double)}. All other types will be converted
     * into a Value (if necessary) and an attempt made to coerce into a PNumber.
     * Otherwise the provided default is returned.
     *
     * @param value object value to convert
     * @param def default value
     * @return value as double or default value
     */
    public default double D(Object value, double def) {
        if (value instanceof PNumber) {
            return ((PNumber) value).value();
        } else if (value instanceof Property) {
            return ((Property) value).getDouble(def);
        } else {
            return PNumber.from(Value.ofObject(value))
                    .map(PNumber::value)
                    .orElse(def);
        }
    }

    /**
     * Casting function to convert an object into an int value. If the value is
     * a {@link PNumber} the value will be extracted directly. If the value is a
     * {@link Property} the value will be extracted using
     * {@link Property#getInt()}. All other types will be converted into a Value
     * (if necessary) and an attempt made to coerce into a PNumber. Otherwise
     * zero is returned.
     *
     * @param value object value to convert
     * @return value as int or zero
     */
    public default int I(Object value) {
        return I(value, 0);
    }

    /**
     * Casting function to convert an object into an int value. If the value is
     * a {@link PNumber} the value will be extracted directly. If the value is a
     * {@link Property} the value will be extracted using
     * {@link Property#getInt(int)}. All other types will be converted into a
     * Value (if necessary) and an attempt made to coerce into a PNumber.
     * Otherwise the provided default is returned.
     *
     * @param value object value to convert
     * @param def default value
     * @return value as int or default value
     */
    public default int I(Object value, int def) {
        if (value instanceof PNumber) {
            return ((PNumber) value).toIntValue();
        } else if (value instanceof Property) {
            return ((Property) value).getInt(def);
        } else {
            return PNumber.from(Value.ofObject(value))
                    .map(PNumber::toIntValue)
                    .orElse(def);
        }
    }

    /**
     * Casting function to convert an object into a boolean value. If the value
     * is a {@link PBoolean} the value will be extracted directly. If the value
     * is a {@link Property} the value will be extracted using
     * {@link Property#getBoolean()}. All other types will be converted into a
     * Value (if necessary) and an attempt made to coerce into a PBoolean.
     * Otherwise false is returned.
     *
     * @param value object value to convert
     * @return value as boolean or false
     */
    public default boolean B(Object value) {
        if (value instanceof PBoolean) {
            return ((PBoolean) value).value();
        } else if (value instanceof Property) {
            return ((Property) value).getBoolean();
        } else {
            return PBoolean.from(Value.ofObject(value))
                    .map(PBoolean::value)
                    .orElse(false);
        }
    }

    /**
     * Casting function to convert an object into a String value. If the value
     * is a {@link Property} the value is extracted and converted to a String.
     * Otherwise the value is converted to a String directly, which covers Value
     * and non-Value types. Null values are returned as an empty String.
     *
     * @param value object value to convert
     * @return value as String
     */
    public default String S(Object value) {
        if (value instanceof Property) {
            return ((Property) value).get().toString();
        } else {
            return value == null ? "" : value.toString();
        }
    }

    /**
     * Casting function to convert an object into an appropriate Value subtype.
     * If the input is already a Value it is returned directly. If the input is
     * a {@link Property} the value is extracted using {@link Property#get()}.
     * Otherwise the input is converted using
     * {@link Value#ofObject(java.lang.Object)}.
     *
     * @param value object value to convert
     * @return value as Value subtype
     */
    public default Value V(Object value) {
        if (value instanceof Value) {
            return (Value) value;
        } else if (value instanceof Property) {
            return ((Property) value).get();
        } else {
            return Value.ofObject(value);
        }
    }

    /**
     * Attempt to extract a {@link PArray} from the given Property. An empty
     * PArray will be returned if the property's value is not a PArray and
     * cannot be coerced.
     *
     * @see #array(org.praxislive.core.types.Value)
     *
     * @param p
     * @return
     */
    public default PArray array(Property p) {
        return PArray.from(p.get()).orElse(PArray.EMPTY);
    }

    /**
     * Convert the given Value into a {@link PArray}. If the Value is already a
     * PArray it will be returned, otherwise an attempt will be made to coerce
     * it. If the Value cannot be converted, an empty PArray will be returned.
     *
     * @param s
     * @return
     */
    public default PArray array(Value v) {
        return PArray.from(v).orElse(PArray.EMPTY);
    }

    /**
     * Parse the given String into a {@link PArray}. If the String is not a
     * valid representation of an array, returns an empty PArray.
     *
     * @param s
     * @return
     */
    public default PArray array(String s) {
        return array(PString.of(s));
    }

    /**
     * Return a random number between zero and max (exclusive)
     *
     * @param max the upper bound of the range
     * @return
     */
    public default double random(double max) {
//        return RND.nextDouble() * max;
        return ThreadLocalRandom.current().nextDouble(max);
    }

    /**
     * Return a random number between min (inclusive) and max (exclusive)
     *
     * @param min the lower bound of the range
     * @param max the upper bound of the range
     * @return
     */
    public default double random(double min, double max) {
        if (min >= max) {
            return min;
        }
        return ThreadLocalRandom.current().nextDouble(min, max);
    }

    /**
     * Return a random element from an array of values.
     *
     * @param values list of values, may not be empty
     * @return random element
     */
    public default double randomOf(double... values) {
        return values[ThreadLocalRandom.current().nextInt(values.length)];
    }

    /**
     * Return a random element from an array of values.
     *
     * @param values list of values, may not be empty
     * @return random element
     */
    public default int randomOf(int... values) {
        return values[ThreadLocalRandom.current().nextInt(values.length)];
    }

    /**
     * Return a random element from an array of values.
     *
     * @param values list of values, may not be empty
     * @return random element
     */
    public default String randomOf(String... values) {
        return values[ThreadLocalRandom.current().nextInt(values.length)];
    }

    /**
     * Calculate the absolute value of the given value. If the value is
     * positive, the value is returned. If the value is negative, the negation
     * of the value is returned.
     *
     * @param n
     * @return
     */
    public default double abs(double n) {
        return Math.abs(n);
    }

    /**
     * Calculate the square of the given value.
     *
     * @param a
     * @return
     */
    public default double sq(double a) {
        return a * a;
    }

    /**
     * Calculate the square root of the given value.
     *
     * @see Math#sqrt(double)
     *
     * @param a
     * @return
     */
    public default double sqrt(double a) {
        return Math.sqrt(a);
    }

    /**
     * Calculate the natural logarithm if the given value.
     *
     * @see Math#log(double)
     *
     * @param a
     * @return
     */
    public default double log(double a) {
        return Math.log(a);
    }

    /**
     * Calculate Euler's number raised to the power of the given value.
     *
     * @see Math#exp(double)
     *
     * @param a
     * @return
     */
    public default double exp(double a) {
        return Math.exp(a);
    }

    /**
     * Calculate the value of the first argument raised to the power of the
     * second argument.
     *
     * @see Math#pow(double, double)
     *
     * @param a the base
     * @param b the exponent
     * @return the value ab
     */
    public default double pow(double a, double b) {
        return Math.pow(a, b);
    }

    /**
     * Calculate the maximum of two values.
     *
     * @param a
     * @param b
     * @return
     */
    public default int max(int a, int b) {
        return Math.max(a, b);
    }

    /**
     * Calculate the maximum of three values.
     *
     * @param a
     * @param b
     * @param c
     * @return
     */
    public default int max(int a, int b, int c) {
        return Math.max(a, Math.max(b, c));
    }

    /**
     * Calculate the maximum value in the provided array.
     *
     * @param values value list - must not be empty
     * @return maximum value
     */
    public default int max(int... values) {
        if (values.length == 0) {
            throw new ArrayIndexOutOfBoundsException();
        }
        int value = values[0];
        for (int i = 1; i < values.length; i++) {
            value = Math.max(value, values[i]);
        }
        return value;
    }

    /**
     * Calculate the maximum of two values.
     *
     * @param a
     * @param b
     * @return
     */
    public default double max(double a, double b) {
        return Math.max(a, b);
    }

    /**
     * Calculate the maximum of three values.
     *
     * @param a
     * @param b
     * @param c
     * @return
     */
    public default double max(double a, double b, double c) {
        return Math.max(a, Math.max(b, c));
    }

    /**
     * Calculate the maximum value in the provided array.
     *
     * @param values value list - must not be empty
     * @return maximum value
     */
    public default double max(double... values) {
        if (values.length == 0) {
            throw new ArrayIndexOutOfBoundsException();
        }
        double value = values[0];
        for (int i = 1; i < values.length; i++) {
            value = Math.max(value, values[i]);
        }
        return value;
    }

    /**
     * Calculate the minimum of two values.
     *
     * @param a
     * @param b
     * @return
     */
    public default int min(int a, int b) {
        return Math.min(a, b);
    }

    /**
     * Calculate the minimum of three values.
     *
     * @param a
     * @param b
     * @param c
     * @return
     */
    public default int min(int a, int b, int c) {
        return Math.min(a, Math.min(b, c));
    }

    /**
     * Calculate the minimum value in the provided array.
     *
     * @param values value list - must not be empty
     * @return minimum value
     */
    public default int min(int... values) {
        if (values.length == 0) {
            throw new ArrayIndexOutOfBoundsException();
        }
        int value = values[0];
        for (int i = 1; i < values.length; i++) {
            value = Math.min(value, values[i]);
        }
        return value;
    }

    /**
     * Calculate the minimum of two values.
     *
     * @param a
     * @param b
     * @return
     */
    public default double min(double a, double b) {
        return Math.min(a, b);
    }

    /**
     * Calculate the minimum of three values.
     *
     * @param a
     * @param b
     * @param c
     * @return
     */
    public default double min(double a, double b, double c) {
        return Math.min(a, Math.min(b, c));
    }

    /**
     * Calculate the minimum value in the provided array.
     *
     * @param values value list - must not be empty
     * @return minimum value
     */
    public default double min(double... values) {
        if (values.length == 0) {
            throw new ArrayIndexOutOfBoundsException();
        }
        double value = values[0];
        for (int i = 1; i < values.length; i++) {
            value = Math.min(value, values[i]);
        }
        return value;
    }

    /**
     * Constrain a value between the range of the given low and high values.
     *
     * @param amt input value
     * @param low lowest allowed value
     * @param high highest allowed value
     * @return constrained value
     */
    public default int constrain(int amt, int low, int high) {
        return (amt < low) ? low : ((amt > high) ? high : amt);
    }

    /**
     * Constrain a value between the range of the given low and high values.
     *
     * @param amt input value
     * @param low lowest allowed value
     * @param high highest allowed value
     * @return constrained value
     */
    public default double constrain(double amt, double low, double high) {
        return (amt < low) ? low : ((amt > high) ? high : amt);
    }

    /**
     * Round a value to the nearest integer.
     *
     * @param amt input value
     * @return rounded value
     */
    public default int round(double amt) {
        return Math.round((float) amt);
    }

    /**
     * Converts an angle in radians to an angle in degrees.
     *
     * @see Math#toDegrees(double)
     *
     * @param radians
     * @return
     */
    public default double degrees(double radians) {
        return Math.toDegrees(radians);
    }

    /**
     * Converts an angle in degrees to an angle in radians.
     *
     * @see Math#toRadians(double)
     *
     * @param degrees
     * @return
     */
    public default double radians(double degrees) {
        return Math.toRadians(degrees);
    }

    /**
     * Returns the trigonometric sine of an angle
     *
     * @see Math#sin(double)
     *
     * @param angle
     * @return
     */
    public default double sin(double angle) {
        return Math.sin(angle);
    }

    /**
     * Returns the trigonometric cosine of an angle.
     *
     * @see Math#cos(double)
     *
     * @param angle
     * @return
     */
    public default double cos(double angle) {
        return Math.cos(angle);
    }

    /**
     * Returns the trigonometric tangent of an angle.
     *
     * @see Math#tan(double)
     *
     * @param angle
     * @return
     */
    public default double tan(double angle) {
        return Math.tan(angle);
    }

    /**
     * Returns the arc sine of a value.
     *
     * @see Math#asin(double)
     *
     * @param value
     * @return
     */
    public default double asin(double value) {
        return Math.asin(value);
    }

    /**
     * Returns the arc cosine of a value.
     *
     * @see Math#acos(double)
     *
     * @param value
     * @return
     */
    public default double acos(double value) {
        return Math.acos(value);
    }

    /**
     * Returns the arc tangent of a value.
     *
     * @see Math#atan(double)
     *
     * @param value
     * @return
     */
    public default double atan(double value) {
        return Math.atan(value);
    }

    /**
     * Returns the angle theta from the conversion of rectangular coordinates
     * (x, y) to polar coordinates (r, theta).
     *
     * @see Math#atan2(double, double)
     *
     * @param y
     * @param x
     * @return
     */
    public default double atan2(double y, double x) {
        return Math.atan2(y, x);
    }

    /**
     * Re-map (scale) an input value from one range to another. Numbers outside
     * the range are not clamped.
     *
     * @param value the value to be converted
     * @param start1 lower bound of the value's current range
     * @param stop1 upper bound of the value's current range
     * @param start2 lower bound of the value's target range
     * @param stop2 upper bound of the value's target range
     * @return
     */
    public default double map(double value,
            double start1, double stop1,
            double start2, double stop2) {
        return start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
    }

    /**
     * Calculates the distance between two points.
     *
     * @return
     * @param x1 x-coordinate of the first point
     * @param y1 y-coordinate of the first point
     * @param x2 x-coordinate of the second point
     * @param y2 y-coordinate of the second point
     */
    public default double dist(double x1, double y1, double x2, double y2) {
        return sqrt(sq(x2 - x1) + sq(y2 - y1));
    }

    /**
     * Calculates the distance between two points.
     *
     * @return
     * @param x1 x-coordinate of the first point
     * @param y1 y-coordinate of the first point
     * @param z1 z-coordinate of the first point
     * @param x2 x-coordinate of the second point
     * @param y2 y-coordinate of the second point
     * @param z2 z-coordinate of the second point
     */
    public default double dist(double x1, double y1, double z1,
            double x2, double y2, double z2) {
        return sqrt(sq(x2 - x1) + sq(y2 - y1) + sq(z2 - z1));
    }

    /**
     * Calculates a number between two numbers at a specific increment. The
     * amt parameter is the amount to interpolate between the two values
     * where 0.0 equal to the first point, 0.1 is very near the first point, 0.5
     * is half-way in between, etc. The lerp function is convenient for creating
     * motion along a straight path and for drawing dotted lines.
     *
     * @return
     * @param start first value
     * @param stop second value
     * @param amt between 0.0 and 1.0
     */
    public default double lerp(double start, double stop, double amt) {
        return start + (stop - start) * amt;
    }

    /**
     * Normalizes a number from another range into a value between 0 and 1.
     * 

* Identical to map(value, low, high, 0, 1); *

* Numbers outside the range are not clamped to 0 and 1, because * out-of-range values are often intentional and useful. * * @return * @param value the incoming value to be converted * @param start lower bound of the value's current range * @param stop upper bound of the value's current range */ public default double norm(double value, double start, double stop) { return (value - start) / (stop - start); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy