001/*
002 * ============================================================================
003 * Copyright © 2002-2023 by Thomas Thrien.
004 * All Rights Reserved.
005 * ============================================================================
006 * Licensed to the public under the agreements of the GNU Lesser General Public
007 * License, version 3.0 (the "License"). You may obtain a copy of the License at
008 *
009 *      http://www.gnu.org/licenses/lgpl.html
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
013 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
014 * License for the specific language governing permissions and limitations
015 * under the License.
016 */
017
018package org.tquadrat.foundation.value;
019
020import static java.lang.String.format;
021import static java.math.MathContext.DECIMAL128;
022import static java.util.Arrays.stream;
023import static org.apiguardian.api.API.Status.STABLE;
024import static org.tquadrat.foundation.lang.Objects.requireNotEmptyArgument;
025import static org.tquadrat.foundation.value.Length.FOOT;
026import static org.tquadrat.foundation.value.Length.KILOMETER;
027import static org.tquadrat.foundation.value.Length.MILE;
028import static org.tquadrat.foundation.value.Length.NAUTICAL_MILE;
029import static org.tquadrat.foundation.value.Time.HOUR;
030import static org.tquadrat.foundation.value.Time.SECOND;
031import static org.tquadrat.foundation.value.Time.WEEK;
032
033import java.math.BigDecimal;
034
035import org.apiguardian.api.API;
036import org.tquadrat.foundation.annotation.ClassVersion;
037import org.tquadrat.foundation.value.api.DimensionWithLinearConversion;
038
039/**
040 *  <p>{@summary The various instances of speed &hellip;}</p>
041 *  <p>Because speed is distance per time, the values for
042 *  {@link #factor()}
043 *  are calculated based on the values from
044 *  {@link Length#factor()}
045 *  and
046 *  {@link Time#factor()}.</p>
047 *
048 *  @extauthor Thomas Thrien - thomas.thrien@tquadrat.org
049 *  @version $Id: Speed.java 1072 2023-09-30 20:44:38Z tquadrat $
050 *  @since 0.0.4
051 *
052 *  @UMLGraph.link
053 */
054@SuppressWarnings( "NewClassNamingConvention" )
055@ClassVersion( sourceVersion = "$Id: Speed.java 1072 2023-09-30 20:44:38Z tquadrat $" )
056@API( status = STABLE, since = "0.0.4" )
057public enum Speed implements DimensionWithLinearConversion
058{
059        /*------------------*\
060    ====** Enum Declaration **=================================================
061        \*------------------*/
062    /**
063     *  <p>{@summary &#x00C5;ngström per Week.} This is by far not a useful
064     *  unit for speed, but it is the implementation of a famous instance of
065     *  Murphy's Laws:</p>
066     *  <cite>&quot;Units are always provided in the most impractical form, e.g.
067     *  a speed as &#x00C5;ngström per Week.&quot;</cite>
068     */
069    @SuppressWarnings( "NonAsciiCharacters" )
070    ÅNGSTRÖM_PER_WEEK( Length.ÅNGSTRÖM.factor().divide( WEEK.factor(), DECIMAL128 ), "Å/w" ),
071
072    /**
073     *  Feet per second.
074     */
075    FEET_PER_SECOND( FOOT.factor().divide( SECOND.factor(), DECIMAL128 ), "fps" ),
076
077    /**
078     *  Knot (nautical mile per hour).
079     */
080    KNOT( NAUTICAL_MILE.factor().divide( HOUR.factor(), DECIMAL128 ), "kn" ),
081
082    /**
083     *  Kilometer per hour.
084     */
085    KILOMETER_PER_HOUR( KILOMETER.factor().divide( HOUR.factor(), DECIMAL128 ), "km/h" ),
086
087    /**
088     *  Meter per second.
089     */
090    METER_PER_SECOND( BigDecimal.ONE, "m/s" ),
091
092    /**
093     *  Mile per hour.
094     */
095    MILE_PER_HOUR( MILE.factor().divide( HOUR.factor(), DECIMAL128 ), "mph" );
096
097        /*------------*\
098    ====** Attributes **=======================================================
099        \*------------*/
100    /**
101     *  The factor.
102     */
103    private final BigDecimal m_Factor;
104
105    /**
106     *  The unit symbol.
107     */
108    private final String m_UnitSymbol;
109
110        /*--------------*\
111    ====** Constructors **=====================================================
112        \*--------------*/
113    /**
114     *  Creates a new {@code Speed} instance.
115     *
116     *  @param  factor  The factor.
117     *  @param  unitSymbol  The unit symbol.
118     */
119    private Speed( final BigDecimal factor, final String unitSymbol )
120    {
121        m_Factor = factor.stripTrailingZeros();
122        m_UnitSymbol = unitSymbol;
123    }   //  Speed()
124
125        /*---------*\
126    ====** Methods **==========================================================
127        \*---------*/
128    /**
129     *  {@inheritDoc}
130     */
131    @Override
132    @SuppressWarnings( "unchecked" )
133    public final Speed baseUnit() { return METER_PER_SECOND; }
134
135    /**
136     *  {@inheritDoc}
137     */
138    @Override
139    public final BigDecimal factor() { return m_Factor; }
140
141    /**
142     *  Returns the {@code Speed} instance for the given unit.
143     *
144     *  @param  unitSymbol  The unit symbol.
145     *  @return The respective instance.
146     *  @throws IllegalArgumentException    The given unit is unknown.
147     */
148    public static final Speed forUnit( final String unitSymbol ) throws IllegalArgumentException
149    {
150        requireNotEmptyArgument( unitSymbol, "unit" );
151
152        final var retValue = stream( values() )
153            .filter( v -> v.unitSymbol().equals( unitSymbol ) )
154            .findFirst()
155            .orElseThrow( () -> new IllegalArgumentException( format( MSG_UnknownUnit, unitSymbol ) ) );
156
157        //---* Done *----------------------------------------------------------
158        return retValue;
159    }   //  forUnit()
160
161    /**
162     *  {@inheritDoc}
163     */
164    @Override
165    public final String unitSymbol() { return m_UnitSymbol; }
166}
167//  enum Speed
168
169/*
170 *  End of File
171 */